Drag'n'drop for components

+ Added CreateInstance to ScriptClass
+ Added CreateComponentInstance to ScriptInstance
This commit is contained in:
Simon Lübeß
2023-07-25 16:37:41 +02:00
parent 37197cbdf1
commit 81a61d5a90
7 changed files with 110 additions and 30 deletions
@@ -66,8 +66,13 @@ namespace Sandbox
Log.Info($"Jump Force: {JumpForce}"); Log.Info($"Jump Force: {JumpForce}");
_rigidBody ??= GetComponent<RigidBody2D>() ?? AddComponent<RigidBody2D>(); //_rigidBody ??= GetComponent<RigidBody2D>() ?? AddComponent<RigidBody2D>();
if (_rigidBody == null)
{
Log.Error("_rigidBody was not set in editor.");
}
if (Camera == null) if (Camera == null)
{ {
Log.Warning("Camera wasn't set in editor. Searching..."); Log.Warning("Camera wasn't set in editor. Searching...");
+16 -16
View File
@@ -72,7 +72,7 @@
Color = { Color = {
R = 1, R = 1,
G = 0.941887021, G = 0.941887021,
B = 0.401484519, B = 0.401484489,
A = 1 A = 1
}, },
Sprite = "", Sprite = "",
@@ -162,7 +162,7 @@
OrthographicHeight = 10, OrthographicHeight = 10,
OrthographicNearPlane = 0, OrthographicNearPlane = 0,
OrthographicFarPlane = 10, OrthographicFarPlane = 10,
AspectRatio = 1.17151165, AspectRatio = 2.05582929,
FixedAspectRatio = false FixedAspectRatio = false
}, },
ScriptComponent = { ScriptComponent = {
@@ -195,8 +195,8 @@
}, },
TransformComponent = { TransformComponent = {
Position = { Position = {
X = -0.121203199, X = -0.121203206,
Y = 0.660161018, Y = 0.660161078,
Z = 0 Z = 0
}, },
Rotation = { Rotation = {
@@ -234,7 +234,7 @@
ScriptComponent = { ScriptComponent = {
ScriptClass = "Sandbox.MyTestEntity", ScriptClass = "Sandbox.MyTestEntity",
Fields = [ Fields = [
_rigidBody = (Component)0, _rigidBody = (Component)15710354273720487680,
TheEntity = (Entity)0, TheEntity = (Entity)0,
JumpForce = (Float)200, JumpForce = (Float)200,
MoveForce = (Float)148, MoveForce = (Float)148,
@@ -276,7 +276,7 @@
Color = { Color = {
R = 0.985467017, R = 0.985467017,
G = 1, G = 1,
B = 0.569977999 B = 0.569977939
} }
} }
}, },
@@ -323,8 +323,8 @@
SpriteRendererComponent = { SpriteRendererComponent = {
Color = { Color = {
R = 0.425658971, R = 0.425658971,
G = 0.855207503, G = 0.855207443,
B = 0.0558161139, B = 0.0558161177,
A = 1 A = 1
}, },
Sprite = "", Sprite = "",
@@ -338,14 +338,14 @@
TransformComponent = { TransformComponent = {
Position = { Position = {
X = 6.74610233, X = 6.74610233,
Y = -2.03225923, Y = -2.03225946,
Z = 0 Z = 0
}, },
Rotation = { Rotation = {
X = 0, X = 0,
Y = 0, Y = 0,
Z = -0.331792623, Z = -0.331792623,
W = 0.943352461 W = 0.94335258
}, },
Scale = { Scale = {
X = 5.29557419, X = 5.29557419,
@@ -399,8 +399,8 @@
}, },
TransformComponent = { TransformComponent = {
Position = { Position = {
X = 15.2321291, X = 15.2321281,
Y = -1.98709261, Y = -1.98709273,
Z = 0 Z = 0
}, },
Rotation = { Rotation = {
@@ -410,7 +410,7 @@
W = 0.990847468 W = 0.990847468
}, },
Scale = { Scale = {
X = 13.9764547, X = 13.9764528,
Y = 1, Y = 1,
Z = 1 Z = 1
}, },
@@ -462,13 +462,13 @@
TransformComponent = { TransformComponent = {
Position = { Position = {
X = -6.27842855, X = -6.27842855,
Y = 2.62550187, Y = 2.62550163,
Z = 0 Z = 0
}, },
Rotation = { Rotation = {
X = 0, X = 0,
Y = 0, Y = 0,
Z = 0.187087849, Z = 0.187087879,
W = 0.982343197 W = 0.982343197
}, },
Scale = { Scale = {
@@ -497,7 +497,7 @@
}, },
Density = 1, Density = 1,
Friction = 0.5, Friction = 0.5,
Restitution = 0.899999917, Restitution = 0.899999857,
RestitutionThreshold = 0.5 RestitutionThreshold = 0.5
} }
} }
@@ -817,11 +817,22 @@ namespace GlitchyEditor.EditWindows
// TODO: I don't like the fact, that we are using mono directly // TODO: I don't like the fact, that we are using mono directly
ScriptField scriptField = scriptClass.Fields[fieldName]; ScriptField scriptField = scriptClass.Fields[fieldName];
MonoReflectionType* reflectionType = Mono.mono_type_get_object(ScriptEngine.[Friend]s_AppDomain, scriptField.GetMonoType());
// TODO: We shouldn't abuse the script glue like that... // For some reason we have to retrieve the MonoType like this. Using scriptField.GetMonoType() directly returns the wrong type...
// ScriptGlue should only be called by C#, not by Beef... MonoReflectionType* reflectionType = Mono.mono_type_get_object(ScriptEngine.[Friend]s_AppDomain, scriptField.GetMonoType());
allowDrop = ScriptGlue.[Friend]Entity_HasComponent(draggedEntity.UUID, reflectionType); MonoType* actualMonoType = Mono.mono_reflection_type_get_type(reflectionType);
// TODO: We shouldn't abuse the script glue like that.
// ScriptGlue should only be called by C#, not by Beef.
if (ScriptGlue.[Friend]s_HasComponentMethods.TryGetValue(actualMonoType, let has_component))
{
allowDrop = has_component(draggedEntity);
}
else
{
Log.EngineLogger.Warning($"No HasComponent-Function found for field {scriptField.Name}");
allowDrop = false;
}
} }
if (allowDrop) if (allowDrop)
@@ -284,6 +284,16 @@ class ScriptClass : SharpClass
return instance; return instance;
} }
public MonoObject* CreateInstance()
{
MonoObject* instance = Mono.mono_object_new(ScriptEngine.[Friend]s_AppDomain, _monoClass);
// Invoke empty constructor to fill fields
Mono.mono_runtime_object_init(instance);
return instance;
}
public MonoMethod* GetMethod(StringView name, int argCount = 0) public MonoMethod* GetMethod(StringView name, int argCount = 0)
{ {
return Mono.mono_class_get_method_from_name(_monoClass, name.ToScopeCStr!(), argCount); return Mono.mono_class_get_method_from_name(_monoClass, name.ToScopeCStr!(), argCount);
+39 -8
View File
@@ -179,6 +179,8 @@ static class ScriptEngine
GetCoreAttributes(); GetCoreAttributes();
GetCoreClasses(); GetCoreClasses();
GetComponentsFromAssemblies();
GetEntitiesFromAssemblies(); GetEntitiesFromAssemblies();
ScriptGlue.RegisterManagedComponents(); ScriptGlue.RegisterManagedComponents();
@@ -214,13 +216,13 @@ static class ScriptEngine
script.Instance.Instantiate(entity.UUID); script.Instance.Instantiate(entity.UUID);
//CopyEditorFieldsToInstance(entity, script);
return true; return true;
} }
public static void CopyEditorFieldsToInstance(Entity entity, ScriptComponent* script) public static void CopyEditorFieldsToInstance(Entity entity, ScriptComponent* script)
{ {
Log.EngineLogger.AssertDebug(script.Instance != null);
// Technically the map is for a different entity (namely the editor-entity), // Technically the map is for a different entity (namely the editor-entity),
// however the UUID is the same, so we get the correct field map // however the UUID is the same, so we get the correct field map
let fields = GetScriptFieldMap(entity); let fields = GetScriptFieldMap(entity);
@@ -242,7 +244,17 @@ static class ScriptEngine
MonoObject* referencedEntity = GetManagedInstance(referencedId); MonoObject* referencedEntity = GetManagedInstance(referencedId);
script.Instance.SetFieldValue(scriptField, referencedEntity); script.Instance.SetFieldValue(scriptField, referencedEntity);
case .Component: case .Component:
// We create a new instance of a component class
MonoType* type = scriptField.GetMonoType();
SharpType sharpType = ScriptEngine.GetSharpType(type);
var componentClass = ComponentClasses[sharpType.FullName];
MonoObject* componentInstance = script.Instance.CreateComponentInstance(componentClass);
script.Instance.SetFieldValue(scriptField, componentInstance);
sharpType.ReleaseRef();
default: default:
script.Instance.SetFieldValue(scriptField, field._data); script.Instance.SetFieldValue(scriptField, field._data);
} }
@@ -362,13 +374,32 @@ static class ScriptEngine
Log.EngineLogger.Info($"Added entity \"{entityScript.FullName}\""); Log.EngineLogger.Info($"Added entity \"{entityScript.FullName}\"");
} }
// Check if it is a component }
else if (monoClass != null && Mono.mono_class_is_subclass_of(monoClass, s_ComponentRoot.[Friend]_monoClass, false)) }
{ private static void GetComponentsFromAssemblies()
ScriptClass entityScript = new ScriptClass(StringView(nameSpace), StringView(name), s_AppAssemblyImage, .Entity); {
_entityScripts.Add(entityScript.FullName, entityScript); ClearDictionaryAndReleaseValues!(_componentClasses);
Log.EngineLogger.Info($"Added entity \"{entityScript.FullName}\""); MonoTableInfo* typeDefinitionsTable = Mono.mono_image_get_table_info(s_CoreAssemblyImage, .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(s_CoreAssemblyImage, (.)cols[(.)SOME_RANDOM_ENUM.MONO_TYPEDEF_NAMESPACE]);
char8* name = Mono.mono_metadata_string_heap(s_CoreAssemblyImage, (.)cols[(.)SOME_RANDOM_ENUM.MONO_TYPEDEF_NAME]);
MonoClass* monoClass = Mono.mono_class_from_name(s_CoreAssemblyImage, nameSpace, name);
// Check if it is a component but not the root Component class
if (monoClass != null && monoClass != s_ComponentRoot.[Friend]_monoClass && Mono.mono_class_is_subclass_of(monoClass, s_ComponentRoot.[Friend]_monoClass, false))
{
ScriptClass componentClass = new ScriptClass(StringView(nameSpace), StringView(name), s_CoreAssemblyImage, .Component);
_componentClasses.Add(componentClass.FullName, componentClass);
Log.EngineLogger.Info($"Added component \"{componentClass.FullName}\"");
} }
} }
} }
@@ -70,4 +70,19 @@ class ScriptInstance : RefCounter
{ {
_scriptClass.SetFieldValue<T>(_instance, field.[Friend]_monoField, value); _scriptClass.SetFieldValue<T>(_instance, field.[Friend]_monoField, value);
} }
/// Creates a new instance of the given component class and initializes it for the current entity.
public MonoObject* CreateComponentInstance(ScriptClass componentClassType)
{
MonoObject* componentInstance = componentClassType.CreateInstance();
// TODO: We could cache the property, but this might be fine
MonoProperty* entityProperty = Mono.mono_class_get_property_from_name(componentClassType.[Friend]_monoClass, "Entity");
MonoObject* exception = null;
Mono.mono_property_set_value(entityProperty, componentInstance, (void**)&_instance, &exception);
return componentInstance;
}
} }
+8
View File
@@ -232,6 +232,12 @@ static class Mono
[LinkName(.C)] [LinkName(.C)]
public static extern MonoThread* mono_thread_current(); public static extern MonoThread* mono_thread_current();
[LinkName(.C)]
public static extern MonoProperty* mono_class_get_property_from_name(MonoClass *klass, char8* name);
[LinkName(.C)]
public static extern void mono_property_set_value(MonoProperty *prop, void *obj, void **@params, MonoObject **exc);
} }
struct MonoDomain; struct MonoDomain;
@@ -250,6 +256,8 @@ struct MonoObject;
struct MonoMethod; struct MonoMethod;
struct MonoProperty;
struct MonoThread; struct MonoThread;
struct MonoException struct MonoException