diff --git a/src/RPGCore.Behaviour/Manifest/FieldInformation.cs b/src/RPGCore.Behaviour/Manifest/FieldInformation.cs index 4de0d76c..bf091920 100644 --- a/src/RPGCore.Behaviour/Manifest/FieldInformation.cs +++ b/src/RPGCore.Behaviour/Manifest/FieldInformation.cs @@ -1,4 +1,5 @@ using Newtonsoft.Json.Linq; +using System; using System.Collections; using System.Reflection; @@ -13,9 +14,70 @@ public sealed class FieldInformation public FieldFormat Format; public FieldInformation ValueFormat; + public abstract class ModelMember + { + public abstract Type ValueType { get; } + public abstract object[] GetCustomAttributes(bool inherit); + public abstract object GetValue(object instance); + } + + public class ModelField : ModelMember + { + public FieldInfo Field { get; } + + public override Type ValueType => Field.FieldType; + + public ModelField(FieldInfo field) + { + Field = field; + } + + public override object[] GetCustomAttributes(bool inherit) + { + return Field.GetCustomAttributes(inherit); + } + + public override object GetValue(object instance) + { + return Field.GetValue(instance); + } + } + + public class ModelProperty : ModelMember + { + public PropertyInfo Property { get; } + + public override Type ValueType => Property.PropertyType; + + public ModelProperty(PropertyInfo property) + { + Property = property; + } + + public override object[] GetCustomAttributes(bool inherit) + { + return Property.GetCustomAttributes(inherit); + } + + public override object GetValue(object instance) + { + return Property.GetValue(instance); + } + } + public static FieldInformation ConstructFieldInformation(FieldInfo field, object defaultInstance) { - object[] attributes = field.GetCustomAttributes(false); + return ConstructFieldInformation(new ModelField(field), defaultInstance); + } + + public static FieldInformation ConstructFieldInformation(PropertyInfo property, object defaultInstance) + { + return ConstructFieldInformation(new ModelProperty(property), defaultInstance); + } + + public static FieldInformation ConstructFieldInformation(ModelMember member, object defaultInstance) + { + object[] attributes = member.GetCustomAttributes(false); string[] attributeIds = new string[attributes.Length]; for (int i = 0; i < attributes.Length; i++) { @@ -23,7 +85,7 @@ public static FieldInformation ConstructFieldInformation(FieldInfo field, object } FieldInformation fieldInformation; - if (typeof(InputSocket).IsAssignableFrom(field.FieldType)) + if (typeof(InputSocket).IsAssignableFrom(member.ValueType)) { fieldInformation = new FieldInformation() { @@ -39,10 +101,10 @@ public static FieldInformation ConstructFieldInformation(FieldInfo field, object if (defaultInstance != null) { - defaultValue = field.GetValue(defaultInstance); + defaultValue = member.GetValue(defaultInstance); } - string typeName = field.FieldType.Name; + string typeName = member.ValueType.Name; try { @@ -65,20 +127,20 @@ public static FieldInformation ConstructFieldInformation(FieldInfo field, object }; } - if (typeof(IDictionary).IsAssignableFrom(field.FieldType)) + if (typeof(IDictionary).IsAssignableFrom(member.ValueType)) { fieldInformation.Format = FieldFormat.Dictionary; - fieldInformation.Type = field.FieldType.GetGenericArguments()[1].Name; + fieldInformation.Type = member.ValueType.GetGenericArguments()[1].Name; fieldInformation.ValueFormat = new FieldInformation() { - Type = field.FieldType.GetGenericArguments()[1].Name, + Type = member.ValueType.GetGenericArguments()[1].Name, Format = FieldFormat.Object }; } - else if (field.FieldType.IsArray) + else if (member.ValueType.IsArray) { - var elementType = field.FieldType.GetElementType(); + var elementType = member.ValueType.GetElementType(); fieldInformation.Format = FieldFormat.List; fieldInformation.Type = elementType.Name; diff --git a/src/RPGCore.Behaviour/Manifest/TypeInformation.cs b/src/RPGCore.Behaviour/Manifest/TypeInformation.cs index 571db6f9..7ca338e9 100644 --- a/src/RPGCore.Behaviour/Manifest/TypeInformation.cs +++ b/src/RPGCore.Behaviour/Manifest/TypeInformation.cs @@ -75,6 +75,30 @@ protected static void ConstructTypeInformation(Type type, TypeInformation typeIn fieldInfos.Add(field.Name, FieldInformation.ConstructFieldInformation(field, defaultInstance)); } + foreach (var field in type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)) + { + if (field.PropertyType == typeof(OutputSocket)) + { + continue; + } + + if (field.GetCustomAttribute() != null) + { + continue; + } + + var getter = field.GetGetMethod(); + var setter = field.GetSetMethod(); + + if (getter == null + || getter.IsPrivate + || setter == null) + { + continue; + } + + fieldInfos.Add(field.Name, FieldInformation.ConstructFieldInformation(field, defaultInstance)); + } typeInformation.Fields = fieldInfos; } } diff --git a/src/RPGCore.Demo.BoardGame/GamePlayer.cs b/src/RPGCore.Demo.BoardGame/GamePlayer.cs index df85eef1..63474400 100644 --- a/src/RPGCore.Demo.BoardGame/GamePlayer.cs +++ b/src/RPGCore.Demo.BoardGame/GamePlayer.cs @@ -4,7 +4,6 @@ namespace RPGCore.Demo.BoardGame { - public class GamePlayer { public LocalId OwnerId; diff --git a/src/RPGCore.Demo.BoardGame/GameView.cs b/src/RPGCore.Demo.BoardGame/GameView.cs index 38729c48..9a48b2ca 100644 --- a/src/RPGCore.Demo.BoardGame/GameView.cs +++ b/src/RPGCore.Demo.BoardGame/GameView.cs @@ -1,5 +1,4 @@ using RPGCore.Behaviour; -using RPGCore.Demo.BoardGame.Models; using RPGCore.Packages; using RPGCore.Traits; using System.Collections.Generic; diff --git a/src/RPGCore.Demo.BoardGame/Models/BuildingTemplate.cs b/src/RPGCore.Demo.BoardGame/Models/BuildingTemplate.cs index f867e2ca..1c21fbb3 100644 --- a/src/RPGCore.Demo.BoardGame/Models/BuildingTemplate.cs +++ b/src/RPGCore.Demo.BoardGame/Models/BuildingTemplate.cs @@ -1,20 +1,26 @@ -using RPGCore.Behaviour; +using Newtonsoft.Json; +using RPGCore.Behaviour; using System.Collections.Generic; namespace RPGCore.Demo.BoardGame.Models { public class BuildingTemplate { - public string DisplayName; + public string DisplayName { get; set; } + public string BodyText { get; set; } - public string[,] Recipe; + public string[,] Recipe { get; set; } - public SerializedGraph GlobalEffectGraph; - public SerializedGraph LocalEffectGraph; + public SerializedGraph GlobalEffectGraph { get; set; } + public SerializedGraph LocalEffectGraph { get; set; } + [JsonIgnore] public int Width => Recipe?.GetLength(0) ?? 0; + + [JsonIgnore] public int Height => Recipe?.GetLength(1) ?? 0; + [JsonIgnore] public bool IsHorizontallySymmetric { get @@ -42,6 +48,7 @@ public bool IsHorizontallySymmetric } } + [JsonIgnore] public bool IsVerticallySymmetric { get @@ -69,6 +76,7 @@ public bool IsVerticallySymmetric } } + [JsonIgnore] public bool IsRotating { get @@ -85,6 +93,7 @@ public bool IsRotating } } + [JsonIgnore] private bool IsTheSameWhenRotated { get @@ -116,6 +125,7 @@ private bool IsTheSameWhenRotated } } + [JsonIgnore] private bool IsRotatedSameAsMirror { get diff --git a/src/RPGCore.Demo.BoardGame/Models/ResourceTemplate.cs b/src/RPGCore.Demo.BoardGame/Models/ResourceTemplate.cs index cade5508..d8e6ad12 100644 --- a/src/RPGCore.Demo.BoardGame/Models/ResourceTemplate.cs +++ b/src/RPGCore.Demo.BoardGame/Models/ResourceTemplate.cs @@ -2,6 +2,7 @@ { public class ResourceTemplate { - public string DisplayName; + public string DisplayName { get; set; } + public VoxelColour Colour { get; set; } } } diff --git a/src/RPGCore.Demo.BoardGame/Models/VoxelColour.cs b/src/RPGCore.Demo.BoardGame/Models/VoxelColour.cs new file mode 100644 index 00000000..61ca2075 --- /dev/null +++ b/src/RPGCore.Demo.BoardGame/Models/VoxelColour.cs @@ -0,0 +1,9 @@ +namespace RPGCore.Demo.BoardGame.Models +{ + public struct VoxelColour + { + public float Red { get; set; } + public float Green { get; set; } + public float Blue { get; set; } + } +} diff --git a/src/RPGCore.Demo.BoardGame/SpecialCardSlot.cs b/src/RPGCore.Demo.BoardGame/SpecialCardSlot.cs index f9f1e355..79909afd 100644 --- a/src/RPGCore.Demo.BoardGame/SpecialCardSlot.cs +++ b/src/RPGCore.Demo.BoardGame/SpecialCardSlot.cs @@ -2,7 +2,7 @@ { public class SpecialCardSlot { - public string BuildingIdentifier; + public string BuildingIdentifier { get; set; } } } diff --git a/src/RPGCoreUnity/Assets/Demos/BoardGame/Plugins/RPGCore.Demo.BoardGame.dll b/src/RPGCoreUnity/Assets/Demos/BoardGame/Plugins/RPGCore.Demo.BoardGame.dll index b177acd3..2e3d0f01 100644 Binary files a/src/RPGCoreUnity/Assets/Demos/BoardGame/Plugins/RPGCore.Demo.BoardGame.dll and b/src/RPGCoreUnity/Assets/Demos/BoardGame/Plugins/RPGCore.Demo.BoardGame.dll differ diff --git a/src/RPGCoreUnity/Assets/Demos/BoardGame/Plugins/RPGCore.Demo.BoardGame.pdb b/src/RPGCoreUnity/Assets/Demos/BoardGame/Plugins/RPGCore.Demo.BoardGame.pdb index aa775c47..53d88f54 100644 Binary files a/src/RPGCoreUnity/Assets/Demos/BoardGame/Plugins/RPGCore.Demo.BoardGame.pdb and b/src/RPGCoreUnity/Assets/Demos/BoardGame/Plugins/RPGCore.Demo.BoardGame.pdb differ diff --git a/src/RPGCoreUnity/Assets/RPGCore/Plugins/RPGCore.Behaviour.dll b/src/RPGCoreUnity/Assets/RPGCore/Plugins/RPGCore.Behaviour.dll index 377f1f55..832da685 100644 Binary files a/src/RPGCoreUnity/Assets/RPGCore/Plugins/RPGCore.Behaviour.dll and b/src/RPGCoreUnity/Assets/RPGCore/Plugins/RPGCore.Behaviour.dll differ diff --git a/src/RPGCoreUnity/Assets/RPGCore/Plugins/RPGCore.Behaviour.pdb b/src/RPGCoreUnity/Assets/RPGCore/Plugins/RPGCore.Behaviour.pdb index 1cc7efae..07ad17f6 100644 Binary files a/src/RPGCoreUnity/Assets/RPGCore/Plugins/RPGCore.Behaviour.pdb and b/src/RPGCoreUnity/Assets/RPGCore/Plugins/RPGCore.Behaviour.pdb differ diff --git a/src/RPGCoreUnity/Assets/RPGCore/Scripts/Editors/Behaviour/RPGCoreEditor.cs b/src/RPGCoreUnity/Assets/RPGCore/Scripts/Editors/Behaviour/RPGCoreEditor.cs index e7ecc606..8a2bac19 100644 --- a/src/RPGCoreUnity/Assets/RPGCore/Scripts/Editors/Behaviour/RPGCoreEditor.cs +++ b/src/RPGCoreUnity/Assets/RPGCore/Scripts/Editors/Behaviour/RPGCoreEditor.cs @@ -8,6 +8,8 @@ namespace RPGCore.Unity.Editors { public static class RPGCoreEditor { + const int FoldoutIndent = -10; + public static void DrawEditor(EditorSession editor) { if (editor == null) @@ -30,9 +32,11 @@ public static void DrawField(EditorField field) { var fieldFeature = field.GetOrCreateFeature(); - EditorGUI.indentLevel--; - fieldFeature.Expanded = EditorGUILayout.Foldout(fieldFeature.Expanded, field.Name, true); - EditorGUI.indentLevel++; + var fieldRect = GUILayoutUtility.GetRect(0, EditorGUIUtility.singleLineHeight, GUILayout.ExpandWidth(true)); + GUILayout.Space(EditorGUIUtility.standardVerticalSpacing); + fieldRect.xMin += FoldoutIndent; + + fieldFeature.Expanded = EditorGUI.Foldout(fieldRect, fieldFeature.Expanded, field.Name, true); if (fieldFeature.Expanded) { @@ -64,6 +68,26 @@ public static void DrawField(EditorField field) field.ApplyModifiedProperties(); } } + else if (field.Field.Type == "Single") + { + EditorGUI.BeginChangeCheck(); + float newValue = EditorGUILayout.FloatField(field.Name, field.GetValue()); + if (EditorGUI.EndChangeCheck()) + { + field.SetValue(newValue); + field.ApplyModifiedProperties(); + } + } + else if(field.Field.Type == "Double") + { + EditorGUI.BeginChangeCheck(); + double newValue = EditorGUILayout.DoubleField(field.Name, field.GetValue()); + if (EditorGUI.EndChangeCheck()) + { + field.SetValue(newValue); + field.ApplyModifiedProperties(); + } + } else if (field.Field.Type == "String") { EditorGUI.BeginChangeCheck(); @@ -110,12 +134,13 @@ public static void DrawField(EditorField field) } var fieldRect = GUILayoutUtility.GetRect(0, EditorGUIUtility.singleLineHeight, GUILayout.ExpandWidth(true)); - PrefixLable(fieldRect, out var lable, out var content); - content.width = 140; + GUILayout.Space(EditorGUIUtility.standardVerticalSpacing); + fieldRect.xMin += 4; + var buttonRect = EditorGUI.PrefixLabel(fieldRect, new GUIContent(field.Name)); - EditorGUI.LabelField(lable, field.Name); + buttonRect.width = 160; - if (GUI.Button(content, $"Edit Graph")) + if (GUI.Button(buttonRect, $"Edit Graph")) { BehaviourEditor.Open(field.Session, field); } @@ -138,9 +163,11 @@ public static void DrawField(EditorField field) { var fieldFeature = field.GetOrCreateFeature(); - EditorGUI.indentLevel--; - fieldFeature.Expanded = EditorGUILayout.Foldout(fieldFeature.Expanded, field.Name, true); - EditorGUI.indentLevel++; + var fieldRect = GUILayoutUtility.GetRect(0, EditorGUIUtility.singleLineHeight, GUILayout.ExpandWidth(true)); + fieldRect.xMin += FoldoutIndent; + GUILayout.Space(EditorGUIUtility.standardVerticalSpacing); + + fieldFeature.Expanded = EditorGUI.Foldout(fieldRect, fieldFeature.Expanded, field.Name, true); if (fieldFeature.Expanded) { @@ -158,18 +185,5 @@ public static void DrawField(EditorField field) EditorGUILayout.LabelField(field.Name, "Unknown Type"); } } - - public static void PrefixLable (Rect position, out Rect lable, out Rect content) - { - content = EditorGUI.PrefixLabel (position, new GUIContent (" ")); - - float indent = EditorGUI.indentLevel * 15.0f; - position.xMin += indent; - - lable = new Rect (position) - { - xMax = content.xMin - }; - } } } diff --git a/src/RPGCoreUnity/Assets/RPGCore/Scripts/Editors/Packages/EditorSessionFrame.cs b/src/RPGCoreUnity/Assets/RPGCore/Scripts/Editors/Packages/EditorSessionFrame.cs index b38aaca0..bc66e6c9 100644 --- a/src/RPGCoreUnity/Assets/RPGCore/Scripts/Editors/Packages/EditorSessionFrame.cs +++ b/src/RPGCoreUnity/Assets/RPGCore/Scripts/Editors/Packages/EditorSessionFrame.cs @@ -76,6 +76,7 @@ public EditorSessionFrame(IResource resource) typeof(PackageNodeEditor), typeof(PackageNodePosition), typeof(ExtraData), + typeof(VoxelColour), typeof(ResourceTemplate), typeof(BuildingTemplate), @@ -109,6 +110,7 @@ public override void OnGUI() { if (Resource is ProjectResource projectResource) { + EditorGUILayout.BeginHorizontal(EditorStyles.toolbar); if (GUILayout.Button("Save", EditorStyles.toolbarButton, GUILayout.Width(100))) { using (var file = projectResource.WriteStream()) @@ -122,6 +124,12 @@ public override void OnGUI() ); } } + + if (GUILayout.Button("View Manifest", EditorStyles.toolbarButton, GUILayout.Width(120))) + { + GenericWindow.Open(new GUIContent("Manifest"), new JsonTextWindowFrame(EditorSession.Manifest.ToString())); + } + EditorGUILayout.EndHorizontal(); } RPGCoreEditor.DrawEditor(EditorSession); diff --git a/src/RPGCoreUnity/Assets/RPGCore/Scripts/Editors/Packages/Frames/JsonTextWindowFrame.cs b/src/RPGCoreUnity/Assets/RPGCore/Scripts/Editors/Packages/Frames/JsonTextWindowFrame.cs index fe2bded6..4362c65e 100644 --- a/src/RPGCoreUnity/Assets/RPGCore/Scripts/Editors/Packages/Frames/JsonTextWindowFrame.cs +++ b/src/RPGCoreUnity/Assets/RPGCore/Scripts/Editors/Packages/Frames/JsonTextWindowFrame.cs @@ -26,7 +26,13 @@ protected override string[] BuildLines(IResource resource) } string allLines = jobject.ToString(Formatting.Indented); + string[] builtLines = HighlightSyntax(allLines); + return builtLines; + } + + private static string[] HighlightSyntax(string allLines) + { string[] builtLines = allLines.Split(new char[] { '\n' }, System.StringSplitOptions.None); var sb = new StringBuilder(); @@ -101,5 +107,10 @@ public JsonTextWindowFrame(IResource resource) : base(resource) { } + + public JsonTextWindowFrame(string text) + : base(HighlightSyntax(text)) + { + } } } diff --git a/src/RPGCoreUnity/Assets/RPGCore/Scripts/Editors/Packages/Frames/RawTextWindowFrame.cs b/src/RPGCoreUnity/Assets/RPGCore/Scripts/Editors/Packages/Frames/RawTextWindowFrame.cs index daadcb23..499d3378 100644 --- a/src/RPGCoreUnity/Assets/RPGCore/Scripts/Editors/Packages/Frames/RawTextWindowFrame.cs +++ b/src/RPGCoreUnity/Assets/RPGCore/Scripts/Editors/Packages/Frames/RawTextWindowFrame.cs @@ -27,6 +27,11 @@ public RawTextWindowFrame(IResource resource) } } + public RawTextWindowFrame(string[] lines) + { + this.lines = lines; + } + protected virtual string[] BuildLines(IResource resource) { var linesList = new List(); @@ -87,7 +92,7 @@ public override void OnGUI() new GUIContent(guideString), out _, out float maxWidth); - var rect = GUILayoutUtility.GetRect(0, 480, GUILayout.ExpandWidth(true)); + var rect = GUILayoutUtility.GetRect(0, 480, GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true)); var lineNumberBackgroundRect = new Rect( rect.x, rect.y, diff --git a/src/RPGCoreUnity/Assets/RPGCore/Scripts/Editors/Packages/GenericWindow.cs b/src/RPGCoreUnity/Assets/RPGCore/Scripts/Editors/Packages/GenericWindow.cs new file mode 100644 index 00000000..1bc45960 --- /dev/null +++ b/src/RPGCoreUnity/Assets/RPGCore/Scripts/Editors/Packages/GenericWindow.cs @@ -0,0 +1,45 @@ +using RPGCore.Behaviour.Editor; +using UnityEditor; +using UnityEngine; + +namespace RPGCore.Unity.Editors +{ + public class GenericWindow : EditorWindow + { + public GUIContent WindowTitle; + private WindowFrame Frame; + + public static void Open(GUIContent title, WindowFrame frame) + { + var window = CreateWindow(); + + window.Show(); + + window.WindowTitle = title; + window.Frame = frame; + window.Frame.Window = window; + window.Frame.OnEnable(); + } + + private void OnEnable() + { + if (Frame != null) + { + Frame.Window = this; + Frame.OnEnable(); + } + titleContent = WindowTitle; + } + + private void OnGUI() + { + if (Frame == null) + { + Close(); + return; + } + + Frame.OnGUI(); + } + } +} diff --git a/src/RPGCoreUnity/Assets/RPGCore/Scripts/Editors/Packages/GenericWindow.cs.meta b/src/RPGCoreUnity/Assets/RPGCore/Scripts/Editors/Packages/GenericWindow.cs.meta new file mode 100644 index 00000000..baa17e00 --- /dev/null +++ b/src/RPGCoreUnity/Assets/RPGCore/Scripts/Editors/Packages/GenericWindow.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6f117a6ffba5a964ab4d7c4d9735a2fb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/RPGCoreUnity/Content/BoardGame/buildings/greenhouse.json b/src/RPGCoreUnity/Content/BoardGame/buildings/greenhouse.json index c44c9d95..ea30008f 100644 --- a/src/RPGCoreUnity/Content/BoardGame/buildings/greenhouse.json +++ b/src/RPGCoreUnity/Content/BoardGame/buildings/greenhouse.json @@ -11,8 +11,8 @@ }, "Editor": { "Position": { - "x": -112, - "y": 51 + "x": 20, + "y": 178 } } }, @@ -24,8 +24,8 @@ }, "Editor": { "Position": { - "x": 188, - "y": -27 + "x": 344, + "y": 95 } } }, @@ -37,8 +37,8 @@ }, "Editor": { "Position": { - "x": -111, - "y": -81 + "x": 20, + "y": 51 } } }, @@ -50,8 +50,8 @@ }, "Editor": { "Position": { - "x": -103, - "y": 169 + "x": 190, + "y": 291 } } }, @@ -63,8 +63,8 @@ }, "Editor": { "Position": { - "x": 475, - "y": 33 + "x": 652, + "y": 161 } } } @@ -74,5 +74,6 @@ "LocalEffectGraph": { "Nodes": null, "SubGraphs": null - } + }, + "BodyText": null } \ No newline at end of file diff --git a/src/RPGCoreUnity/Content/BoardGame/resources/glass.json b/src/RPGCoreUnity/Content/BoardGame/resources/glass.json index 510ba1c6..61f3711f 100644 --- a/src/RPGCoreUnity/Content/BoardGame/resources/glass.json +++ b/src/RPGCoreUnity/Content/BoardGame/resources/glass.json @@ -1,3 +1,8 @@ { - "DisplayName": "Glass" + "DisplayName": "Glass", + "Colour": { + "Red": 0.0, + "Green": 0.0, + "Blue": 0.0 + } } \ No newline at end of file diff --git a/src/RPGCoreUnity/Content/BoardGame/resources/wood.json b/src/RPGCoreUnity/Content/BoardGame/resources/wood.json index a9b02187..29a7ac8f 100644 --- a/src/RPGCoreUnity/Content/BoardGame/resources/wood.json +++ b/src/RPGCoreUnity/Content/BoardGame/resources/wood.json @@ -1,3 +1,8 @@ { - "DisplayName": "Wood" + "DisplayName": "Wood", + "Colour": { + "Red": 1111.0, + "Green": 11.0, + "Blue": 1111.0 + } } \ No newline at end of file