diff --git a/GlitchyEditor/SandboxProject/Assets/Scripts/MyTestEntity.cs b/GlitchyEditor/SandboxProject/Assets/Scripts/MyTestEntity.cs new file mode 100644 index 0000000..ddefb14 --- /dev/null +++ b/GlitchyEditor/SandboxProject/Assets/Scripts/MyTestEntity.cs @@ -0,0 +1,106 @@ +using System; +using GlitchyEngine; +using GlitchyEngine.Editor; +using GlitchyEngine.Math; + +namespace Sandbox; + +public enum MyEnum +{ + Yes, + No, + Maybe +} + +public struct MyStruct +{ + public float TheFloat; + public Vector2 TheVector; + public MyEnum TheEnum; +} + +class MyTestEntity : Entity +{ + //[ShowInEditor] + RigidBody2D _rigidBody; + + public bool Bo; + + public byte By; + public ushort Us; + public uint Ui; + public ulong Ul; + + public sbyte Sb; + public short Sh; + public int In; + public long Lo; + + public float Fl; + public double Do; + public Vector2 V2; + public Vector3 V3; + public Vector4 V4; + + public Entity TheEntity; + + public float JumpForce = 2000; + [ShowInEditor] + float MoveForce = 1000; + [ShowInEditor] + private int MyNumber = 1337; + [ShowInEditor] + public double MyDouble = 1000.0f; + + public MyStruct AStruct; + + /// + /// Called after the script component was created. (The entity might not be fully created yet) + /// + void OnCreate() + { + Log.Info($"Create! {UUID}"); + + _rigidBody ??= GetComponent() ?? AddComponent(); + } + + /// + /// Called every frame. + /// + /// + void OnUpdate(float deltaTime) + { + Vector2 force = Vector2.Zero; + + if (Input.IsKeyPressed(Key.A)) + { + force.X -= MoveForce * deltaTime; + } + + if (Input.IsKeyPressed(Key.D)) + { + force.X += MoveForce * deltaTime; + } + + if (Input.IsKeyPressing(Key.Space)) + { + force.Y += JumpForce; + } + + _rigidBody.ApplyForceToCenter(force); + + if (Input.IsMouseButtonReleasing(MouseButton.MiddleButton)) + { + Log.Info($"Ouha! {MyNumber}"); + Physics2D.Gravity *= new Vector2(1, -1); + } + } + + /// + /// Called before the component is being destroyed. + /// + void OnDestroy() + { + Log.Trace("Destroy"); + } +} diff --git a/GlitchyEditor/SandboxProject/Assets/Scripts/Properties/AssemblyInfo.cs b/GlitchyEditor/SandboxProject/Assets/Scripts/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..1e0009f --- /dev/null +++ b/GlitchyEditor/SandboxProject/Assets/Scripts/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// Allgemeine Informationen über eine Assembly werden über die folgenden +// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern, +// die einer Assembly zugeordnet sind. +[assembly: AssemblyTitle("Sanbox")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Sanbox")] +[assembly: AssemblyCopyright("Copyright © 2023")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Durch Festlegen von ComVisible auf FALSE werden die Typen in dieser Assembly +// für COM-Komponenten unsichtbar. Wenn Sie auf einen Typ in dieser Assembly von +// COM aus zugreifen müssen, sollten Sie das ComVisible-Attribut für diesen Typ auf "True" festlegen. +[assembly: ComVisible(false)] + +// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird +[assembly: Guid("7a70819c-5317-402a-8553-95c5a001e370")] + +// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten: +// +// Hauptversion +// Nebenversion +// Buildnummer +// Revision +// +// Sie können alle Werte angeben oder Standardwerte für die Build- und Revisionsnummern verwenden, +// indem Sie "*" wie unten gezeigt eingeben: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/GlitchyEditor/SandboxProject/Assets/Scripts/Sandbox.csproj b/GlitchyEditor/SandboxProject/Assets/Scripts/Sandbox.csproj new file mode 100644 index 0000000..bad560c --- /dev/null +++ b/GlitchyEditor/SandboxProject/Assets/Scripts/Sandbox.csproj @@ -0,0 +1,56 @@ + + + + + Debug + AnyCPU + {7A70819C-5317-402A-8553-95C5A001E370} + Library + Properties + Sandbox + Sandbox + v4.7.2 + 512 + true + + + true + full + false + bin\ + DEBUG;TRACE + prompt + 4 + default + + + pdbonly + true + bin\ + TRACE + prompt + 4 + default + + + + + + + + + + + + + + + + + + {6222c226-fc78-498c-80ba-5cf10ac9123c} + ScriptCore + + + + \ No newline at end of file diff --git a/GlitchyEditor/SandboxProject/Assets/Scripts/Sandbox.sln b/GlitchyEditor/SandboxProject/Assets/Scripts/Sandbox.sln new file mode 100644 index 0000000..02c6104 --- /dev/null +++ b/GlitchyEditor/SandboxProject/Assets/Scripts/Sandbox.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.4.33205.214 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sandbox", "Sandbox.csproj", "{7A70819C-5317-402A-8553-95C5A001E370}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ScriptCore", "..\..\..\..\ScriptCore\ScriptCore.csproj", "{6222C226-FC78-498C-80BA-5CF10AC9123C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {7A70819C-5317-402A-8553-95C5A001E370}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7A70819C-5317-402A-8553-95C5A001E370}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7A70819C-5317-402A-8553-95C5A001E370}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7A70819C-5317-402A-8553-95C5A001E370}.Release|Any CPU.Build.0 = Release|Any CPU + {6222C226-FC78-498C-80BA-5CF10AC9123C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6222C226-FC78-498C-80BA-5CF10AC9123C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6222C226-FC78-498C-80BA-5CF10AC9123C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6222C226-FC78-498C-80BA-5CF10AC9123C}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {B5D43D8D-D80B-41AA-BE40-1DC507D87148} + EndGlobalSection +EndGlobal diff --git a/GlitchyEditor/content/Textures/TestMat/rustediron2_metallic.png.ass b/GlitchyEditor/content/Textures/TestMat/rustediron2_metallic.png.ass index ccdb9a9..b40adb4 100644 --- a/GlitchyEditor/content/Textures/TestMat/rustediron2_metallic.png.ass +++ b/GlitchyEditor/content/Textures/TestMat/rustediron2_metallic.png.ass @@ -1,20 +1,16 @@ { AssetLoader = "EditorTextureAssetLoader", Config = (GlitchyEditor.Assets.EditorTextureAssetLoaderConfig){ - _generateMipMaps = false, - _isSrgb = false, _samplerStateDescription = { - MinFilter = .Linear, - MagFilter = .Linear, - MipFilter = .Linear, - FilterMode = .Default, + MinFilter = .Anisotropic, + MagFilter = .Anisotropic, + MipFilter = .Anisotropic, ComparisonFunction = .Never, AddressModeU = .Wrap, AddressModeV = .Wrap, AddressModeW = .Clamp, - MipLODBias = 0, - MipMinLOD = -3.40282347e+38, - MipMaxLOD = 3.40282347e+38, + MipMinLOD = -Infinity, + MipMaxLOD = Infinity, MaxAnisotropy = 1, BorderColor = { R = 1, diff --git a/GlitchyEditor/content/Textures/TestMaterial.mat b/GlitchyEditor/content/Textures/TestMaterial.mat index a8d3b45..07cce57 100644 --- a/GlitchyEditor/content/Textures/TestMaterial.mat +++ b/GlitchyEditor/content/Textures/TestMaterial.mat @@ -1,10 +1,10 @@ { - Effect = "Shaders\\myEffect.hlsl", + Effect = "Shaders/myEffect.hlsl", Textures = [ - "AlbedoTexture": "Textures\\TestMat\\rustediron2_albedo.png", - "NormalTexture": "Textures\\TestMat\\rustediron2_normal.png", - "MetallicTexture": "Textures\\TestMat\\rustediron2_metallic.png", - "RoughnessTexture": "Textures\\TestMat\\rustediron2_roughness.png" + "AlbedoTexture": "Textures/TestMat/rustediron2_albedo.png", + "NormalTexture": "Textures/TestMat/rustediron2_normal.png", + "MetallicTexture": "Textures/TestMat/rustediron2_metallic.png", + "RoughnessTexture": "Textures/TestMat/rustediron2_roughness.png" ], Variables = [ "AlbedoColor": .ColorRGBA{ diff --git a/GlitchyEngine/src/Helper.bf b/GlitchyEngine/src/Helper.bf index 5c447bd..1a597a1 100644 --- a/GlitchyEngine/src/Helper.bf +++ b/GlitchyEngine/src/Helper.bf @@ -1,5 +1,6 @@ using DirectX.Common; using GlitchyEngine.Core; +using System.Collections; namespace GlitchyEngine { @@ -20,7 +21,7 @@ namespace GlitchyEngine value?.ReleaseRef(); value = null; } - + public static mixin DeleteContainerAndReleaseItems(var container) { if (container != null) @@ -37,5 +38,17 @@ namespace GlitchyEngine value?.ReleaseRef(); container.Clear(); } + + public static mixin DeleteDictionaryAndReleaseValues(var container) + { + if (container != null) + { + for (var value in container) + { + value.value?.ReleaseRef(); + } + delete container; + } + } } } diff --git a/GlitchyEngine/src/Scripting/ScriptClass.bf b/GlitchyEngine/src/Scripting/ScriptClass.bf index ab57a15..56fd7af 100644 --- a/GlitchyEngine/src/Scripting/ScriptClass.bf +++ b/GlitchyEngine/src/Scripting/ScriptClass.bf @@ -11,56 +11,55 @@ public struct ScriptField { public StringView Name; internal MonoClassField* _monoField; + public bool IsStatic; + public ScriptFieldType FieldType; - internal this(StringView name, MonoClassField* monoField) + internal this(StringView name, MonoClassField* monoField, bool isStatic, ScriptFieldType fieldType) { Name = name; _monoField = monoField; + IsStatic = isStatic; + FieldType = fieldType; } } -class ScriptClass : RefCounter +abstract class SharpType : RefCounter { - private String _namespace ~ delete _; - private String _className ~ delete _; - private String _fullName ~ delete _; - - private MonoClass* _monoClass; - - //private List _monoFields ~ delete _; - private Dictionary _monoFields ~ delete _; - - //typealias ConstructorMethod = function void(MonoObject* instance, UUID uuid, MonoException** exception); - typealias OnCreateMethod = function MonoObject*(MonoObject* instance, MonoException** exception); - typealias OnUpdateMethod = function MonoObject*(MonoObject* instance, float deltaTime, MonoException** exception); - typealias OnDestroyMethod = function MonoObject*(MonoObject* instance, MonoException** exception); - - private MonoMethod* _constructor; - //private ConstructorMethod _constructor; - private OnCreateMethod _onCreate; - private OnUpdateMethod _onUpdate; - private OnDestroyMethod _onDestroy; + protected String _namespace ~ delete _; + protected String _className ~ delete _; + protected String _fullName ~ delete _; + protected ScriptFieldType _scriptType; + + protected Dictionary _monoFields ~ delete _; public StringView Namespace => _namespace; public StringView ClassName => _className; public StringView FullName => _fullName; - + public ScriptFieldType ScriptType => _scriptType; + public Dictionary Fields => _monoFields; - - [AllowAppend] - public this(StringView classNamespace, StringView className) + + public this(StringView classNamespace, StringView className, ScriptFieldType scriptType) { _namespace = new String(classNamespace); _className = new String(className); _fullName = new $"{_namespace}.{_className}"; + _scriptType = scriptType; + + ScriptEngine.RegisterSharpType(this); + } +} - _monoClass = Mono.mono_class_from_name(ScriptEngine.[Friend]s_CoreAssemblyImage, _namespace, _className); +class SharpClass : SharpType +{ + protected internal MonoClass* _monoClass; + + public this(StringView classNamespace, StringView className, MonoImage* image, ScriptFieldType fieldType = .Class) : + base(classNamespace, className, fieldType) + { + _monoClass = Mono.mono_class_from_name(image, _namespace, _className); - //_constructor = (ConstructorMethod)GetMethodThunk(".ctor", 1); // GetMethod(".ctor", 1);// - _constructor = GetMethod(".ctor", 1); - _onCreate = (OnCreateMethod)GetMethodThunk("OnCreate"); - _onUpdate = (OnUpdateMethod)GetMethodThunk("OnUpdate", 1); - _onDestroy = (OnDestroyMethod)GetMethodThunk("OnDestroy"); + Log.EngineLogger.AssertDebug(_monoClass != null); ExtractFields(); } @@ -74,12 +73,89 @@ class ScriptClass : RefCounter MonoClassField* currentField = null; while ((currentField = Mono.mono_class_get_fields(_monoClass, &iterator)) != null) { - // TODO: does the pointer from mono really never move? StringView name = StringView(Mono.mono_field_get_name(currentField)); - _monoFields[name] = .(name, currentField); + MonoType* type = Mono.mono_field_get_type(currentField); + + ScriptFieldType fieldType = ScriptEngineHelper.GetScriptFieldType(type); + + // If field type is none the field might be a struct, class or enum + if (fieldType == .None) + { + SharpType sharpType = ScriptEngine.GetSharpType(type); + fieldType = sharpType?.ScriptType ?? .None; + + if (sharpType == null) + continue; + } + + //Mono.MonoTypeEnum fieldType = Mono.Mono.mono_type_get_type(type); + + FieldAttribute flags = (.)Mono.mono_field_get_flags(currentField); + + MonoCustomAttrInfo* attributes = Mono.mono_custom_attrs_from_field(_monoClass, currentField); + + if (flags.HasFlag(.Public) || + (attributes != null && + Mono.mono_custom_attrs_has_attr(attributes, ScriptEngine.Attributes.s_ShowInEditorAttribute))) + { + _monoFields[name] = .(name, currentField, flags.HasFlag(.Static), fieldType); + } } } +} + +class SharpStruct : SharpClass +{ + protected int _size; + + public int Size => _size; + + public this(StringView classNamespace, StringView className, MonoImage* image) + : base(classNamespace, className, image) + { + + } +} + +class ScriptClass : SharpClass +{ + /*private String _namespace ~ delete _; + private String _className ~ delete _; + private String _fullName ~ delete _; + + private MonoClass* _monoClass; + + //private List _monoFields ~ delete _; + private Dictionary _monoFields ~ delete _;*/ + + //typealias ConstructorMethod = function void(MonoObject* instance, UUID uuid, MonoException** exception); + typealias OnCreateMethod = function MonoObject*(MonoObject* instance, MonoException** exception); + typealias OnUpdateMethod = function MonoObject*(MonoObject* instance, float deltaTime, MonoException** exception); + typealias OnDestroyMethod = function MonoObject*(MonoObject* instance, MonoException** exception); + + private MonoMethod* _constructor; + //private ConstructorMethod _constructor; + private OnCreateMethod _onCreate; + private OnUpdateMethod _onUpdate; + private OnDestroyMethod _onDestroy; + + /*public StringView Namespace => _namespace; + public StringView ClassName => _className; + public StringView FullName => _fullName; + + public Dictionary Fields => _monoFields;*/ + + [AllowAppend] + public this(StringView classNamespace, StringView className, MonoImage* image) : + base(classNamespace, className, image) + { + //_constructor = (ConstructorMethod)GetMethodThunk(".ctor", 1); // GetMethod(".ctor", 1);// + _constructor = GetMethod(".ctor", 1); + _onCreate = (OnCreateMethod)GetMethodThunk("OnCreate"); + _onUpdate = (OnUpdateMethod)GetMethodThunk("OnUpdate", 1); + _onDestroy = (OnDestroyMethod)GetMethodThunk("OnDestroy"); + } public void OnCreate(MonoObject* instance) { @@ -155,4 +231,16 @@ class ScriptClass : RefCounter MonoObject* object = Invoke(method, instance, args.Ptr); return *(T*)Mono.mono_object_unbox(object); } + + public T GetFieldValue(MonoObject* instance, MonoClassField* field) + { + T value = default; + Mono.Mono.mono_field_get_value(instance, field, &value); + return value; + } + + public void SetFieldValue(MonoObject* instance, MonoClassField* field, in T value) + { + Mono.Mono.mono_field_set_value(instance, field, &value); + } } diff --git a/GlitchyEngine/src/Scripting/ScriptEngine.bf b/GlitchyEngine/src/Scripting/ScriptEngine.bf index eb7894f..3585114 100644 --- a/GlitchyEngine/src/Scripting/ScriptEngine.bf +++ b/GlitchyEngine/src/Scripting/ScriptEngine.bf @@ -8,6 +8,68 @@ using GlitchyEngine.Core; namespace GlitchyEngine.Scripting; +using internal GlitchyEngine.Scripting; + +enum ScriptFieldType +{ + None, + + Class, + Enum, + Struct, + + // TODO! + Bool, + + SByte, + Short, + Int,// Int2, Int3, Int4, + Long, + Byte, + UShort, + UInt, // UInt2, UInt3, UInt4, + ULong, + // Half, Half2, Half3, Half4, + Float, Vector2, Vector3, Vector4, + Double, // Double2, Double3, Double4, + + Entity +} + +static sealed class ScriptEngineHelper +{ + private static Dictionary _scriptFieldTypes = new Dictionary() + { + ("System.Boolean", .Bool), + + ("System.SByte", .SByte), + ("System.Int16", .Short), + ("System.Int32", .Int), + ("System.Int64", .Long), + + ("System.Byte", .Byte), + ("System.UInt16", .UShort), + ("System.UInt32", .UInt), + ("System.UInt64", .ULong), + + ("System.Single", .Float), + ("GlitchyEngine.Math.Vector2", .Vector2), + ("GlitchyEngine.Math.Vector3", .Vector3), + ("GlitchyEngine.Math.Vector4", .Vector4), + + ("System.Double", .Double), + + ("GlitchyEngine.Entity", .Entity), + } ~ delete _; + + public static ScriptFieldType GetScriptFieldType(MonoType* monoType) + { + StringView typeName = StringView(Mono.mono_type_get_name(monoType)); + + return _scriptFieldTypes.TryGetValue(typeName, .. let scriptFieldType); + } +} + static class ScriptEngine { private static MonoDomain* s_RootDomain; @@ -16,31 +78,35 @@ static class ScriptEngine private static MonoAssembly* s_CoreAssembly; private static MonoImage* s_CoreAssemblyImage; + private static MonoAssembly* s_AppAssembly; + private static MonoImage* s_AppAssemblyImage; + private static Scene s_Context ~ _?.ReleaseRef(); private static ScriptClass s_EntityRoot ~ _?.ReleaseRef(); private static ScriptClass s_EngineObject ~ _?.ReleaseRef(); - private static Dictionary _entityScripts = new .() ~ { - for (var entry in _) - { - entry.value.ReleaseRef(); - } - delete _entityScripts; - }; - - private static Dictionary _entityScriptInstances = new .() ~ { + private static Dictionary _sharpClasses = new .() ~ DeleteDictionaryAndReleaseValues!(_); + + private static Dictionary _entityScripts = new .() ~ DeleteDictionaryAndReleaseValues!(_); + + /*private static Dictionary _entityScriptInstances = new .() ~ { for (var entry in _) { entry.value?.ReleaseRef(); } delete _; - }; - + };*/ + public static Dictionary EntityClasses => _entityScripts; public static Scene Context => s_Context; + internal static class Attributes + { + internal static MonoClass* s_ShowInEditorAttribute; + } + public static void Init() { Mono.mono_set_assemblies_path("mono/lib"); @@ -50,7 +116,11 @@ static class ScriptEngine ScriptGlue.Init(); - LoadAssembly("resources/scripts/ScriptCore.dll"); + CreateAppDomain("GlitchyEngineScriptRuntime"); + (s_CoreAssembly, s_CoreAssemblyImage) = LoadAssembly("resources/scripts/ScriptCore.dll"); + (s_AppAssembly, s_AppAssemblyImage) = LoadAssembly("SandboxProject/Assets/Scripts/bin/Sandbox.dll"); + + GetEntitiesFromAssemblies(); ScriptGlue.RegisterManagedComponents(); @@ -64,18 +134,18 @@ static class ScriptEngine public static void OnRuntimeStop() { - for (var entry in _entityScriptInstances) + /*for (var entry in _entityScriptInstances) { entry.value.ReleaseRef(); } - _entityScriptInstances.Clear(); + _entityScriptInstances.Clear();*/ SetContext(null); } public static void InitializeInstance(Entity entity, ScriptComponent* script) { - _entityScriptInstances[entity.UUID] = script.Instance..AddRef(); + //_entityScriptInstances[entity.UUID] = script.Instance..AddRef(); script.Instance.Instantiate(entity.UUID); } @@ -107,85 +177,54 @@ static class ScriptEngine return assembly; } - static void LoadAssembly(StringView filepath) + static void CreateAppDomain(StringView name) { - s_AppDomain = Mono.mono_domain_create_appdomain("GlitchyEngineScriptRuntime", null); + s_AppDomain = Mono.mono_domain_create_appdomain(name.ToScopeCStr!(), null); Mono.mono_domain_set(s_AppDomain, true); - - s_CoreAssembly = LoadCSharpAssembly(filepath); - s_CoreAssemblyImage = Mono.mono_assembly_get_image(s_CoreAssembly); - GetEntitiesFromAssembly(s_CoreAssembly); } - private static void GetEntitiesFromAssembly(MonoAssembly* assembly) + static (MonoAssembly* assembly, MonoImage* image) LoadAssembly(StringView filepath) + { + MonoAssembly* assembly = LoadCSharpAssembly(filepath); + MonoImage* image = Mono.mono_assembly_get_image(assembly); + + return (assembly, image); + } + + private static void GetEntitiesFromAssemblies() { for (var entry in _entityScripts) { entry.value.ReleaseRef(); } _entityScripts.Clear(); - - MonoImage* image = Mono.mono_assembly_get_image(assembly); - MonoTableInfo* typeDefinitionsTable = Mono.mono_image_get_table_info(image, .MONO_TABLE_TYPEDEF); - int32 numTypes = Mono.mono_table_info_get_rows(typeDefinitionsTable); - - /*MonoTableInfo* fieldsTable = Mono.mono_image_get_table_info(image, .MONO_TABLE_FIELD); - int32 numFields = Mono.mono_table_info_get_rows(fieldsTable);*/ - - s_EngineObject = new ScriptClass("GlitchyEngine.Core", "EngineObject"); - s_EntityRoot = new ScriptClass("GlitchyEngine", "Entity"); - - Log.EngineLogger.Assert(s_EntityRoot != null); - - /*for (int32 fieldIndex < numFields) + + if (s_EngineObject == null) { - uint32[(.)FIELD_TABLE_FLAGS.MONO_FIELD_SIZE] fieldCols = .(); - Mono.mono_metadata_decode_row(fieldsTable, fieldIndex, (.)&fieldCols, (.)FIELD_TABLE_FLAGS.MONO_FIELD_SIZE); - - char8* fieldName = Mono.mono_metadata_string_heap(image, (.)fieldCols[(.)FIELD_TABLE_FLAGS.MONO_FIELD_NAME]); - Log.EngineLogger.Info($"{StringView(fieldName)}"); - }*/ + s_EngineObject = new ScriptClass("GlitchyEngine.Core", "EngineObject", s_CoreAssemblyImage); + s_EntityRoot = new ScriptClass("GlitchyEngine", "Entity", s_CoreAssemblyImage); + + Log.EngineLogger.Assert(s_EntityRoot != null); + } + + Attributes.s_ShowInEditorAttribute = Mono.mono_class_from_name(s_CoreAssemblyImage, "GlitchyEngine.Editor", "ShowInEditorAttribute"); + + MonoTableInfo* typeDefinitionsTable = Mono.mono_image_get_table_info(s_AppAssemblyImage, .MONO_TABLE_TYPEDEF); + int32 numTypes = Mono.mono_table_info_get_rows(typeDefinitionsTable); for (int32 i = 0; i < numTypes; i++) { int32[(.)SOME_RANDOM_ENUM.MONO_TYPEDEF_SIZE] cols = .(); Mono.mono_metadata_decode_row(typeDefinitionsTable, i, (.)&cols, (.)SOME_RANDOM_ENUM.MONO_TYPEDEF_SIZE); - char8* nameSpace = Mono.mono_metadata_string_heap(image, (.)cols[(.)SOME_RANDOM_ENUM.MONO_TYPEDEF_NAMESPACE]); - char8* name = Mono.mono_metadata_string_heap(image, (.)cols[(.)SOME_RANDOM_ENUM.MONO_TYPEDEF_NAME]); + char8* nameSpace = Mono.mono_metadata_string_heap(s_AppAssemblyImage, (.)cols[(.)SOME_RANDOM_ENUM.MONO_TYPEDEF_NAMESPACE]); + char8* name = Mono.mono_metadata_string_heap(s_AppAssemblyImage, (.)cols[(.)SOME_RANDOM_ENUM.MONO_TYPEDEF_NAME]); - /*int32 firstFieldIndex = cols[(.)SOME_RANDOM_ENUM.MONO_TYPEDEF_FIELD_LIST] - 1; - if (firstFieldIndex >= 0) - { - int32 lastFieldIndex; - - if ((i + 1) < numTypes) - { - int32[(.)SOME_RANDOM_ENUM.MONO_TYPEDEF_SIZE] nextCols = .(); - Mono.mono_metadata_decode_row(typeDefinitionsTable, i + 1, (.)&nextCols, (.)SOME_RANDOM_ENUM.MONO_TYPEDEF_SIZE); - lastFieldIndex = nextCols[(.)SOME_RANDOM_ENUM.MONO_TYPEDEF_FIELD_LIST] - 1; - } - else - { - lastFieldIndex = numFields; - } - - for (int32 fieldIndex = firstFieldIndex; fieldIndex < lastFieldIndex; fieldIndex++) - { - uint32[(.)FIELD_TABLE_FLAGS.MONO_FIELD_SIZE] fieldCols = .(); - Mono.mono_metadata_decode_row(fieldsTable, fieldIndex, (.)&fieldCols, (.)FIELD_TABLE_FLAGS.MONO_FIELD_SIZE); - - char8* fieldName = Mono.mono_metadata_string_heap(image, (.)fieldCols[(.)FIELD_TABLE_FLAGS.MONO_FIELD_NAME]); - Log.EngineLogger.Info($"{StringView(nameSpace)}.{StringView(name)}::{StringView(fieldName)}"); - //char8* fieldSignature = Mono.mono_metadata_blob_heap(image, (.)fieldCols[(.)FIELD_TABLE_FLAGS.MONO_FIELD_SIGNATURE]); - } - }*/ - - MonoClass* monoClass = Mono.mono_class_from_name(image, nameSpace, name); + MonoClass* monoClass = Mono.mono_class_from_name(s_AppAssemblyImage, nameSpace, name); if (monoClass != null && Mono.mono_class_is_subclass_of(monoClass, s_EntityRoot.[Friend]_monoClass, false)) { - ScriptClass entityScript = new ScriptClass(StringView(nameSpace), StringView(name)); + ScriptClass entityScript = new ScriptClass(StringView(nameSpace), StringView(name), s_AppAssemblyImage); _entityScripts.Add(entityScript.FullName, entityScript); Log.EngineLogger.Info($"Added entity \"{entityScript.FullName}\""); @@ -205,6 +244,51 @@ static class ScriptEngine s_RootDomain = null; } + internal static void RegisterSharpType(SharpType sharpType) + { + _sharpClasses.Add(sharpType.FullName, sharpType..AddRef()); + } + + internal static SharpType GetSharpType(MonoType* monoType) + { + StringView typeName = StringView(Mono.mono_type_get_name(monoType)); + + if (_sharpClasses.TryGetValue(typeName, let sharpType)) + return sharpType; + + Mono.MonoTypeEnum fieldType = Mono.Mono.mono_type_get_type(monoType); + + MonoClass* monoClass = Mono.mono_type_get_class(monoType); + + if (monoClass == null) + return null; + + StringView className = StringView(Mono.mono_class_get_name(monoClass)); + StringView classNamespace = StringView(Mono.mono_class_get_namespace(monoClass)); + + // TODO: at the moment only allow user-structs + if (classNamespace.StartsWith("GlitchyEngine")) + return null; + + switch (fieldType) + { + case .Class, .Valuetype, .Enum: + ScriptFieldType scriptType = .None; + + if (fieldType == .Class) + scriptType = .Class; + else if (fieldType == .Enum) + scriptType = .Enum; + else if (fieldType == .Valuetype) + scriptType = .Struct; + + Log.EngineLogger.AssertDebug(scriptType != .None); + + return new SharpClass(classNamespace, className, Mono.mono_class_get_image(monoClass), scriptType); + default: + return null; + } + } diff --git a/GlitchyEngine/src/Scripting/ScriptInstance.bf b/GlitchyEngine/src/Scripting/ScriptInstance.bf index e7fd04e..a3a0f9a 100644 --- a/GlitchyEngine/src/Scripting/ScriptInstance.bf +++ b/GlitchyEngine/src/Scripting/ScriptInstance.bf @@ -1,5 +1,6 @@ using Mono; using GlitchyEngine.Core; +using System; namespace GlitchyEngine.Scripting; @@ -50,4 +51,22 @@ class ScriptInstance : RefCounter { _scriptClass.OnDestroy(_instance); } + + public T GetFieldValue(MonoClassField* field) + { + return _scriptClass.GetFieldValue(_instance, field); + } + + public void SetFieldValue(MonoClassField* field, in T value) + { + _scriptClass.SetFieldValue(_instance, field, value); + } + + public void CopyEditorFieldsTo(ScriptInstance target) + { + for (let (fieldName, field) in ScriptClass.Fields) + { + + } + } } \ No newline at end of file diff --git a/GlitchyEngine/src/World/Scene.bf b/GlitchyEngine/src/World/Scene.bf index 6908f65..9215a27 100644 --- a/GlitchyEngine/src/World/Scene.bf +++ b/GlitchyEngine/src/World/Scene.bf @@ -98,6 +98,8 @@ namespace GlitchyEngine.World targetComponent.Instance = new ScriptInstance(sourceComponent.Instance.ScriptClass); targetComponent.Instance..ReleaseRef(); + + sourceComponent.Instance.CopyEditorFieldsTo(targetComponent.Instance); } // Copy transforms @@ -263,17 +265,23 @@ namespace GlitchyEngine.World script.Instance.[Friend]OnUpdate(gameTime); } - + /*} + + if (mode.HasFlag(.Runtime) || mode.HasFlag(.Editor)) + {*/ // Run scripts for (var (entity, script) in _ecsWorld.Enumerate()) { if (!script.InInstantiated) { ScriptEngine.InitializeInstance(Entity(entity, this), script); - script.Instance.InvokeOnCreate(); + + if (mode.HasFlag(.Runtime)) + script.Instance.InvokeOnCreate(); } - - script.Instance.InvokeOnUpdate(gameTime.DeltaTime); + + if (mode.HasFlag(.Runtime)) + script.Instance.InvokeOnUpdate(gameTime.DeltaTime); } } diff --git a/GlitchyEngineHelper/src/Mono/Mono.bf b/GlitchyEngineHelper/src/Mono/Mono.bf index d2f004f..bf99fc5 100644 --- a/GlitchyEngineHelper/src/Mono/Mono.bf +++ b/GlitchyEngineHelper/src/Mono/Mono.bf @@ -79,6 +79,15 @@ static class Mono [LinkName(.C)] public static extern MonoClass* mono_class_from_name(MonoImage* image, char8* name_space, char8* name); + + [LinkName(.C)] + public static extern char8* mono_class_get_name(MonoClass* monoClass); + + [LinkName(.C)] + public static extern char8* mono_class_get_namespace(MonoClass* monoClass); + + [LinkName(.C)] + public static extern MonoImage* mono_class_get_image(MonoClass* monoClass); [LinkName(.C)] public static extern MonoClass* mono_class_load_from_name(MonoImage* image, char8* name_space, @@ -139,6 +148,40 @@ static class Mono [LinkName(.C)] public static extern char8* mono_field_get_name(MonoClassField* field); + + [LinkName(.C)] + public static extern MonoType* mono_field_get_type(MonoClassField* field); + + [LinkName(.C)] + public static extern MonoClass* mono_field_get_parent(MonoClassField* field); + + [LinkName(.C)] + public static extern uint32 mono_field_get_flags(MonoClassField* field); + + [LinkName(.C)] + public static extern uint8* mono_field_get_data(MonoClassField* field); + + [LinkName(.C)] + public static extern void mono_field_get_value(MonoObject* object, MonoClassField* field, void* value); + + + [LinkName(.C)] + public static extern MonoCustomAttrInfo* mono_custom_attrs_from_field(MonoClass* monoClass, MonoClassField* field); + + [LinkName(.C)] + public static extern mono_bool mono_custom_attrs_has_attr(MonoCustomAttrInfo* attributeInfo, MonoClass* attributeClass); + + [LinkName(.C)] + public static extern MonoObject* mono_custom_attrs_get_attr(MonoCustomAttrInfo* attributeInfo, MonoClass* attributeClass); + + [LinkName(.C)] + public static extern Mono.MonoTypeEnum mono_type_get_type(MonoType* type); + + [LinkName(.C)] + public static extern char8* mono_type_get_name(MonoType* type); + + [LinkName(.C)] + public static extern MonoClass* mono_type_get_class(MonoType* type); } struct MonoDomain; @@ -165,6 +208,8 @@ struct MonoType; struct MonoReflectionType; +struct MonoCustomAttrInfo; + enum MonoImageOpenStatus { Ok, @@ -255,3 +300,71 @@ enum MonoMetaTableEnum : int32 //#define MONO_TABLE_NUM (MONO_TABLE_LAST + 1) } + +enum FieldAttribute +{ + FieldAccessMask = 0x0007, + CompilerControlled = 0x0000, + Private = 0x0001, + FamAndAssem = 0x0002, + Assembly = 0x0003, + Family = 0x0004, + FamOrAssem = 0x0005, + Public = 0x0006, + Static = 0x0010, + InitOnly = 0x0020, + Literal = 0x0040, + NotSerialized = 0x0080, + SpecialName = 0x0200, + PinvokeImpl = 0x2000, + /** For runtime use only */ + ReservedMask = 0x9500, + /** For runtime use only */ + RtSpecialName = 0x0400, + /** For runtime use only */ + HasFieldMarshal = 0x1000, + /** For runtime use only */ + HasDefault = 0x8000, + /** For runtime use only */ + HasFieldRva = 0x0100 +} + +enum MonoTypeEnum : int32 +{ + End = 0x00, /* End of List */ + Void = 0x01, + Boolean = 0x02, + Char = 0x03, + I1 = 0x04, + U1 = 0x05, + I2 = 0x06, + U2 = 0x07, + I4 = 0x08, + U4 = 0x09, + I8 = 0x0a, + U8 = 0x0b, + R4 = 0x0c, + R8 = 0x0d, + String = 0x0e, + Ptr = 0x0f, /* arg: token */ + Byref = 0x10, /* arg: token */ + Valuetype = 0x11, /* arg: token */ + Class = 0x12, /* arg: token */ + Var = 0x13, /* number */ + Array = 0x14, /* type, rank, boundsCount, bound1, loCount, lo1 */ + Genericins = 0x15, /* \x{2026} */ + Typedbyref = 0x16, + I = 0x18, + U = 0x19, + Fnptr = 0x1b, /* arg: full method signature */ + Object = 0x1c, + SzArray = 0x1d, /* 0-based one-dim-array */ + Mvar = 0x1e, /* number */ + CmodReqd = 0x1f, /* arg: typedef or typeref token */ + CmodOpt = 0x20, /* optional arg: typedef or typref token */ + Internal = 0x21, /* CLR internal type */ + Modifier = 0x40, /* Or with the following types */ + Sentinel = 0x41, /* Sentinel for varargs method signature */ + Pinned = 0x45, /* Local var that points to pinned object */ + Enum = 0x55 /* an enumeration */ +} diff --git a/ScriptCore/CSharpTesting.cs b/ScriptCore/CSharpTesting.cs deleted file mode 100644 index f88d598..0000000 --- a/ScriptCore/CSharpTesting.cs +++ /dev/null @@ -1,44 +0,0 @@ -using System; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using GlitchyEngine.Math; - -namespace GlitchyEngine; - -public class CSharpTesting -{ - public float MyPublicFloatVar = 5.0f; - - public CSharpTesting() - { - Console.WriteLine("Hallo von C#!"); - DoSomething(); - Console.WriteLine(Sample()); - - Vector3 a = new Vector3(1, 2, 3); - Vector3 b = new Vector3(3, 2, 1); - - Vector3 result; - //Vector3.Add_Internal(a, b, out result); - - //Console.WriteLine(result); - } - - [DllImport ("__Internal", EntryPoint="DoSomething")] - static extern void DoSomething(); - - [MethodImpl(MethodImplOptions.InternalCall)] - static extern string Sample(); - - public void PrintFloatVar() - { - Console.WriteLine("MyPublicFloatVar = {0:F}", MyPublicFloatVar); - } - - private float IncrementFloatVar(float value) - { - MyPublicFloatVar += value; - - return MyPublicFloatVar; - } -} diff --git a/ScriptCore/Editor/RangeAttribute.cs b/ScriptCore/Editor/RangeAttribute.cs new file mode 100644 index 0000000..68fe518 --- /dev/null +++ b/ScriptCore/Editor/RangeAttribute.cs @@ -0,0 +1,15 @@ +using System; + +namespace GlitchyEngine.Editor; + +//public sealed class RangeAttribute : Attribute +//{ +// public float Min { get; set; } +// public float Max { get; set; } + +// public RangeAttribute(float min, float max) +// { +// Min = min; +// Max = max; +// } +//} \ No newline at end of file diff --git a/ScriptCore/Editor/ShowInEditorAttribute.cs b/ScriptCore/Editor/ShowInEditorAttribute.cs new file mode 100644 index 0000000..cfaa605 --- /dev/null +++ b/ScriptCore/Editor/ShowInEditorAttribute.cs @@ -0,0 +1,11 @@ +using System; + +namespace GlitchyEngine.Editor; + +public sealed class ShowInEditorAttribute : Attribute +{ + public string DisplayName { get; set; } = null; + + public ShowInEditorAttribute() + {} +} \ No newline at end of file diff --git a/ScriptCore/Math/Vector4.cs b/ScriptCore/Math/Vector4.cs new file mode 100644 index 0000000..cee01c8 --- /dev/null +++ b/ScriptCore/Math/Vector4.cs @@ -0,0 +1,155 @@ +using System; +using System.Runtime.CompilerServices; + +namespace GlitchyEngine.Math; + +public struct Vector4 +{ + //public static readonly Vector3 Zero = new(0.0f, 0.0f, 0.0f); + //public static readonly Vector3 UnitX = new(1.0f, 0.0f, 0.0f); + //public static readonly Vector3 UnitY = new(0.0f, 1.0f, 0.0f); + //public static readonly Vector3 UnitZ = new(0.0f, 0.0f, 1.0f); + //public static readonly Vector3 One = new(0.0f, 0.0f, 0.0f); + + //public static readonly Vector3 Forward = new(0.0f, 0.0f, 1.0f); + //public static readonly Vector3 Backward = new(0.0f, 0.0f, -1.0f); + //public static readonly Vector3 Left = new(-1.0f, 0.0f, 0.0f); + //public static readonly Vector3 Right = new(1.0f, 0.0f, 0.0f); + //public static readonly Vector3 Up = new(0.0f, 1.0f, 0.0f); + //public static readonly Vector3 Down = new(0.0f, -1.0f, 0.0f); + + public const int ComponentCount = 4; + + public float X, Y, Z, W; + + public Vector4() + { + X = Y = Z = W = 0.0f; + } + + public Vector4(float x, float y, float z, float w) + { + X = x; + Y = y; + Z = z; + W = w; + } + + public Vector4(Vector2 xy, Vector2 zw) + { + X = xy.X; + Y = xy.Y; + Z = zw.X; + W = zw.Y; + } + + public Vector4(Vector3 xyz, float w) + { + X = xyz.X; + Y = xyz.Y; + Z = xyz.Z; + W = w; + } + + public float this[int index] + { + get + { + switch (index) + { + case 0: return X; + case 1: return Y; + case 2: return Z; + case 3: return W; + default: throw new IndexOutOfRangeException(); + } + } + + set + { + switch (index) + { + case 0: + X = value; + break; + case 1: + Y = value; + break; + case 2: + Z = value; + break; + case 3: + W = value; + break; + default: throw new IndexOutOfRangeException(); + } + } + } + + //[MethodImpl(MethodImplOptions.AggressiveInlining)] + //public static Vector3 operator +(in Vector3 a, in Vector3 b) => new(a.X + b.X, a.Y + b.Y, a.Z + b.Z); + //[MethodImpl(MethodImplOptions.AggressiveInlining)] + //public static Vector3 operator +(float a, in Vector3 b) => new(a + b.X, a + b.Y, a + b.Z); + //[MethodImpl(MethodImplOptions.AggressiveInlining)] + //public static Vector3 operator +(in Vector3 a, float b) => new(a.X + b, a.Y + b, a.Z + b); + //[MethodImpl(MethodImplOptions.AggressiveInlining)] + //public static Vector3 operator +(in Vector3 a) => a; + + //[MethodImpl(MethodImplOptions.AggressiveInlining)] + //public static Vector3 operator -(in Vector3 a, in Vector3 b) => new(a.X - b.X, a.Y - b.Y, a.Z - b.Z); + //[MethodImpl(MethodImplOptions.AggressiveInlining)] + //public static Vector3 operator -(float a, in Vector3 b) => new(a - b.X, a - b.Y, a - b.Z); + //[MethodImpl(MethodImplOptions.AggressiveInlining)] + //public static Vector3 operator -(in Vector3 a, float b) => new(a.X - b, a.Y - b, a.Z - b); + //[MethodImpl(MethodImplOptions.AggressiveInlining)] + //public static Vector3 operator -(in Vector3 a) => new Vector3(-a.X, -a.Y, -a.Z); + + //[MethodImpl(MethodImplOptions.AggressiveInlining)] + //public static Vector3 operator *(in Vector3 a, in Vector3 b) => new(a.X * b.X, a.Y * b.Y, a.Z * b.Z); + //[MethodImpl(MethodImplOptions.AggressiveInlining)] + //public static Vector3 operator *(float a, in Vector3 b) => new(a * b.X, a * b.Y, a * b.Z); + //[MethodImpl(MethodImplOptions.AggressiveInlining)] + //public static Vector3 operator *(in Vector3 a, float b) => new(a.X * b, a.Y * b, a.Z * b); + + //[MethodImpl(MethodImplOptions.AggressiveInlining)] + //public static Vector3 operator /(in Vector3 a, in Vector3 b) => new(a.X / b.X, a.Y / b.Y, a.Z / b.Z); + //[MethodImpl(MethodImplOptions.AggressiveInlining)] + //public static Vector3 operator /(float a, in Vector3 b) => new(a / b.X, a / b.Y, a / b.Z); + //[MethodImpl(MethodImplOptions.AggressiveInlining)] + //public static Vector3 operator /(in Vector3 a, float b) => new(a.X / b, a.Y / b, a.Z / b); + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool operator ==(Vector4 a, Vector4 b) + { + float diffX = a.X - b.X; + float diffY = a.Y - b.Y; + float diffZ = a.Z - b.Z; + float diffW = a.W - b.W; + + return diffX * diffX + diffY * diffY + diffZ * diffZ + diffW * diffW < 0.00001f; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool operator !=(Vector4 a, Vector4 b) + { + return !(a == b); + } + + public override int GetHashCode() + { + unchecked + { + var hashCode = X.GetHashCode(); + hashCode = (hashCode * 397) ^ Y.GetHashCode(); + hashCode = (hashCode * 397) ^ Z.GetHashCode(); + hashCode = (hashCode * 397) ^ Z.GetHashCode(); + return hashCode; + } + } + + public override string ToString() + { + return $"X:{X}, Y:{Y}, Z:{Z}, W:{W}"; + } +} \ No newline at end of file diff --git a/ScriptCore/MyTestEntity.cs b/ScriptCore/MyTestEntity.cs deleted file mode 100644 index 74bda99..0000000 --- a/ScriptCore/MyTestEntity.cs +++ /dev/null @@ -1,59 +0,0 @@ -using System; -using GlitchyEngine.Math; - -namespace GlitchyEngine; - -class MyTestEntity : Entity -{ - RigidBody2D _rigidBody; - - /// - /// Called after the script component was created. (The entity might not be fully created yet) - /// - void OnCreate() - { - Log.Info($"Create! {UUID}"); - - _rigidBody ??= GetComponent() ?? AddComponent(); - } - - /// - /// Called every frame. - /// - /// - void OnUpdate(float deltaTime) - { - Vector2 force = Vector2.Zero; - - if (Input.IsKeyPressed(Key.A)) - { - force.X -= 1000 * deltaTime; - } - - if (Input.IsKeyPressed(Key.D)) - { - force.X += 1000 * deltaTime; - } - - if (Input.IsKeyPressing(Key.Space)) - { - force.Y += 2000; - } - - _rigidBody.ApplyForceToCenter(force); - - //if (Input.IsMouseButtonReleasing(MouseButton.MiddleButton)) - //{ - // Log.Info("Ouha!"); - // Physics2D.Gravity *= new Vector2(1, -1); - //} - } - - /// - /// Called before the component is being destroyed. - /// - void OnDestroy() - { - Log.Trace("Destroy"); - } -} diff --git a/ScriptCore/ScriptCore.csproj b/ScriptCore/ScriptCore.csproj index d1e6d9f..6d16dce 100644 --- a/ScriptCore/ScriptCore.csproj +++ b/ScriptCore/ScriptCore.csproj @@ -48,15 +48,16 @@ - + + + -