Scripting: FindEntityWithName and get script instance

+ Some C# UUID stuff
+ Added some Mono functions
+ ScriptEngine:
  + ID -> ScriptInstance map in ScriptEngine
  + GetManagedInstance

+ Fixed Scene not visible after loading a new scene
  + Renamed OnViewportResize to SetViewportSize for Scene and SceneRenderer
This commit is contained in:
Simon Lübeß
2023-07-17 20:27:18 +02:00
parent 66d66d3308
commit e8505f6bdb
16 changed files with 492 additions and 61 deletions
@@ -0,0 +1,46 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using GlitchyEngine;
using GlitchyEngine.Math;
namespace Sandbox;
public class Camera : Entity
{
public float DistanceFromPlayer = 5.0f;
public float DontFollowRadius = 3.0f;
void OnUpdate(float deltaTime)
{
Entity player = FindEntityWithName("Player");
if (player != null)
{
Vector2 playerPosition = new Vector2(player.Transform.Translation.X, player.Transform.Translation.Y);
Vector2 cameraPosition = new Vector2(Transform.Translation.X, Transform.Translation.Y);
Vector2 distanceVector = playerPosition - cameraPosition;
float distance = distanceVector.Length();
Vector2 neededMovement = Vector2.Zero;
if (distance > DontFollowRadius)
{
neededMovement = distanceVector - (distanceVector / distance) * DontFollowRadius;
}
Transform.Translation = new Vector3(cameraPosition + neededMovement, DistanceFromPlayer);
//Transform.Translation = new Vector3(player.Transform.Translation.X, player.Transform.Translation.Y, DistanceFromPlayer);
}
else
{
Log.Error("Player not found!");
}
}
}
@@ -54,6 +54,8 @@ class MyTestEntity : Entity
public MyStruct AStruct;
public Camera Camera;
/// <summary>
/// Called after the script component was created. (The entity might not be fully created yet)
/// </summary>
@@ -61,7 +63,16 @@ class MyTestEntity : Entity
{
Log.Info($"Create! {UUID}");
Log.Info($"Jump Force: {JumpForce}");
_rigidBody ??= GetComponent<RigidBody2D>() ?? AddComponent<RigidBody2D>();
Camera = FindEntityWithName("Camera").As<Camera>();
if (Camera == null)
{
Log.Error("Camera not found.");
}
}
/// <summary>
@@ -82,6 +93,12 @@ class MyTestEntity : Entity
force.X += MoveForce * deltaTime;
}
if (Input.IsKeyPressed(Key.Q))
Camera.DistanceFromPlayer -= deltaTime;
if (Input.IsKeyPressed(Key.E))
Camera.DistanceFromPlayer += deltaTime;
if (Input.IsKeyPressing(Key.Space))
{
force.Y += JumpForce;
@@ -43,6 +43,7 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Camera.cs" />
<Compile Include="MyTestEntity.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
+240 -13
View File
@@ -23,7 +23,7 @@
},
TransformComponent = {
Position = {
X = 0,
X = -0.72789681,
Y = 2,
Z = 0
},
@@ -71,8 +71,8 @@
SpriteRendererComponent = {
Color = {
R = 1,
G = 0.941886365,
B = 0.401484847,
G = 0.941886961,
B = 0.401484549,
A = 1
},
Sprite = "",
@@ -162,14 +162,20 @@
OrthographicHeight = 10,
OrthographicNearPlane = 0,
OrthographicFarPlane = 10,
AspectRatio = 3.22169805,
AspectRatio = 0.884925187,
FixedAspectRatio = false
}
},
ScriptComponent = {
ScriptClass = "Sandbox.Camera",
Fields = [
DistanceFromPlayer = (Float)-7,
DontFollowRadius = (Float)3
] }
},
{
Id = 15710354273720487680,
NameComponent = {
Name = "Circle"
Name = "Player"
},
CircleRendererComponent = {
Color = {
@@ -189,8 +195,8 @@
},
TransformComponent = {
Position = {
X = -0.12120308,
Y = 0.660160363,
X = -0.121203184,
Y = 0.660160959,
Z = 0
},
Rotation = {
@@ -224,7 +230,42 @@
Friction = 0.5,
Restitution = 0,
RestitutionThreshold = 0.5
}
},
ScriptComponent = {
ScriptClass = "Sandbox.MyTestEntity",
Fields = [
Bo = (Bool)false,
By = (Byte)0,
Us = (UShort)57,
Ui = (UInt)54,
Ul = (ULong)53,
Sb = (SByte)-128,
Sh = (Short)95,
In = (Int)-149,
Lo = (Long)82,
Fl = (Float)-98.122963,
Do = (Double)118,
V2 = (float2){
X = 11,
Y = 12
},
V3 = (float3){
X = 13,
Y = 14,
Z = 15
},
V4 = (float4){
X = 14,
Y = 17,
Z = 18,
W = 19
},
TheEntity = (Entity)0,
JumpForce = (Float)200,
MoveForce = (Float)148,
MyNumber = (Int)22,
MyDouble = (Double)23
] }
},
{
Id = 935640822766280888,
@@ -249,9 +290,9 @@
Z = 1
},
EditorEulerRotation = {
X = 1.0908947,
X = 1.09089541,
Y = -0.340793997,
Z = 0.160857916
Z = 0.160857871
}
},
LightComponent = {
@@ -260,7 +301,7 @@
Color = {
R = 0.985467017,
G = 1,
B = 0.569978654
B = 0.569978058
}
}
},
@@ -273,7 +314,7 @@
Position = {
X = 0,
Y = 0,
Z = -1.47202551
Z = 2.56930423
},
Rotation = {
X = 0,
@@ -298,6 +339,192 @@
MeshRendererComponent = {
Material = "Textures/TestMaterial.mat"
}
},
{
Id = 2241063100006479259,
NameComponent = {
Name = "Floor 2"
},
SpriteRendererComponent = {
Color = {
R = 0.425658971,
G = 0.855207562,
B = 0.0558161102,
A = 1
},
Sprite = "",
UvTransform = {
X = 0,
Y = 0,
Z = 1,
W = 1
}
},
TransformComponent = {
Position = {
X = 6.74610233,
Y = -2.03225899,
Z = 0
},
Rotation = {
X = 0,
Y = 0,
Z = -0.331792623,
W = 0.943352342
},
Scale = {
X = 5.29557419,
Y = 1,
Z = 1
},
EditorEulerRotation = {
X = 0,
Y = 0,
Z = -0.676406503
}
},
Rigidbody2D = {
BodyType = .Static,
FixedRotation = false
},
BoxCollider2D = {
Offset = {
X = 0,
Y = 0
},
Size = {
X = 0.5,
Y = 0.5
},
Density = 1,
Friction = 0.5,
Restitution = 0,
RestitutionThreshold = 0.5
}
},
{
Id = 5126705881069187728,
NameComponent = {
Name = "Floor 3"
},
SpriteRendererComponent = {
Color = {
R = 0.666116953,
G = 0.0600316115,
B = 1,
A = 1
},
Sprite = "",
UvTransform = {
X = 0,
Y = 0,
Z = 1,
W = 1
}
},
TransformComponent = {
Position = {
X = 15.2321301,
Y = -1.98709249,
Z = 0
},
Rotation = {
X = 0,
Y = 0,
Z = 0.134986058,
W = 0.990847468
},
Scale = {
X = 13.9764566,
Y = 1,
Z = 1
},
EditorEulerRotation = {
X = 0,
Y = 0,
Z = 0.270798802
}
},
Rigidbody2D = {
BodyType = .Static,
FixedRotation = false
},
BoxCollider2D = {
Offset = {
X = 0,
Y = 0
},
Size = {
X = 0.5,
Y = 0.5
},
Density = 1,
Friction = 0.5,
Restitution = 0.800000012,
RestitutionThreshold = 0.5
}
},
{
Id = 6861260438693901700,
NameComponent = {
Name = "Floor 4"
},
SpriteRendererComponent = {
Color = {
R = 0.176544324,
G = 0.666713238,
B = 0.687030852,
A = 1
},
Sprite = "",
UvTransform = {
X = 0,
Y = 0,
Z = 1,
W = 1
}
},
TransformComponent = {
Position = {
X = -6.27842855,
Y = 2.62550211,
Z = 0
},
Rotation = {
X = 0,
Y = 0,
Z = 0.187087834,
W = 0.982343197
},
Scale = {
X = 0.999999523,
Y = 6.49634314,
Z = 1
},
EditorEulerRotation = {
X = 0,
Y = 0,
Z = 0.376393586
}
},
Rigidbody2D = {
BodyType = .Static,
FixedRotation = false
},
BoxCollider2D = {
Offset = {
X = 0,
Y = 0
},
Size = {
X = 0.5,
Y = 0.5
},
Density = 1,
Friction = 0.5,
Restitution = 0.899999976,
RestitutionThreshold = 0.5
}
}
]
}
+22 -15
View File
@@ -206,6 +206,20 @@ namespace GlitchyEditor
// Clear the swapchain-buffer
RenderCommand.Clear(null, .Color | .Depth, .(0.2f, 0.2f, 0.2f), 1.0f, 0);
RenderCommand.SetBlendState(_alphaBlendState);
RenderCommand.SetDepthStencilState(_depthStencilState);
if (_editor.GameViewportWindow.Visible)
{
_gameSceneRenderer.Scene = _activeScene;
_activeScene.SetViewportSize((uint32)_editor.GameViewportWindow.ViewportSize.X, (uint32)_editor.GameViewportWindow.ViewportSize.Y);
_gameSceneRenderer.SetViewportSize((uint32)_editor.GameViewportWindow.ViewportSize.X, (uint32)_editor.GameViewportWindow.ViewportSize.Y);
RenderCommand.Clear(_gameViewportTarget, .Color | .Depth, .(0.2f, 0.2f, 0.2f), 1.0f, 0);
_gameSceneRenderer.RenderRuntime(gameTime, _gameViewportTarget);
}
RenderCommand.SetBlendState(_alphaBlendState);
RenderCommand.SetDepthStencilState(_depthStencilState);
@@ -215,21 +229,16 @@ namespace GlitchyEditor
_editorSceneRenderer.Scene = _activeScene;
// Only use aspect ratio of editor-window, if game is not being rendered
if (!_editor.GameViewportWindow.Visible)
_activeScene.SetViewportSize((uint32)_editor.SceneViewportWindow.ViewportSize.X, (uint32)_editor.SceneViewportWindow.ViewportSize.Y);
_editorSceneRenderer.SetViewportSize((uint32)_editor.SceneViewportWindow.ViewportSize.X, (uint32)_editor.SceneViewportWindow.ViewportSize.Y);
RenderCommand.Clear(_editorViewportTarget, .Color | .Depth, .(0.2f, 0.2f, 0.2f), 1.0f, 0);
_editorSceneRenderer.RenderEditor(gameTime, _camera, _editorViewportTarget, scope => DebugDraw3D, scope => DebugDraw2D);
}
RenderCommand.SetBlendState(_alphaBlendState);
RenderCommand.SetDepthStencilState(_depthStencilState);
if (_editor.GameViewportWindow.Visible)
{
_gameSceneRenderer.Scene = _activeScene;
RenderCommand.Clear(_gameViewportTarget, .Color | .Depth, .(0.2f, 0.2f, 0.2f), 1.0f, 0);
_gameSceneRenderer.RenderRuntime(gameTime, _gameViewportTarget);
}
RenderCommand.UnbindRenderTargets();
RenderCommand.SetRenderTarget(null, 0, true);
RenderCommand.BindRenderTargets();
@@ -742,7 +751,7 @@ namespace GlitchyEditor
_camera.OnViewportResize(sizeX, sizeY);
_editorSceneRenderer.OnViewportResize(sizeX, sizeY);
_activeScene.SetViewportSize(sizeX, sizeY);
}
private void GameViewportSizeChanged(Object sender, float2 viewportSize)
@@ -755,9 +764,7 @@ namespace GlitchyEditor
_gameViewportTarget.Resize(sizeX, sizeY);
_activeScene.OnViewportResize(sizeX, sizeY);
_gameSceneRenderer.OnViewportResize(sizeX, sizeY);
_activeScene.SetViewportSize(sizeX, sizeY);
}
private bool OnKeyPressed(KeyPressedEvent e)
@@ -90,6 +90,11 @@ class SharpClass : SharpType
ExtractFields();
}
internal bool IsType(MonoType* type)
{
return Mono.mono_class_get_type(_monoClass) == type;
}
private void ExtractFields()
{
//_monoFields = new List<MonoClassField*>();´
+12 -6
View File
@@ -151,13 +151,13 @@ static class ScriptEngine
private static Dictionary<StringView, ScriptClass> _entityScripts = new .() ~ DeleteDictionaryAndReleaseValues!(_);
/*private static Dictionary<UUID, ScriptInstance> _entityScriptInstances = new .() ~ {
private static Dictionary<UUID, ScriptInstance> _entityScriptInstances = new .() ~ {
for (var entry in _)
{
entry.value?.ReleaseRef();
}
delete _;
};*/
}
public static Dictionary<StringView, ScriptClass> EntityClasses => _entityScripts;
@@ -197,18 +197,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);
@@ -403,7 +403,13 @@ static class ScriptEngine
return _entityFields[uuid];
}
public static MonoObject* GetManagedInstance(UUID entityId)
{
if (_entityScriptInstances.TryGetValue(entityId, let scriptInstance))
return scriptInstance.MonoInstance;
return null;
}
+24 -4
View File
@@ -11,6 +11,8 @@ using Box2D;
namespace GlitchyEngine.Scripting;
using internal GlitchyEngine.Scripting;
static class ScriptGlue
{
private static Dictionary<MonoType*, function void(Entity entityId)> s_AddComponentMethods = new .() ~ delete _;
@@ -176,11 +178,29 @@ static class ScriptGlue
else
Log.EngineLogger.AssertDebug(false, "No managed component with the given type registered.");
}
/*[RegisterCall("Input::IsMouseButtonReleasing")]
static void Destroy()
[RegisterCall("ScriptGlue::Entity_FindEntityWithName")]
static void Entity_FindEntityWithName(MonoString* monoName, UUID* outUuid)
{
// TODO:
}*/
*outUuid = UUID(0);
char8* entityName = Mono.mono_string_to_utf8(monoName);
StringView nameString = StringView(entityName);
Result<Entity> entityResult = ScriptEngine.Context.GetEntityByName(nameString);
Mono.mono_free(entityName);
if (entityResult case .Ok(let entity))
*outUuid = entity.UUID;
}
[RegisterCall("ScriptGlue::Entity_GetScriptInstance")]
static MonoObject* Entity_GetScriptInstance(UUID entityId)
{
return ScriptEngine.GetManagedInstance(entityId);
}
#endregion
@@ -37,6 +37,8 @@ class ScriptInstance : RefCounter
_scriptClass?.ReleaseRef();
}
internal MonoObject* MonoInstance => _instance;
public void Instantiate(UUID uuid)
{
_instance = _scriptClass.CreateInstance(uuid);
+19 -4
View File
@@ -92,7 +92,8 @@ namespace GlitchyEngine.World
Entity targetEntity = target.GetEntityByID(sourceEntity.UUID);
ScriptComponent* targetComponent = targetEntity.AddComponent<ScriptComponent>();
targetComponent.ScriptClass = sourceComponent.ScriptClass;
targetComponent.Instance = new ScriptInstance(sourceComponent.ScriptClass);
targetComponent.Instance..ReleaseRef();
@@ -116,7 +117,7 @@ namespace GlitchyEngine.World
}
}
target.OnViewportResize(_viewportWidth, _viewportHeight);
//target.SetViewportSize(_viewportWidth, _viewportHeight);
}
private static void CopyComponents<TComponent>(Scene source, Scene target) where TComponent : struct, new
@@ -376,9 +377,23 @@ namespace GlitchyEngine.World
return .Err;
}
/// Sets the size of the viewport into which the scene will be rendered.
public void OnViewportResize(uint32 width, uint32 height)
public Result<Entity> GetEntityByName(StringView name)
{
for (let (ecsEntity, nameComponent) in GetEntities<NameComponent>())
{
if (nameComponent.Name == name)
return .Ok(Entity(ecsEntity, this));
}
return .Err;
}
/// Sets the size of the viewport into which the scene will be rendered.
public void SetViewportSize(uint32 width, uint32 height)
{
if (_viewportWidth == width && _viewportHeight == height)
return;
_viewportWidth = width;
_viewportHeight = height;
+4 -1
View File
@@ -45,8 +45,11 @@ class SceneRenderer
}
/// Sets the size of the viewport into which the scene will be rendered.
public void OnViewportResize(uint32 width, uint32 height)
public void SetViewportSize(uint32 width, uint32 height)
{
if (_viewportWidth == width && _viewportHeight == height)
return;
_viewportWidth = width;
_viewportHeight = height;
+27 -1
View File
@@ -79,9 +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 MonoClass* mono_class_from_mono_type(MonoType* type);
[LinkName(.C)]
public static extern char8* mono_class_get_name(MonoClass* monoClass);
[LinkName(.C)]
public static extern MonoType* mono_class_get_type(MonoClass* monoClass);
[LinkName(.C)]
public static extern char8* mono_class_get_namespace(MonoClass* monoClass);
@@ -131,6 +137,9 @@ static class Mono
[LinkName(.C)]
public static extern char8* mono_string_to_utf8(MonoString *s);
[LinkName(.C)]
public static extern char8* mono_string_to_utf8_checked(MonoString *s, MonoError* error);
[LinkName(.C)]
public static extern void mono_free(void* ptr);
@@ -188,6 +197,17 @@ static class Mono
[LinkName(.C)]
public static extern MonoClass* mono_type_get_class(MonoType* type);
/// MonoError
[LinkName(.C)]
public static extern void mono_error_cleanup(MonoError* error);
[LinkName(.C)]
public static extern mono_bool mono_error_ok(MonoError* error);
[LinkName(.C)]
public static extern char8* mono_error_get_message(MonoError* error);
}
struct MonoDomain;
@@ -212,6 +232,12 @@ struct MonoClassField;
struct MonoType;
struct MonoError
{
private uint32 bla;
private void*[12] bla2;
}
struct MonoReflectionType;
struct MonoCustomAttrInfo;
+16
View File
@@ -3,4 +3,20 @@ namespace GlitchyEngine.Core;
public struct UUID
{
private ulong _uuid;
public UUID(ulong uuid)
{
_uuid = uuid;
}
public static UUID Zero = new UUID(0);
public static bool operator ==(UUID left, UUID right) => left._uuid == right._uuid;
public static bool operator !=(UUID left, UUID right) => left._uuid != right._uuid;
public override string ToString()
{
return _uuid.ToString();
}
}
+44 -15
View File
@@ -1,5 +1,7 @@
using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Xml.Linq;
using GlitchyEngine.Core;
using GlitchyEngine.Math;
@@ -11,22 +13,22 @@ internal struct EntityHandle
public uint Index;
}
public abstract class Entity : EngineObject
public class Entity : EngineObject
{
//private UUID _uuid;
//public UUID UUID => _uuid;
///// <summary>
///// Empty constructor not used. Do NOT USE!
///// </summary>
//protected Entity()
//{}
/// <summary>
/// Empty constructor not used. Do NOT USE!
/// </summary>
protected Entity()
{ }
//internal Entity(UUID uuid)
//{
// _uuid = uuid;
//}
private Entity(UUID uuid)
{
_uuid = uuid;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool HasComponent<T>() => HasComponent(typeof(T));
@@ -41,8 +43,6 @@ public abstract class Entity : EngineObject
/// <returns>The component or null, if the entity doesn't have a component of the specified type.</returns>
public T GetComponent<T>() where T : Component, new()
{
Log.Info("Trying to get component");
if (HasComponent<T>())
{
return new T
@@ -129,10 +129,39 @@ public abstract class Entity : EngineObject
public Transform Transform => GetComponent<Transform>();
public Vector3 Translation
//public Vector3 Translation
//{
// get => Transform.Translation;
// set => Transform.Translation = value;
//}
/// <summary>
/// Returns the first entity with the given name.
/// </summary>
/// <param name="name">The name of the entity.</param>
/// <returns>The first entity with the given name, or null.</returns>
public static Entity FindEntityWithName(string name)
{
get => Transform.Translation;
set => Transform.Translation = value;
ScriptGlue.Entity_FindEntityWithName(name, out UUID entityId);
Log.Error($"Found EntityID {entityId}");
if (entityId == UUID.Zero)
return null;
return new Entity(entityId);
}
/// <summary>
/// Returns the script of the given type, or null, if the entity has no script of the given type.
/// </summary>
/// <typeparam name="T">The type of the script.</typeparam>
/// <returns>The script instance or null.</returns>
public T As<T>() where T : Entity
{
object scriptInstance = ScriptGlue.Entity_GetScriptInstance(_uuid);
return scriptInstance as T;
}
// Will be executed once after the entity as be created.
+6 -1
View File
@@ -99,7 +99,12 @@ public struct Vector2
{
return !(a == b);
}
public float Length()
{
return (float)System.Math.Sqrt(X * X + Y * Y);
}
public override int GetHashCode()
{
unchecked
+7 -1
View File
@@ -20,7 +20,13 @@ internal static class ScriptGlue
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern void Entity_RemoveComponent(UUID entityId, Type componentType);
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern void Entity_FindEntityWithName(string name, out UUID uuid);
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern object Entity_GetScriptInstance(UUID entityId);
#endregion Entity
#region TransformComponent