diff --git a/GlitchyEngine/src/Scripting/ScriptClass.bf b/GlitchyEngine/src/Scripting/ScriptClass.bf index 4c7db3c..996f380 100644 --- a/GlitchyEngine/src/Scripting/ScriptClass.bf +++ b/GlitchyEngine/src/Scripting/ScriptClass.bf @@ -283,6 +283,8 @@ class ScriptClass : SharpClass typealias OnUpdateMethod = function MonoObject*(MonoObject* instance, float deltaTime, MonoException** exception); typealias OnDestroyMethod = function MonoObject*(MonoObject* instance, MonoException** exception); + private bool _runInEditMode; + private MonoMethod* _constructor; private OnCreateMethod _onCreate; @@ -300,6 +302,8 @@ class ScriptClass : SharpClass public bool HasCollisionEnter2D => _onCollisionEnter2DMethod != null; public bool HasCollisionLeave2D => _onCollisionLeave2DMethod != null; + public bool RunInEditMode => _runInEditMode; + [AllowAppend] public this(StringView classNamespace, StringView className, MonoImage* image, ScriptFieldType scriptFieldType = .Class) : base(classNamespace, className, image, scriptFieldType) @@ -314,6 +318,19 @@ class ScriptClass : SharpClass _onCollisionEnter2DMethod = GetMethod("OnCollisionEnter2D", 1); _onCollisionLeave2DMethod = GetMethod("OnCollisionLeave2D", 1); + + DetermineRunInEditMode(); + } + + /// Determines whether or not scripts of this class will be executed in edit mode. + private void DetermineRunInEditMode() + { + // TODO: This is only relevant for the editor! + MonoCustomAttrInfo* attributes = Mono.mono_custom_attrs_from_class(_monoClass); + + if (attributes != null) + _runInEditMode = Mono.mono_custom_attrs_has_attr(attributes, ScriptEngine.Attributes.s_RunInEditModeAttribute); + } private MonoMethod* FindConstructor() diff --git a/GlitchyEngine/src/Scripting/ScriptEngine.bf b/GlitchyEngine/src/Scripting/ScriptEngine.bf index 9626054..9167503 100644 --- a/GlitchyEngine/src/Scripting/ScriptEngine.bf +++ b/GlitchyEngine/src/Scripting/ScriptEngine.bf @@ -5,6 +5,7 @@ using System.Collections; using GlitchyEngine.Core; using GlitchyEngine.Math; using GlitchyEngine.World; +using System.Diagnostics; namespace GlitchyEngine.Scripting; @@ -104,6 +105,7 @@ static class ScriptEngine internal static class Attributes { internal static MonoClass* s_ShowInEditorAttribute; + internal static MonoClass* s_RunInEditModeAttribute; } public static void Init() @@ -553,7 +555,12 @@ static class ScriptEngine /// Retrieves the classes for Attributes that are defined in the Core library static void GetCoreAttributes() { + // We definitely need these attributes! + // TODO: Some only for the editor! Attributes.s_ShowInEditorAttribute = Mono.mono_class_from_name(s_CoreAssemblyImage, "GlitchyEngine.Editor", "ShowInEditorAttribute"); + Debug.Assert(Attributes.s_ShowInEditorAttribute != null); + Attributes.s_RunInEditModeAttribute = Mono.mono_class_from_name(s_CoreAssemblyImage, "GlitchyEngine.Editor", "RunInEditModeAttribute"); + Debug.Assert(Attributes.s_RunInEditModeAttribute != null); } private static void GetEntitiesFromAssemblies() diff --git a/GlitchyEngine/src/World/Scene.bf b/GlitchyEngine/src/World/Scene.bf index d4628e9..316cd4d 100644 --- a/GlitchyEngine/src/World/Scene.bf +++ b/GlitchyEngine/src/World/Scene.bf @@ -600,12 +600,12 @@ namespace GlitchyEngine.World { /// No special update configuration (this does NOT mean nothing will be updated!) None = 0x00, - /// Update editor-specific stuff - Editor = 0x01, /// Update the physics related stuff - Physics = 0x02, + Physics = 0x01, /// Execute scripts. - Scripts = 0x04, + Scripts = 0x02, + /// Update editor-specific stuff and also scripts (most only ever initialize, but some update!) + Editor = 0x04 | Scripts, /// Update the runtume related stuff (e.g. execute scripts). Also run physics! Runtime = Scripts | Physics, } @@ -630,7 +630,10 @@ namespace GlitchyEngine.World if (!script.IsInitialized) ScriptEngine.InitializeInstance(Entity(entity, this), script); - if (script.Instance == null) + // Skip OnCreate and OnUpdate invocation if we didn't create an instance + // (happens, if script component has no script class associated) + // Also skip if we are in edit mode and the class doesn't have the RunInEditMode-Attribute + if (script.Instance == null || (mode.HasFlag(.Editor) && !script.Instance.ScriptClass.RunInEditMode)) continue; if (mode.HasFlag(.Runtime)) diff --git a/GlitchyEngineHelper/src/Mono/Mono.bf b/GlitchyEngineHelper/src/Mono/Mono.bf index 3b4a48d..66e746c 100644 --- a/GlitchyEngineHelper/src/Mono/Mono.bf +++ b/GlitchyEngineHelper/src/Mono/Mono.bf @@ -209,6 +209,9 @@ static class Mono /// Gets the field as object, boxes the value if it is a valuetype. [LinkName(.C)] public static extern MonoObject* mono_field_get_value_object(MonoDomain* domain, MonoClassField* field, MonoObject* obj); + + [LinkName(.C)] + public static extern MonoCustomAttrInfo* mono_custom_attrs_from_class(MonoClass *klass); [LinkName(.C)] public static extern MonoCustomAttrInfo* mono_custom_attrs_from_field(MonoClass* monoClass, MonoClassField* field); diff --git a/ScriptCore/Editor/RunInEditModeAttribute.cs b/ScriptCore/Editor/RunInEditModeAttribute.cs new file mode 100644 index 0000000..59fc529 --- /dev/null +++ b/ScriptCore/Editor/RunInEditModeAttribute.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace GlitchyEngine.Editor; + +/// +/// Specifies that the OnCreate- and OnUpdate-Methods of this entity are to be be executed in the editor. +/// +[AttributeUsage(AttributeTargets.Class)] +public sealed class RunInEditModeAttribute : Attribute +{ +}