mirror of
https://github.com/aharabada/glitchy-engine-beef.git
synced 2026-09-05 13:01:52 +00:00
Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
499ca0311c | ||
|
|
62c85e9e1f | ||
|
|
8296f1c5cd |
+4
-1
@@ -30,4 +30,7 @@
|
|||||||
url = https://github.com/jazzbre/box2d-beef.git
|
url = https://github.com/jazzbre/box2d-beef.git
|
||||||
[submodule "GlitchyEngine/vendor/Beef.Linq"]
|
[submodule "GlitchyEngine/vendor/Beef.Linq"]
|
||||||
path = GlitchyEngine/vendor/Beef.Linq
|
path = GlitchyEngine/vendor/Beef.Linq
|
||||||
url = https://github.com/aharabada/Beef.Linq.git
|
url = https://github.com/aharabada/Beef.Linq.git
|
||||||
|
[submodule "GlitchyEngine/vendor/NetHostBeef"]
|
||||||
|
path = GlitchyEngine/vendor/NetHostBeef
|
||||||
|
url = https://github.com/aharabada/NetHostBeef.git
|
||||||
|
|||||||
+2
-2
@@ -1,7 +1,7 @@
|
|||||||
FileVersion = 1
|
FileVersion = 1
|
||||||
Projects = {Sandbox = {Path = "Sandbox"}, GlitchyEngine = {Path = "GlitchyEngine"}, GlitchLog = {Path = "GlitchLog"}, DirectX = {Path = "GlitchyEngine/vendor/directx/DirectX"}, LodePng = {Path = "vendor/lodepng-beef/lodepng-beef"}, FreeType = {Path = "GlitchyEngine/vendor/freetype"}, cgltf-beef = {Path = "GlitchyEngine/vendor/gltf/cgltf-beef"}, GlitchyEditor = {Path = "GlitchyEditor"}, msdfgen-beef = {Path = "GlitchyEngine/vendor/msdfgen/msdfgen-beef"}, ImGui = {Path = "GlitchyEngine/vendor/imgui/ImGui"}, ImGuiImplDX11 = {Path = "GlitchyEngine/vendor/imgui/ImGuiImplDX11"}, ImGuiImplWin32 = {Path = "GlitchyEngine/vendor/imgui/ImGuiImplWin32"}, ImGuizmo = {Path = "GlitchyEngine/vendor/imgui/ImGuizmo"}, GlitchyEngineHelper = {Path = "GlitchyEngineHelper"}, bon = {Path = "GlitchyEngine/vendor/bon"}, box2d-beef = {Path = "GlitchyEngine/vendor/box2D"}, "Beef.Linq" = {Path = "GlitchyEngine/vendor/Beef.Linq/src"}, ScriptCore = {Path = "ScriptCore"}}
|
Projects = {Sandbox = {Path = "Sandbox"}, GlitchyEngine = {Path = "GlitchyEngine"}, GlitchLog = {Path = "GlitchLog"}, DirectX = {Path = "GlitchyEngine/vendor/directx/DirectX"}, LodePng = {Path = "vendor/lodepng-beef/lodepng-beef"}, FreeType = {Path = "GlitchyEngine/vendor/freetype"}, cgltf-beef = {Path = "GlitchyEngine/vendor/gltf/cgltf-beef"}, GlitchyEditor = {Path = "GlitchyEditor"}, msdfgen-beef = {Path = "GlitchyEngine/vendor/msdfgen/msdfgen-beef"}, ImGui = {Path = "GlitchyEngine/vendor/imgui/ImGui"}, ImGuiImplDX11 = {Path = "GlitchyEngine/vendor/imgui/ImGuiImplDX11"}, ImGuiImplWin32 = {Path = "GlitchyEngine/vendor/imgui/ImGuiImplWin32"}, ImGuizmo = {Path = "GlitchyEngine/vendor/imgui/ImGuizmo"}, GlitchyEngineHelper = {Path = "GlitchyEngineHelper"}, bon = {Path = "GlitchyEngine/vendor/bon"}, box2d-beef = {Path = "GlitchyEngine/vendor/box2D"}, "Beef.Linq" = {Path = "GlitchyEngine/vendor/Beef.Linq/src"}, ScriptCore = {Path = "ScriptCore"}, NetHostBeef = {Path = "GlitchyEngine/vendor/NetHostBeef/NetHostBeef"}}
|
||||||
Unlocked = ["corlib"]
|
Unlocked = ["corlib"]
|
||||||
WorkspaceFolders = {GlitchyEngine = ["GlitchyEngine", "GlitchLog", "GlitchyEngineHelper", "ScriptCore"], "GlitchyEngine/Dependencies" = ["cgltf-beef", "DirectX", "FreeType", "ImGui", "ImGuiImplDX11", "ImGuiImplWin32", "ImGuizmo", "LodePng", "msdfgen-beef", "bon", "box2d-beef", "Beef.Linq"]}
|
WorkspaceFolders = {GlitchyEngine = ["GlitchyEngine", "GlitchLog", "GlitchyEngineHelper", "ScriptCore"], "GlitchyEngine/Dependencies" = ["cgltf-beef", "DirectX", "FreeType", "ImGui", "ImGuiImplDX11", "ImGuiImplWin32", "ImGuizmo", "LodePng", "msdfgen-beef", "bon", "box2d-beef", "Beef.Linq", "NetHostBeef"]}
|
||||||
|
|
||||||
[Workspace]
|
[Workspace]
|
||||||
StartupProject = "GlitchyEditor"
|
StartupProject = "GlitchyEditor"
|
||||||
|
|||||||
@@ -15,32 +15,39 @@ public class Camera : Entity
|
|||||||
|
|
||||||
public float DontFollowRadius = 3.0f;
|
public float DontFollowRadius = 3.0f;
|
||||||
|
|
||||||
void OnUpdate(float deltaTime)
|
void OnCreate()
|
||||||
{
|
{
|
||||||
Entity player = FindEntityWithName("Player");
|
Log.Info("Camera Create");
|
||||||
|
}
|
||||||
|
|
||||||
if (player != null)
|
public void OnUpdate(float deltaTime)
|
||||||
{
|
{
|
||||||
float2 playerPosition = player.Transform.Translation.XY;
|
Log.Info($"Camera Update {deltaTime}");
|
||||||
|
|
||||||
float2 cameraPosition = Transform.Translation.XY;
|
//Entity player = FindEntityWithName("Player");
|
||||||
|
|
||||||
float2 distanceVector = playerPosition - cameraPosition;
|
//if (player != null)
|
||||||
|
//{
|
||||||
|
// float2 playerPosition = player.Transform.Translation.XY;
|
||||||
|
|
||||||
float distance = length(distanceVector);
|
// float2 cameraPosition = Transform.Translation.XY;
|
||||||
|
|
||||||
float2 neededMovement = float2.Zero;
|
// float2 distanceVector = playerPosition - cameraPosition;
|
||||||
|
|
||||||
if (distance > DontFollowRadius)
|
// float distance = length(distanceVector);
|
||||||
{
|
|
||||||
neededMovement = distanceVector - (distanceVector / distance) * DontFollowRadius;
|
|
||||||
}
|
|
||||||
|
|
||||||
Transform.Translation = new float3(cameraPosition + neededMovement, DistanceFromPlayer);
|
// float2 neededMovement = float2.Zero;
|
||||||
}
|
|
||||||
else
|
// if (distance > DontFollowRadius)
|
||||||
{
|
// {
|
||||||
Log.Error("Player not found!");
|
// neededMovement = distanceVector - (distanceVector / distance) * DontFollowRadius;
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
// Transform.Translation = new float3(cameraPosition + neededMovement, DistanceFromPlayer);
|
||||||
|
//}
|
||||||
|
//else
|
||||||
|
//{
|
||||||
|
// Log.Error("Player not found!");
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Runtime.Remoting.Metadata.W3cXsd2001;
|
|
||||||
using GlitchyEngine;
|
using GlitchyEngine;
|
||||||
using GlitchyEngine.Editor;
|
using GlitchyEngine.Editor;
|
||||||
using GlitchyEngine.Math;
|
using GlitchyEngine.Math;
|
||||||
@@ -66,14 +65,14 @@ namespace Sandbox
|
|||||||
|
|
||||||
Log.Info($"Jump Force: {JumpForce}");
|
Log.Info($"Jump Force: {JumpForce}");
|
||||||
|
|
||||||
_rigidBody ??= GetComponent<RigidBody2D>() ?? AddComponent<RigidBody2D>();
|
//_rigidBody ??= GetComponent<RigidBody2D>() ?? AddComponent<RigidBody2D>();
|
||||||
|
|
||||||
Camera = FindEntityWithName("Camera").As<Camera>();
|
//Camera = FindEntityWithName("Camera").As<Camera>();
|
||||||
|
|
||||||
if (Camera == null)
|
//if (Camera == null)
|
||||||
{
|
//{
|
||||||
Log.Error("Camera not found.");
|
// Log.Error("Camera not found.");
|
||||||
}
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -82,36 +81,38 @@ namespace Sandbox
|
|||||||
/// <param name="deltaTime"></param>
|
/// <param name="deltaTime"></param>
|
||||||
void OnUpdate(float deltaTime)
|
void OnUpdate(float deltaTime)
|
||||||
{
|
{
|
||||||
float2 force = float2.Zero;
|
Log.Info($"On update: {deltaTime}");
|
||||||
|
|
||||||
if (Input.IsKeyPressed(Key.A))
|
//float2 force = float2.Zero;
|
||||||
{
|
|
||||||
force.X -= MoveForce * deltaTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Input.IsKeyPressed(Key.D))
|
//if (Input.IsKeyPressed(Key.A))
|
||||||
{
|
//{
|
||||||
force.X += MoveForce * deltaTime;
|
// force.X -= MoveForce * deltaTime;
|
||||||
}
|
//}
|
||||||
|
|
||||||
if (Input.IsKeyPressed(Key.Q))
|
//if (Input.IsKeyPressed(Key.D))
|
||||||
Camera.DistanceFromPlayer -= deltaTime;
|
//{
|
||||||
|
// force.X += MoveForce * deltaTime;
|
||||||
|
//}
|
||||||
|
|
||||||
if (Input.IsKeyPressed(Key.E))
|
//if (Input.IsKeyPressed(Key.Q))
|
||||||
Camera.DistanceFromPlayer += deltaTime;
|
// Camera.DistanceFromPlayer -= deltaTime;
|
||||||
|
|
||||||
if (Input.IsKeyPressing(Key.Space))
|
//if (Input.IsKeyPressed(Key.E))
|
||||||
{
|
// Camera.DistanceFromPlayer += deltaTime;
|
||||||
force.Y += JumpForce;
|
|
||||||
}
|
|
||||||
|
|
||||||
_rigidBody.ApplyForceToCenter(force);
|
//if (Input.IsKeyPressing(Key.Space))
|
||||||
|
//{
|
||||||
|
// force.Y += JumpForce;
|
||||||
|
//}
|
||||||
|
|
||||||
if (Input.IsMouseButtonReleasing(MouseButton.MiddleButton))
|
//_rigidBody.ApplyForceToCenter(force);
|
||||||
{
|
|
||||||
Log.Info($"Ouha! {MyNumber}");
|
//if (Input.IsMouseButtonReleasing(MouseButton.MiddleButton))
|
||||||
Physics2D.Gravity *= new float2(1, -1);
|
//{
|
||||||
}
|
// Log.Info($"Ouha! {MyNumber}");
|
||||||
|
// Physics2D.Gravity *= new float2(1, -1);
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -1,36 +0,0 @@
|
|||||||
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")]
|
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"profiles": {
|
||||||
|
"Start Editor": {
|
||||||
|
"commandName": "Executable",
|
||||||
|
"executablePath": "D:\\Development\\Projects\\Beef\\GlitchyEngine\\build\\Debug_Win64\\GlitchyEditor\\GlitchyEditor.exe",
|
||||||
|
"commandLineArgs": "\"content\\Scenes\\physics2D.scene\"",
|
||||||
|
"workingDirectory": "D:\\Development\\Projects\\Beef\\GlitchyEngine\\GlitchyEditor",
|
||||||
|
"nativeDebugging": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||||
|
<PropertyGroup>
|
||||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
|
<ProjectGuid>{7A70819C-5317-402A-8553-95C5A001E370}</ProjectGuid>
|
||||||
|
<OutputType>Library</OutputType>
|
||||||
|
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||||
|
<RootNamespace>Sandbox</RootNamespace>
|
||||||
|
<AssemblyName>Sandbox</AssemblyName>
|
||||||
|
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
||||||
|
<FileAlignment>512</FileAlignment>
|
||||||
|
<Deterministic>true</Deterministic>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<Optimize>false</Optimize>
|
||||||
|
<OutputPath>bin\</OutputPath>
|
||||||
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
<LangVersion>default</LangVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<OutputPath>bin\</OutputPath>
|
||||||
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
<LangVersion>default</LangVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="System" />
|
||||||
|
<Reference Include="System.Core" />
|
||||||
|
<Reference Include="System.Xml.Linq" />
|
||||||
|
<Reference Include="System.Data.DataSetExtensions" />
|
||||||
|
<Reference Include="Microsoft.CSharp" />
|
||||||
|
<Reference Include="System.Data" />
|
||||||
|
<Reference Include="System.Net.Http" />
|
||||||
|
<Reference Include="System.Xml" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="Camera.cs" />
|
||||||
|
<Compile Include="MyTestEntity.cs" />
|
||||||
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\..\..\ScriptCore\ScriptCore.csproj">
|
||||||
|
<Project>{6222c226-fc78-498c-80ba-5cf10ac9123c}</Project>
|
||||||
|
<Name>ScriptCore</Name>
|
||||||
|
</ProjectReference>
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
|
</Project>
|
||||||
@@ -1,57 +1,16 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
<LangVersion>latest</LangVersion>
|
||||||
<ProjectGuid>{7A70819C-5317-402A-8553-95C5A001E370}</ProjectGuid>
|
<OutputPath>bin</OutputPath>
|
||||||
<OutputType>Library</OutputType>
|
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
|
||||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
|
||||||
<RootNamespace>Sandbox</RootNamespace>
|
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
|
||||||
<AssemblyName>Sandbox</AssemblyName>
|
<EnableDynamicLoading>true</EnableDynamicLoading>
|
||||||
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||||
<FileAlignment>512</FileAlignment>
|
|
||||||
<Deterministic>true</Deterministic>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
|
||||||
<DebugSymbols>true</DebugSymbols>
|
|
||||||
<DebugType>full</DebugType>
|
|
||||||
<Optimize>false</Optimize>
|
|
||||||
<OutputPath>bin\</OutputPath>
|
|
||||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
|
||||||
<ErrorReport>prompt</ErrorReport>
|
|
||||||
<WarningLevel>4</WarningLevel>
|
|
||||||
<LangVersion>default</LangVersion>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
|
||||||
<DebugType>pdbonly</DebugType>
|
|
||||||
<Optimize>true</Optimize>
|
|
||||||
<OutputPath>bin\</OutputPath>
|
|
||||||
<DefineConstants>TRACE</DefineConstants>
|
|
||||||
<ErrorReport>prompt</ErrorReport>
|
|
||||||
<WarningLevel>4</WarningLevel>
|
|
||||||
<LangVersion>default</LangVersion>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="System" />
|
<ProjectReference Include="..\..\..\..\ScriptCore\ScriptCore.csproj" />
|
||||||
<Reference Include="System.Core" />
|
|
||||||
<Reference Include="System.Xml.Linq" />
|
|
||||||
<Reference Include="System.Data.DataSetExtensions" />
|
|
||||||
<Reference Include="Microsoft.CSharp" />
|
|
||||||
<Reference Include="System.Data" />
|
|
||||||
<Reference Include="System.Net.Http" />
|
|
||||||
<Reference Include="System.Xml" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
|
||||||
<Compile Include="Camera.cs" />
|
</Project>
|
||||||
<Compile Include="MyTestEntity.cs" />
|
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\..\..\..\ScriptCore\ScriptCore.csproj">
|
|
||||||
<Project>{6222c226-fc78-498c-80ba-5cf10ac9123c}</Project>
|
|
||||||
<Name>ScriptCore</Name>
|
|
||||||
</ProjectReference>
|
|
||||||
</ItemGroup>
|
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
|
||||||
</Project>
|
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using GlitchyEngine;
|
||||||
|
|
||||||
|
namespace Sandbox;
|
||||||
|
|
||||||
|
public static class TestClass
|
||||||
|
{
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
|
public static void TestFunction()
|
||||||
|
{
|
||||||
|
Console.WriteLine("Hello from the second Assembly!");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void InternalTest()
|
||||||
|
{
|
||||||
|
Console.WriteLine("Ja, ich existiere in der Tat");
|
||||||
|
|
||||||
|
Log.Info("Yeah!");
|
||||||
|
//Console.WriteLine("Und nun bin ich anders");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int Test(IntPtr arg, int sizeofArg)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"YUPPYPLASDPASDOIUZASD");
|
||||||
|
return 7;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,25 +1,15 @@
|
|||||||
{
|
{
|
||||||
"runtimeTarget": {
|
"runtimeTarget": {
|
||||||
"name": ".NETStandard,Version=v2.0/",
|
"name": ".NETCoreApp,Version=v7.0",
|
||||||
"signature": ""
|
"signature": ""
|
||||||
},
|
},
|
||||||
"compilationOptions": {},
|
"compilationOptions": {},
|
||||||
"targets": {
|
"targets": {
|
||||||
".NETStandard,Version=v2.0": {},
|
".NETCoreApp,Version=v7.0": {
|
||||||
".NETStandard,Version=v2.0/": {
|
|
||||||
"ScriptCore/1.0.0": {
|
"ScriptCore/1.0.0": {
|
||||||
"dependencies": {
|
|
||||||
"NETStandard.Library": "2.0.3"
|
|
||||||
},
|
|
||||||
"runtime": {
|
"runtime": {
|
||||||
"ScriptCore.dll": {}
|
"ScriptCore.dll": {}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"Microsoft.NETCore.Platforms/1.1.0": {},
|
|
||||||
"NETStandard.Library/2.0.3": {
|
|
||||||
"dependencies": {
|
|
||||||
"Microsoft.NETCore.Platforms": "1.1.0"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -28,20 +18,6 @@
|
|||||||
"type": "project",
|
"type": "project",
|
||||||
"serviceable": false,
|
"serviceable": false,
|
||||||
"sha512": ""
|
"sha512": ""
|
||||||
},
|
|
||||||
"Microsoft.NETCore.Platforms/1.1.0": {
|
|
||||||
"type": "package",
|
|
||||||
"serviceable": true,
|
|
||||||
"sha512": "sha512-kz0PEW2lhqygehI/d6XsPCQzD7ff7gUJaVGPVETX611eadGsA3A877GdSlU0LRVMCTH/+P3o2iDTak+S08V2+A==",
|
|
||||||
"path": "microsoft.netcore.platforms/1.1.0",
|
|
||||||
"hashPath": "microsoft.netcore.platforms.1.1.0.nupkg.sha512"
|
|
||||||
},
|
|
||||||
"NETStandard.Library/2.0.3": {
|
|
||||||
"type": "package",
|
|
||||||
"serviceable": true,
|
|
||||||
"sha512": "sha512-st47PosZSHrjECdjeIzZQbzivYBJFv6P2nv4cj2ypdI204DO+vZ7l5raGMiX4eXMJ53RfOIg+/s4DHVZ54Nu2A==",
|
|
||||||
"path": "netstandard.library/2.0.3",
|
|
||||||
"hashPath": "netstandard.library.2.0.3.nupkg.sha512"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"runtimeOptions": {
|
||||||
|
"additionalProbingPaths": [
|
||||||
|
"C:\\Users\\Simon\\.dotnet\\store\\|arch|\\|tfm|",
|
||||||
|
"C:\\Users\\Simon\\.nuget\\packages",
|
||||||
|
"C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"runtimeOptions": {
|
||||||
|
"tfm": "net7.0",
|
||||||
|
"rollForward": "LatestMinor",
|
||||||
|
"framework": {
|
||||||
|
"name": "Microsoft.NETCore.App",
|
||||||
|
"version": "7.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -453,7 +453,8 @@ namespace GlitchyEditor.EditWindows
|
|||||||
|
|
||||||
StringView search = StringView();
|
StringView search = StringView();
|
||||||
|
|
||||||
char8* scriptLabel = scriptComponent.Instance?.ScriptClass.FullName.ToScopeCStr!() ?? "Select Script...";
|
//char8* scriptLabel = scriptComponent.Instance?.ScriptClass.FullName.ToScopeCStr!() ?? "Select Script...";
|
||||||
|
char8* scriptLabel = scriptComponent.Instance?.ScriptClass.FullName.CStr() ?? "Select Script...";
|
||||||
|
|
||||||
if (ImGui.Button(scriptLabel))
|
if (ImGui.Button(scriptLabel))
|
||||||
ImGui.OpenPopup("SelectScript");
|
ImGui.OpenPopup("SelectScript");
|
||||||
@@ -478,13 +479,15 @@ namespace GlitchyEditor.EditWindows
|
|||||||
//ScriptEngine.InitializeInstance(entity, scriptComponent);
|
//ScriptEngine.InitializeInstance(entity, scriptComponent);
|
||||||
|
|
||||||
scriptComponent.ScriptClassName = scriptClass.FullName;
|
scriptComponent.ScriptClassName = scriptClass.FullName;
|
||||||
|
|
||||||
ScriptEngine.CreateScriptFieldMap(entity);
|
//ScriptEngine.CreateScriptFieldMap(entity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImGui.EndPopup();
|
ImGui.EndPopup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
ScriptClass scriptClass = ScriptEngine.GetScriptClass(scriptComponent.ScriptClassName);
|
ScriptClass scriptClass = ScriptEngine.GetScriptClass(scriptComponent.ScriptClassName);
|
||||||
|
|
||||||
/*T GetFieldValue<T>()
|
/*T GetFieldValue<T>()
|
||||||
@@ -707,6 +710,8 @@ namespace GlitchyEditor.EditWindows
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void LabelColumn(StringView label)
|
private static void LabelColumn(StringView label)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
FileVersion = 1
|
FileVersion = 1
|
||||||
Dependencies = {GlitchLog = "*", corlib = "*", DirectX = "*", FreeType = "*", cgltf-beef = "*", msdfgen-beef = "*", ImGui = "*", ImGuiImplDX11 = "*", ImGuiImplWin32 = "*", ImGuizmo = "*", Beefy2D = "*", LodePng = "*", GlitchyEngineHelper = "*", bon = "*", box2d-beef = "*", "Beef.Linq" = "*"}
|
Dependencies = {GlitchLog = "*", corlib = "*", DirectX = "*", FreeType = "*", cgltf-beef = "*", msdfgen-beef = "*", ImGui = "*", ImGuiImplDX11 = "*", ImGuiImplWin32 = "*", ImGuizmo = "*", Beefy2D = "*", LodePng = "*", GlitchyEngineHelper = "*", bon = "*", box2d-beef = "*", "Beef.Linq" = "*", NetHostBeef = "*"}
|
||||||
|
|
||||||
[Project]
|
[Project]
|
||||||
Name = "GlitchyEngine"
|
Name = "GlitchyEngine"
|
||||||
|
|||||||
@@ -70,5 +70,28 @@ namespace GlitchyEngine
|
|||||||
delete dictionary;
|
delete dictionary;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static mixin ClearDictionaryAndDeleteValues(var dictionary)
|
||||||
|
{
|
||||||
|
if (dictionary != null)
|
||||||
|
{
|
||||||
|
for (var value in dictionary)
|
||||||
|
delete value.value;
|
||||||
|
delete dictionary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static mixin ClearDictionaryAndDeleteKeysAndValues(var dictionary)
|
||||||
|
{
|
||||||
|
if (dictionary != null)
|
||||||
|
{
|
||||||
|
for (var value in dictionary)
|
||||||
|
{
|
||||||
|
delete value.key;
|
||||||
|
delete value.value;
|
||||||
|
}
|
||||||
|
delete dictionary;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,166 @@
|
|||||||
|
using NetHostBeef;
|
||||||
|
using System;
|
||||||
|
using System.Interop;
|
||||||
|
using GlitchyEngine.Core;
|
||||||
|
|
||||||
|
namespace GlitchyEngine.Scripting;
|
||||||
|
|
||||||
|
static class CoreClrHelper
|
||||||
|
{
|
||||||
|
static HostFxr.InitializeForDotnetCommandLineFn HostFxr_Init;
|
||||||
|
static HostFxr.GetRuntimeDelegateFn HostFxr_GetDelegate;
|
||||||
|
static HostFxr.CloseFn HostFxr_Close;
|
||||||
|
|
||||||
|
static CoreClr.LoadAssemblyAndGetFunctionPointerFn LoadAssemblyAndGetFunctionPointerFn;
|
||||||
|
static CoreClr.GetFunctionPointerFn GetFunctionPointerFn;
|
||||||
|
|
||||||
|
private function void LoadScriptAssemblyFunc(uint8* appData, int64 appLength, uint8* pdbData, int64 pdbLength);
|
||||||
|
|
||||||
|
//static function void(char8* path) LoadScriptAssembly;
|
||||||
|
static LoadScriptAssemblyFunc _loadScriptAssembly;
|
||||||
|
static function void() _unloadAssemblies;
|
||||||
|
|
||||||
|
// public static unsafe void GetScriptClasses(void** outBuffer, long* length)
|
||||||
|
private function void GetScriptClassesFunc(void** outBuffer, int64* length);
|
||||||
|
static GetScriptClassesFunc _getScriptClasses;
|
||||||
|
static function void() _freeScriptClassNames;
|
||||||
|
|
||||||
|
//public static unsafe ScriptFunctions CreateScriptInstance(UUID entityId, byte* scriptClassName)
|
||||||
|
private function ScriptFunctionPointers CreateScriptInstanceFunc(UUID entityId, char8* scriptClassName);
|
||||||
|
static CreateScriptInstanceFunc _createScriptInstance;
|
||||||
|
|
||||||
|
public static void Init(StringView coreAssemblyPath)
|
||||||
|
{
|
||||||
|
LoadHostFxr();
|
||||||
|
InitAndStartRuntime(coreAssemblyPath);
|
||||||
|
|
||||||
|
PrepareFunction();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void LoadHostFxr()
|
||||||
|
{
|
||||||
|
char_t[256] buffer = ?;
|
||||||
|
c_size bufferSize = buffer.Count;
|
||||||
|
int rc = NetHost.get_hostfxr_path(&buffer, &bufferSize, null);
|
||||||
|
|
||||||
|
Log.EngineLogger.AssertDebug(rc == 0, "Failed to get HostFxr path.");
|
||||||
|
|
||||||
|
// Load hostfxr and get desired exports
|
||||||
|
void* lib = NetHostHelper.LoadLibrary(&buffer);
|
||||||
|
HostFxr_Init = NetHostHelper.GetExport<HostFxr.InitializeForDotnetCommandLineFn>(lib, "hostfxr_initialize_for_dotnet_command_line");
|
||||||
|
HostFxr_GetDelegate = NetHostHelper.GetExport<HostFxr.GetRuntimeDelegateFn>(lib, "hostfxr_get_runtime_delegate");
|
||||||
|
HostFxr_Close = NetHostHelper.GetExport<HostFxr.CloseFn>(lib, "hostfxr_close");
|
||||||
|
|
||||||
|
Log.EngineLogger.AssertDebug(HostFxr_Init != null && HostFxr_GetDelegate != null && HostFxr_Close != null, "Retrieving at least one HostFxr function failed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void InitAndStartRuntime(StringView coreAssembly)
|
||||||
|
{
|
||||||
|
char_t* ptr = NetHostHelper.GetScopedRawPtr!(coreAssembly);
|
||||||
|
|
||||||
|
char_t*[2] args = char_t*[](
|
||||||
|
ptr,
|
||||||
|
null
|
||||||
|
);
|
||||||
|
|
||||||
|
HostFxr.Handle cxt = null;
|
||||||
|
int rc = HostFxr_Init(1, &args, null, &cxt);
|
||||||
|
|
||||||
|
if (rc != 0 || cxt == null)
|
||||||
|
{
|
||||||
|
Log.EngineLogger.Error($"Failed to initialize HostFxr: {rc}");
|
||||||
|
HostFxr_Close(cxt);
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.EngineLogger.Assert(rc == 0, "Failed to initialize HostFxr.");
|
||||||
|
|
||||||
|
rc = HostFxr_GetDelegate(cxt, .LoadAssemblyAndGetFunctionPointer, (void**)&LoadAssemblyAndGetFunctionPointerFn);
|
||||||
|
|
||||||
|
Log.EngineLogger.Assert(rc == 0, scope $"Get delegate failed: {rc}. (LoadAssemblyAndGetFunctionPointer)");
|
||||||
|
|
||||||
|
rc = HostFxr_GetDelegate(cxt, .GetFunctionPointer, (void**)&GetFunctionPointerFn);
|
||||||
|
|
||||||
|
Log.EngineLogger.Assert(rc == 0, scope $"Get delegate failed: {rc}. (GetFunctionPointer)");
|
||||||
|
|
||||||
|
HostFxr_Close(cxt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void PrepareFunction()
|
||||||
|
{
|
||||||
|
GetFunctionPointerUnmanagedCallersOnly("GlitchyEngine.ScriptGlue, ScriptCore", "LoadScriptAssembly", out _loadScriptAssembly);
|
||||||
|
|
||||||
|
GetFunctionPointerUnmanagedCallersOnly("GlitchyEngine.ScriptGlue, ScriptCore", "UnloadAssemblies", out _unloadAssemblies);
|
||||||
|
|
||||||
|
GetFunctionPointerUnmanagedCallersOnly("GlitchyEngine.ScriptGlue, ScriptCore", "GetScriptClasses", out _getScriptClasses);
|
||||||
|
|
||||||
|
GetFunctionPointerUnmanagedCallersOnly("GlitchyEngine.ScriptGlue, ScriptCore", "FreeScriptClassNames", out _freeScriptClassNames);
|
||||||
|
|
||||||
|
GetFunctionPointerUnmanagedCallersOnly("GlitchyEngine.ScriptGlue, ScriptCore", "CreateScriptInstance", out _createScriptInstance);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void LoadAppAssembly(Span<uint8> appAssemblyData, Span<uint8> pdbData)
|
||||||
|
{
|
||||||
|
_loadScriptAssembly(appAssemblyData.Ptr, appAssemblyData.Length, pdbData.Ptr, pdbData.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void UnloadAssemblies()
|
||||||
|
{
|
||||||
|
_unloadAssemblies();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gets an array of script class infos. Use FreeScriptClassNames to release the buffer.
|
||||||
|
public static void GetScriptClasses(out void* outBuffer, out int64 entryCount)
|
||||||
|
{
|
||||||
|
outBuffer = null;
|
||||||
|
entryCount = 0;
|
||||||
|
_getScriptClasses(&outBuffer, &entryCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Releases the buffer created by GetScriptClasses
|
||||||
|
public static void FreeScriptClassNames()
|
||||||
|
{
|
||||||
|
_freeScriptClassNames();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ScriptFunctionPointers CreateScriptInstance(UUID entityId, StringView scriptName)
|
||||||
|
{
|
||||||
|
return _createScriptInstance(entityId, scriptName.Ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int GetFunctionPointer<T>(StringView typeName, StringView methodName, StringView delegateName, out T outDelegate) where T: operator explicit void*
|
||||||
|
{
|
||||||
|
void* funPtr = null;
|
||||||
|
|
||||||
|
int rc = GetFunctionPointerFn(NetHostHelper.GetScopedRawPtr!(typeName),
|
||||||
|
NetHostHelper.GetScopedRawPtr!(methodName), NetHostHelper.GetScopedRawPtr!(delegateName),
|
||||||
|
null, null, out funPtr);
|
||||||
|
|
||||||
|
outDelegate = (T)funPtr;
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int GetFunctionPointerDefaultDelegate(StringView typeName, StringView methodName, out CoreClr.DefaultEntryPoint outDelegate)
|
||||||
|
{
|
||||||
|
void* funPtr = null;
|
||||||
|
|
||||||
|
int rc = GetFunctionPointerFn(NetHostHelper.GetScopedRawPtr!(typeName),
|
||||||
|
NetHostHelper.GetScopedRawPtr!(methodName), null, null, null, out funPtr);
|
||||||
|
|
||||||
|
outDelegate = (CoreClr.DefaultEntryPoint)funPtr;
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int GetFunctionPointerUnmanagedCallersOnly<T>(StringView typeName, StringView methodName, out T outDelegate) where T: operator explicit void*
|
||||||
|
{
|
||||||
|
void* funPtr = null;
|
||||||
|
|
||||||
|
int rc = GetFunctionPointerFn(NetHostHelper.GetScopedRawPtr!(typeName),
|
||||||
|
NetHostHelper.GetScopedRawPtr!(methodName), CoreClr.UNMANAGEDCALLERSONLY_METHOD, null, null, out funPtr);
|
||||||
|
|
||||||
|
outDelegate = (T)funPtr;
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,6 +5,8 @@ using System.Collections;
|
|||||||
using GlitchyEngine.Core;
|
using GlitchyEngine.Core;
|
||||||
using GlitchyEngine.Math;
|
using GlitchyEngine.Math;
|
||||||
using GlitchyEngine.World;
|
using GlitchyEngine.World;
|
||||||
|
using NetHostBeef;
|
||||||
|
using System.Interop;
|
||||||
|
|
||||||
namespace GlitchyEngine.Scripting;
|
namespace GlitchyEngine.Scripting;
|
||||||
|
|
||||||
@@ -45,6 +47,73 @@ static sealed class ScriptEngineHelper
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum ScriptMethods : uint32
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
OnCreate = 0x1,
|
||||||
|
OnUpdate = 0x2,
|
||||||
|
OnDestroy = 0x4,
|
||||||
|
}
|
||||||
|
|
||||||
|
class SexyScriptClass
|
||||||
|
{
|
||||||
|
public String FullName ~ delete _;
|
||||||
|
public StringView Name;
|
||||||
|
public Guid Guid;
|
||||||
|
public ScriptMethods Methods;
|
||||||
|
|
||||||
|
public this(StringView fullName, Guid guid, ScriptMethods methods)
|
||||||
|
{
|
||||||
|
FullName = new String(fullName);
|
||||||
|
Guid = guid;
|
||||||
|
|
||||||
|
int lastDotIndex = FullName.LastIndexOf('.');
|
||||||
|
|
||||||
|
if (lastDotIndex == -1)
|
||||||
|
Name = FullName;
|
||||||
|
else
|
||||||
|
Name = FullName.Substring(lastDotIndex + 1);
|
||||||
|
|
||||||
|
Methods = methods;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SexyScriptInstance
|
||||||
|
{
|
||||||
|
public SexyScriptClass ScriptClass;
|
||||||
|
|
||||||
|
public ScriptFunctionPointers Functions;
|
||||||
|
|
||||||
|
public this(SexyScriptClass scriptClass, ScriptFunctionPointers functions)
|
||||||
|
{
|
||||||
|
ScriptClass = scriptClass;
|
||||||
|
Functions = functions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void InvokeOnCreate()
|
||||||
|
{
|
||||||
|
Functions.OnCreateMethod();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*public void InvokeOnUpdate(float deltaTime)
|
||||||
|
{
|
||||||
|
CoreClrHelper.InvokeOnUpdate(float deltaTime);
|
||||||
|
//Functions.OnUpdateMethod(deltaTime);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
public void InvokeOnDestroy()
|
||||||
|
{
|
||||||
|
Functions.OnDestroyMethod();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct ScriptFunctionPointers
|
||||||
|
{
|
||||||
|
public function void() OnCreateMethod;
|
||||||
|
public function void(float) OnUpdateMethod;
|
||||||
|
public function void() OnDestroyMethod;
|
||||||
|
}
|
||||||
|
|
||||||
static class ScriptEngine
|
static class ScriptEngine
|
||||||
{
|
{
|
||||||
private static MonoDomain* s_RootDomain;
|
private static MonoDomain* s_RootDomain;
|
||||||
@@ -63,17 +132,11 @@ static class ScriptEngine
|
|||||||
|
|
||||||
private static Dictionary<StringView, SharpType> _sharpClasses = new .() ~ DeleteDictionaryAndReleaseValues!(_);
|
private static Dictionary<StringView, SharpType> _sharpClasses = new .() ~ DeleteDictionaryAndReleaseValues!(_);
|
||||||
|
|
||||||
private static Dictionary<StringView, ScriptClass> _entityScripts = new .() ~ DeleteDictionaryAndReleaseValues!(_);
|
private static Dictionary<StringView, SexyScriptClass> _entityScripts = new .() ~ DeleteDictionaryAndValues!(_);
|
||||||
|
|
||||||
private static Dictionary<UUID, ScriptInstance> _entityScriptInstances = new .() ~ {
|
private static Dictionary<UUID, SexyScriptInstance> _entityScriptInstances = new .() ~ DeleteDictionaryAndValues!(_);
|
||||||
for (var entry in _)
|
|
||||||
{
|
|
||||||
entry.value?.ReleaseRef();
|
|
||||||
}
|
|
||||||
delete _;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Dictionary<StringView, ScriptClass> EntityClasses => _entityScripts;
|
public static Dictionary<StringView, SexyScriptClass> EntityClasses => _entityScripts;
|
||||||
|
|
||||||
public static Scene Context => s_Context;
|
public static Scene Context => s_Context;
|
||||||
|
|
||||||
@@ -96,49 +159,35 @@ static class ScriptEngine
|
|||||||
{
|
{
|
||||||
internal static MonoClass* s_ShowInEditorAttribute;
|
internal static MonoClass* s_ShowInEditorAttribute;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static String _coreAssemblyPath = "resources/scripts/ScriptCore.dll";
|
||||||
|
private static String _appAssemblyPath = "SandboxProject/Assets/Scripts/bin/Sandbox.dll";
|
||||||
|
|
||||||
|
|
||||||
public static void Init()
|
public static void Init()
|
||||||
{
|
{
|
||||||
InitMono();
|
CoreClrHelper.Init(_coreAssemblyPath);
|
||||||
ScriptGlue.Init();
|
|
||||||
|
|
||||||
LoadScriptAssemblies();
|
GetFunctions();
|
||||||
|
|
||||||
|
//ScriptGlue.Init();
|
||||||
|
|
||||||
|
LoadScriptAssembly();
|
||||||
|
|
||||||
InitAssemblyWatcher();
|
InitAssemblyWatcher();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void InitMono()
|
|
||||||
{
|
|
||||||
Mono.mono_set_assemblies_path("mono/lib");
|
|
||||||
|
|
||||||
if (_debuggingEnabled)
|
|
||||||
{
|
|
||||||
char8*[2] options = .(
|
|
||||||
"--debugger-agent=transport=dt_socket,address=127.0.0.1:2550,server=y,suspend=n,loglevel=3,logfile=MonoDebugger.log",
|
|
||||||
"--soft-breakpoints"
|
|
||||||
);
|
|
||||||
|
|
||||||
Mono.mono_jit_parse_options(options.Count, &options);
|
|
||||||
Mono.mono_debug_init(.Mono);
|
|
||||||
}
|
|
||||||
|
|
||||||
s_RootDomain = Mono.mono_jit_init("GlitchyEngineJITRuntime");
|
|
||||||
Log.EngineLogger.Assert(s_RootDomain != null, "Failed to initialize mono root domain");
|
|
||||||
|
|
||||||
if (_debuggingEnabled)
|
|
||||||
{
|
|
||||||
Mono.mono_debug_domain_create(s_RootDomain);
|
|
||||||
}
|
|
||||||
|
|
||||||
Mono.mono_thread_set_main(Mono.mono_thread_current());
|
|
||||||
}
|
|
||||||
|
|
||||||
static void InitAssemblyWatcher()
|
static void InitAssemblyWatcher()
|
||||||
{
|
{
|
||||||
if (_userAssemblyWatcher == null)
|
if (_userAssemblyWatcher == null)
|
||||||
{
|
{
|
||||||
|
String directoryPath = scope String();
|
||||||
|
Path.GetDirectoryPath(_appAssemblyPath, directoryPath);
|
||||||
|
String fileName = scope String();
|
||||||
|
Path.GetFileName(_appAssemblyPath, fileName);
|
||||||
|
|
||||||
// TODO: Obviously don't hardcode path
|
// TODO: Obviously don't hardcode path
|
||||||
_userAssemblyWatcher = new FileSystemWatcher("SandboxProject/Assets/Scripts/bin/", "*/Sandbox.dll");
|
_userAssemblyWatcher = new FileSystemWatcher(directoryPath, fileName);
|
||||||
_userAssemblyWatcher.OnChanged.Add(new (fileName) =>
|
_userAssemblyWatcher.OnChanged.Add(new (fileName) =>
|
||||||
{
|
{
|
||||||
// TODO: Temporary, we want to be able to reload while in play-mode. (+ Editor Scripts will be a thing some day)
|
// TODO: Temporary, we want to be able to reload while in play-mode. (+ Editor Scripts will be a thing some day)
|
||||||
@@ -165,17 +214,44 @@ static class ScriptEngine
|
|||||||
_userAssemblyWatcher.StartRaisingEvents();
|
_userAssemblyWatcher.StartRaisingEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void LoadScriptAssemblies()
|
static void LoadScriptAssembly()
|
||||||
{
|
{
|
||||||
CreateAppDomain("GlitchyEngineScriptRuntime");
|
List<uint8> data = new List<uint8>(1024);
|
||||||
(s_CoreAssembly, s_CoreAssemblyImage) = LoadAssembly("resources/scripts/ScriptCore.dll", _debuggingEnabled);
|
File.ReadAll(_appAssemblyPath, data);
|
||||||
(s_AppAssembly, s_AppAssemblyImage) = LoadAssembly("SandboxProject/Assets/Scripts/bin/Sandbox.dll", _debuggingEnabled);
|
|
||||||
|
List<uint8> pdbData = new List<uint8>(1024);
|
||||||
|
|
||||||
|
String pdbPath = scope .();
|
||||||
|
Path.ChangeExtension(_appAssemblyPath, ".pdb", pdbPath);
|
||||||
|
|
||||||
|
File.ReadAll(pdbPath, pdbData);
|
||||||
|
|
||||||
|
CoreClrHelper.LoadAppAssembly(data, pdbData);
|
||||||
|
|
||||||
|
delete data;
|
||||||
|
delete pdbData;
|
||||||
|
|
||||||
GetEntitiesFromAssemblies();
|
GetEntitiesFromAssemblies();
|
||||||
|
|
||||||
ScriptGlue.RegisterManagedComponents();
|
//ScriptGlue.RegisterManagedComponents();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void ReloadAssemblies()
|
||||||
|
{
|
||||||
|
Debug.Profiler.ProfileFunction!();
|
||||||
|
|
||||||
|
CoreClrHelper.UnloadAssemblies();
|
||||||
|
LoadScriptAssembly();
|
||||||
|
|
||||||
|
// TODO: ScriptFields might get added
|
||||||
|
// TODO: ScriptField Types may change after reload!
|
||||||
|
// TODO: Scripts may be renamed (probably not detectable (trivially))
|
||||||
|
|
||||||
|
// TODO: Reload in play mode
|
||||||
|
// Only scripts that were changed should actually be reinstatiated
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static void SetContext(Scene scene)
|
public static void SetContext(Scene scene)
|
||||||
{
|
{
|
||||||
SetReference!(s_Context, scene);
|
SetReference!(s_Context, scene);
|
||||||
@@ -183,37 +259,54 @@ static class ScriptEngine
|
|||||||
|
|
||||||
public static void OnRuntimeStop()
|
public static void OnRuntimeStop()
|
||||||
{
|
{
|
||||||
for (var entry in _entityScriptInstances)
|
ThrowUnimplemented();
|
||||||
|
|
||||||
|
// TODO: Also check, if something has to happen on the C# side!
|
||||||
|
|
||||||
|
ClearDictionaryAndDeleteValues!(_entityScriptInstances);
|
||||||
|
|
||||||
|
/*for (var entry in _entityScriptInstances)
|
||||||
{
|
{
|
||||||
entry.value.ReleaseRef();
|
entry.value.ReleaseRef();
|
||||||
}
|
}
|
||||||
_entityScriptInstances.Clear();
|
_entityScriptInstances.Clear();
|
||||||
|
*/
|
||||||
SetContext(null);
|
SetContext(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function void InvokeOnUpdateFunc(UUID entityId, float deltaTime);
|
||||||
|
|
||||||
|
private static InvokeOnUpdateFunc _InvokeOnUpdate;
|
||||||
|
|
||||||
|
private static void GetFunctions()
|
||||||
|
{
|
||||||
|
CoreClrHelper.GetFunctionPointerUnmanagedCallersOnly("GlitchyEngine.ScriptGlue, ScriptCore", "InvokeOnUpdate", out _InvokeOnUpdate);
|
||||||
|
}
|
||||||
|
|
||||||
public static bool InitializeInstance(Entity entity, ScriptComponent* script)
|
public static bool InitializeInstance(Entity entity, ScriptComponent* script)
|
||||||
{
|
{
|
||||||
ScriptClass scriptClass = GetScriptClass(script.ScriptClassName);
|
SexyScriptClass scriptClass = GetScriptClass(script.ScriptClassName);
|
||||||
|
|
||||||
if (scriptClass == null)
|
if (scriptClass == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
ScriptFunctionPointers functions = CoreClrHelper.CreateScriptInstance(entity.UUID, scriptClass.FullName);
|
||||||
|
|
||||||
script.Instance = new ScriptInstance(scriptClass);
|
script.Instance = new SexyScriptInstance(scriptClass, functions);//new ScriptInstance(scriptClass);
|
||||||
script.Instance..ReleaseRef();
|
// script.Instance..ReleaseRef();
|
||||||
|
|
||||||
|
_entityScriptInstances[entity.UUID] = script.Instance;
|
||||||
|
|
||||||
_entityScriptInstances[entity.UUID] = script.Instance..AddRef();
|
// CopyEditorFieldsToInstance(entity, script);
|
||||||
|
|
||||||
script.Instance.Instantiate(entity.UUID);
|
|
||||||
|
|
||||||
CopyEditorFieldsToInstance(entity, script);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void CopyEditorFieldsToInstance(Entity entity, ScriptComponent* script)
|
private static void CopyEditorFieldsToInstance(Entity entity, ScriptComponent* script)
|
||||||
{
|
{
|
||||||
// Technically the map is for a different entity (namely the editor-entity),
|
ThrowUnimplemented();
|
||||||
|
|
||||||
|
/*// 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);
|
||||||
|
|
||||||
@@ -224,82 +317,71 @@ static class ScriptEngine
|
|||||||
ScriptField scriptField = script.Instance.ScriptClass.Fields[fieldName];
|
ScriptField scriptField = script.Instance.ScriptClass.Fields[fieldName];
|
||||||
|
|
||||||
script.Instance.SetFieldValue(scriptField, field._data);
|
script.Instance.SetFieldValue(scriptField, field._data);
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
private static MonoAssembly* LoadCSharpAssembly(StringView assemblyPath, bool loadPDB = false)
|
struct ScriptClassInfo
|
||||||
{
|
{
|
||||||
List<uint8> data = new List<uint8>(1024);
|
public char8* Name;
|
||||||
|
public Guid Guid;
|
||||||
File.ReadAll(assemblyPath, data);
|
public ScriptMethods Methods;
|
||||||
|
|
||||||
// NOTE: We can't use this image for anything other than loading the assembly because this image doesn't have a reference to the assembly
|
|
||||||
MonoImageOpenStatus status = .ImageInvalid;
|
|
||||||
MonoImage* image = Mono.mono_image_open_from_data_full(data.Ptr, (.)data.Count, true, &status, false);
|
|
||||||
|
|
||||||
delete data;
|
|
||||||
|
|
||||||
if (status != .Ok)
|
|
||||||
{
|
|
||||||
char8* errorMessage = Mono.mono_image_strerror(status);
|
|
||||||
|
|
||||||
Log.EngineLogger.Error($"Failed to load C# Assembly: \"{StringView(errorMessage)}\"");
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (loadPDB)
|
|
||||||
{
|
|
||||||
String pdbPath = scope .();
|
|
||||||
Path.ChangeExtension(assemblyPath, ".pdb", pdbPath);
|
|
||||||
|
|
||||||
if (File.Exists(pdbPath))
|
|
||||||
{
|
|
||||||
Log.EngineLogger.Trace($"Loading PDB \"{pdbPath}\"...");
|
|
||||||
|
|
||||||
List<uint8> pdbData = new List<uint8>(1024);
|
|
||||||
|
|
||||||
let result = File.ReadAll(pdbPath, pdbData);
|
|
||||||
|
|
||||||
if (result case .Err(let error))
|
|
||||||
{
|
|
||||||
Log.EngineLogger.Error("Failed to load PDB file ({error}).");
|
|
||||||
}
|
|
||||||
|
|
||||||
Mono.mono_debug_open_image_from_memory(image, pdbData.Ptr, (int32)pdbData.Count);
|
|
||||||
|
|
||||||
delete pdbData;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Log.EngineLogger.Warning($"Debugging enabled but no PDB-File found \"{assemblyPath}\".");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MonoAssembly* assembly = Mono.mono_assembly_load_from_full(image, assemblyPath.ToScopeCStr!(), &status, 0);
|
|
||||||
|
|
||||||
Mono.mono_image_close(image);
|
|
||||||
|
|
||||||
return assembly;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void CreateAppDomain(StringView name)
|
|
||||||
{
|
|
||||||
s_AppDomain = Mono.mono_domain_create_appdomain(name.ToScopeCStr!(), null);
|
|
||||||
Mono.mono_domain_set(s_AppDomain, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
static (MonoAssembly* assembly, MonoImage* image) LoadAssembly(StringView filepath, bool loadPDB = false)
|
|
||||||
{
|
|
||||||
MonoAssembly* assembly = LoadCSharpAssembly(filepath, loadPDB);
|
|
||||||
MonoImage* image = Mono.mono_assembly_get_image(assembly);
|
|
||||||
|
|
||||||
return (assembly, image);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void GetEntitiesFromAssemblies()
|
private static void GetEntitiesFromAssemblies()
|
||||||
{
|
{
|
||||||
|
CoreClrHelper.GetScriptClasses(let data, let entryCount);
|
||||||
|
|
||||||
|
Span<ScriptClassInfo> scriptClasses = .((.)data, entryCount);
|
||||||
|
|
||||||
|
List<SexyScriptClass> newClasses = scope .();
|
||||||
|
|
||||||
for (var entry in _entityScripts)
|
for (var entry in _entityScripts)
|
||||||
|
{
|
||||||
|
bool remove = true;
|
||||||
|
|
||||||
|
// We can only rely on guids.
|
||||||
|
for (var newEntry in scriptClasses)
|
||||||
|
{
|
||||||
|
if (entry.value.Guid == newEntry.Guid)
|
||||||
|
{
|
||||||
|
remove = false;
|
||||||
|
|
||||||
|
if (!String.Equals(entry.value.FullName.CStr(), newEntry.Name))
|
||||||
|
{
|
||||||
|
@entry.Remove();
|
||||||
|
|
||||||
|
entry.value.FullName.Set(StringView(newEntry.Name));
|
||||||
|
}
|
||||||
|
|
||||||
|
newClasses.Add(entry.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (remove)
|
||||||
|
{
|
||||||
|
@entry.Remove();
|
||||||
|
|
||||||
|
delete entry.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var entry in scriptClasses)
|
||||||
|
{
|
||||||
|
SexyScriptClass scriptClass = new .(StringView(entry.Name), entry.Guid, entry.Methods);
|
||||||
|
|
||||||
|
newClasses.Add(scriptClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var scriptClass in newClasses)
|
||||||
|
{
|
||||||
|
_entityScripts.Add(scriptClass.FullName, scriptClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
CoreClrHelper.FreeScriptClassNames();
|
||||||
|
|
||||||
|
// TODO: Cleanup
|
||||||
|
|
||||||
|
/*for (var entry in _entityScripts)
|
||||||
{
|
{
|
||||||
entry.value.ReleaseRef();
|
entry.value.ReleaseRef();
|
||||||
}
|
}
|
||||||
@@ -344,36 +426,18 @@ static class ScriptEngine
|
|||||||
|
|
||||||
Log.EngineLogger.Info($"Added entity \"{entityScript.FullName}\"");
|
Log.EngineLogger.Info($"Added entity \"{entityScript.FullName}\"");
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
}
|
|
||||||
|
|
||||||
public static void ReloadAssemblies()
|
|
||||||
{
|
|
||||||
Debug.Profiler.ProfileFunction!();
|
|
||||||
|
|
||||||
Mono.mono_domain_set(s_RootDomain, false);
|
|
||||||
|
|
||||||
Mono.mono_domain_unload(s_AppDomain);
|
|
||||||
|
|
||||||
LoadScriptAssemblies();
|
|
||||||
|
|
||||||
// TODO: ScriptFields might get added
|
|
||||||
// TODO: ScriptField Types may change after reload!
|
|
||||||
// TODO: Scripts may be renamed (probably not detectable (trivially))
|
|
||||||
|
|
||||||
// TODO: Reload in play mode
|
|
||||||
// Only scripts that were changed should actually be reinstatiated
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Shutdown()
|
public static void Shutdown()
|
||||||
{
|
{
|
||||||
Mono.mono_domain_set(s_RootDomain, false);
|
/*Mono.mono_domain_set(s_RootDomain, false);
|
||||||
|
|
||||||
Mono.mono_domain_unload(s_AppDomain);
|
Mono.mono_domain_unload(s_AppDomain);
|
||||||
s_AppDomain = null;
|
s_AppDomain = null;
|
||||||
|
|
||||||
Mono.mono_jit_cleanup(s_RootDomain);
|
Mono.mono_jit_cleanup(s_RootDomain);
|
||||||
s_RootDomain = null;
|
s_RootDomain = null;*/
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void RegisterSharpType(SharpType sharpType)
|
internal static void RegisterSharpType(SharpType sharpType)
|
||||||
@@ -424,6 +488,9 @@ static class ScriptEngine
|
|||||||
|
|
||||||
public static void CreateScriptFieldMap(Entity entity)
|
public static void CreateScriptFieldMap(Entity entity)
|
||||||
{
|
{
|
||||||
|
Log.EngineLogger.Error("Not implemented");
|
||||||
|
|
||||||
|
/*
|
||||||
Log.EngineLogger.AssertDebug(entity.IsValid);
|
Log.EngineLogger.AssertDebug(entity.IsValid);
|
||||||
|
|
||||||
if (_entityFields.TryGetValue(entity.UUID, var entityFields))
|
if (_entityFields.TryGetValue(entity.UUID, var entityFields))
|
||||||
@@ -445,11 +512,13 @@ static class ScriptEngine
|
|||||||
for (let (fieldName, field) in scriptClass.Fields)
|
for (let (fieldName, field) in scriptClass.Fields)
|
||||||
{
|
{
|
||||||
entityFields.Add(new String(fieldName), ScriptFieldInstance(field.FieldType));
|
entityFields.Add(new String(fieldName), ScriptFieldInstance(field.FieldType));
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ScriptFieldMap GetScriptFieldMap(Entity entity)
|
public static ScriptFieldMap GetScriptFieldMap(Entity entity)
|
||||||
{
|
{
|
||||||
|
ThrowUnimplemented();
|
||||||
|
|
||||||
Log.EngineLogger.AssertDebug(entity.IsValid);
|
Log.EngineLogger.AssertDebug(entity.IsValid);
|
||||||
|
|
||||||
let uuid = entity.UUID;
|
let uuid = entity.UUID;
|
||||||
@@ -462,16 +531,23 @@ static class ScriptEngine
|
|||||||
|
|
||||||
public static MonoObject* GetManagedInstance(UUID entityId)
|
public static MonoObject* GetManagedInstance(UUID entityId)
|
||||||
{
|
{
|
||||||
if (_entityScriptInstances.TryGetValue(entityId, let scriptInstance))
|
ThrowUnimplemented();
|
||||||
return scriptInstance.MonoInstance;
|
|
||||||
|
/*if (_entityScriptInstances.TryGetValue(entityId, let scriptInstance))
|
||||||
|
return scriptInstance.MonoInstance;*/
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ScriptClass GetScriptClass(StringView name)
|
public static SexyScriptClass GetScriptClass(StringView name)
|
||||||
{
|
{
|
||||||
EntityClasses.TryGetValue(name, let scriptClass);
|
EntityClasses.TryGetValue(name, let scriptClass);
|
||||||
|
|
||||||
return scriptClass;
|
return scriptClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void InvokeOnUpdate(UUID entityId, float deltaTime)
|
||||||
|
{
|
||||||
|
_InvokeOnUpdate(entityId, deltaTime);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -29,7 +29,7 @@ static class ScriptGlue
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Adding this attribute to a method will log method entry and returned Result<T> errors */
|
/*/* Adding this attribute to a method will log method entry and returned Result<T> errors */
|
||||||
[AttributeUsage(.Method)]
|
[AttributeUsage(.Method)]
|
||||||
struct RegisterMethodAttribute : Attribute, IOnMethodInit
|
struct RegisterMethodAttribute : Attribute, IOnMethodInit
|
||||||
{
|
{
|
||||||
@@ -48,13 +48,13 @@ static class ScriptGlue
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
public static void Init()
|
public static void Init()
|
||||||
{
|
{
|
||||||
RegisterCalls();
|
//RegisterCalls();
|
||||||
|
|
||||||
RegisterMathFunctions();
|
//RegisterMathFunctions();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void RegisterManagedComponents()
|
public static void RegisterManagedComponents()
|
||||||
@@ -67,11 +67,11 @@ static class ScriptGlue
|
|||||||
RegisterComponent<Rigidbody2DComponent>("GlitchyEngine.RigidBody2D");
|
RegisterComponent<Rigidbody2DComponent>("GlitchyEngine.RigidBody2D");
|
||||||
}
|
}
|
||||||
|
|
||||||
[RegisterMethod]
|
/*[RegisterMethod]
|
||||||
private static void RegisterCalls()
|
private static void RegisterCalls()
|
||||||
{
|
{
|
||||||
// Generated at CompTime
|
// Generated at CompTime
|
||||||
}
|
}*/
|
||||||
|
|
||||||
private static void RegisterComponent<T>(StringView cSharpClassName = "") where T : struct, new
|
private static void RegisterComponent<T>(StringView cSharpClassName = "") where T : struct, new
|
||||||
{
|
{
|
||||||
@@ -104,13 +104,10 @@ static class ScriptGlue
|
|||||||
}
|
}
|
||||||
|
|
||||||
[RegisterCall("Log::LogMessage_Impl")]
|
[RegisterCall("Log::LogMessage_Impl")]
|
||||||
static void Log(int32 logLevel, MonoString* message)
|
[Export, LinkName("Log::LogMessage_Impl"), CallingConvention(.Cdecl)]
|
||||||
|
static void Log(int32 logLevel, char8* message)
|
||||||
{
|
{
|
||||||
char8* utfMessage = Mono.mono_string_to_utf8(message);
|
Log.ClientLogger.Log((LogLevel)logLevel, StringView(message));
|
||||||
|
|
||||||
Log.ClientLogger.Log((LogLevel)logLevel, StringView(utfMessage));
|
|
||||||
|
|
||||||
Mono.mono_free(utfMessage);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Input
|
#region Input
|
||||||
|
|||||||
@@ -509,7 +509,7 @@ namespace GlitchyEngine.World
|
|||||||
{
|
{
|
||||||
private String _scriptClassName = null;
|
private String _scriptClassName = null;
|
||||||
|
|
||||||
private ScriptInstance _instance = null;
|
private SexyScriptInstance _instance = null;
|
||||||
|
|
||||||
public StringView ScriptClassName
|
public StringView ScriptClassName
|
||||||
{
|
{
|
||||||
@@ -523,22 +523,24 @@ namespace GlitchyEngine.World
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ScriptInstance Instance
|
public SexyScriptInstance Instance
|
||||||
{
|
{
|
||||||
[Inline]
|
[Inline]
|
||||||
get => _instance;
|
get => _instance;
|
||||||
[Inline]
|
[Inline]
|
||||||
set mut => SetReference!(_instance, value);
|
set mut => _instance = value;//SetReference!(_instance, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsInitialized => _instance?.IsInitialized ?? false;
|
// public bool IsInitialized => _instance?.IsInitialized ?? false;
|
||||||
|
|
||||||
public bool IsCreated => _instance?.IsCreated ?? false;
|
// public bool IsCreated => _instance?.IsCreated ?? false;
|
||||||
|
|
||||||
|
public bool IsCreated => _instance != null;
|
||||||
|
|
||||||
public void Dispose() mut
|
public void Dispose() mut
|
||||||
{
|
{
|
||||||
delete _scriptClassName;
|
delete _scriptClassName;
|
||||||
ReleaseRefAndNullify!(_instance);
|
//ReleaseRefAndNullify!(_instance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -260,7 +260,7 @@ namespace GlitchyEngine.World
|
|||||||
script.Instance._entity = Entity(entity, this);
|
script.Instance._entity = Entity(entity, this);
|
||||||
script.Instance.[Friend]OnCreate();
|
script.Instance.[Friend]OnCreate();
|
||||||
}
|
}
|
||||||
|
|
||||||
script.Instance.[Friend]OnUpdate(gameTime);
|
script.Instance.[Friend]OnUpdate(gameTime);
|
||||||
}
|
}
|
||||||
/*}
|
/*}
|
||||||
@@ -272,15 +272,15 @@ namespace GlitchyEngine.World
|
|||||||
{
|
{
|
||||||
if (!script.IsCreated)
|
if (!script.IsCreated)
|
||||||
{
|
{
|
||||||
if (!script.IsInitialized)
|
ScriptEngine.InitializeInstance(Entity(entity, this), script);
|
||||||
ScriptEngine.InitializeInstance(Entity(entity, this), script);
|
|
||||||
|
|
||||||
if (mode.HasFlag(.Runtime))
|
//if (mode.HasFlag(.Runtime))
|
||||||
script.Instance.InvokeOnCreate();
|
//script.Instance.InvokeOnCreate();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mode.HasFlag(.Runtime))
|
if (mode.HasFlag(.Runtime) && script.Instance.ScriptClass.Methods.HasFlag(.OnUpdate))
|
||||||
script.Instance.InvokeOnUpdate(gameTime.DeltaTime);
|
ScriptEngine.InvokeOnUpdate(Entity(entity, this).UUID, gameTime.DeltaTime);
|
||||||
|
//script.Instance.InvokeOnUpdate(gameTime.DeltaTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -191,7 +191,9 @@ class SceneSerializer
|
|||||||
{
|
{
|
||||||
Serialize.Value(writer, "ScriptClass", component.ScriptClassName);
|
Serialize.Value(writer, "ScriptClass", component.ScriptClassName);
|
||||||
|
|
||||||
//if (component.HasScript)
|
ThrowUnimplemented();
|
||||||
|
|
||||||
|
/*//if (component.HasScript)
|
||||||
// TODO: Thats not a good check, I think. At least we know the script class is valid
|
// TODO: Thats not a good check, I think. At least we know the script class is valid
|
||||||
if (ScriptEngine.GetScriptClass(component.ScriptClassName) != null)
|
if (ScriptEngine.GetScriptClass(component.ScriptClassName) != null)
|
||||||
{
|
{
|
||||||
@@ -221,7 +223,7 @@ class SceneSerializer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -579,9 +581,9 @@ class SceneSerializer
|
|||||||
// But that is a bug for me to rediscover in the distant future, so in case this bug occurred and it took ages for you to
|
// But that is a bug for me to rediscover in the distant future, so in case this bug occurred and it took ages for you to
|
||||||
// figure out what happened: You are welcome :)
|
// figure out what happened: You are welcome :)
|
||||||
|
|
||||||
ScriptEngine.CreateScriptFieldMap(entity);
|
//ScriptEngine.CreateScriptFieldMap(entity);
|
||||||
|
|
||||||
var fields = ScriptEngine.GetScriptFieldMap(entity);
|
//var fields = ScriptEngine.GetScriptFieldMap(entity);
|
||||||
|
|
||||||
Try!(reader.EntryEnd());
|
Try!(reader.EntryEnd());
|
||||||
|
|
||||||
@@ -613,44 +615,47 @@ class SceneSerializer
|
|||||||
// Allocate a string on the stack, because the dictionary uses a string as key
|
// Allocate a string on the stack, because the dictionary uses a string as key
|
||||||
String fieldNameString = scope .(fieldName);
|
String fieldNameString = scope .(fieldName);
|
||||||
|
|
||||||
if (fields.ContainsKey(fieldNameString))
|
//if (fields.ContainsKey(fieldNameString))
|
||||||
{
|
//{
|
||||||
var field = ref fields[fieldNameString];
|
//var field = ref fields[fieldNameString];
|
||||||
|
|
||||||
Result<StringView> fieldTypeName = reader.Type();
|
Result<StringView> fieldTypeName = reader.Type();
|
||||||
|
|
||||||
if (fieldTypeName case .Err)
|
/*if (fieldTypeName case .Err)
|
||||||
{
|
{
|
||||||
Log.EngineLogger.Error($"Failed to read field type for field \"{fieldName}\" in script \"{component.ScriptClassName}\" of entity {entity.UUID} (\"{entity.Name}\")");
|
Log.EngineLogger.Error($"Failed to read field type for field \"{fieldName}\" in script \"{component.ScriptClassName}\" of entity {entity.UUID} (\"{entity.Name}\")");
|
||||||
reader.FileEntrySkip(1);
|
reader.FileEntrySkip(1);
|
||||||
dontRemoveComma = true;
|
dontRemoveComma = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
Result<ScriptFieldType> fieldType = Enum.Parse<ScriptFieldType>(fieldTypeName, true);
|
Result<ScriptFieldType> fieldType = Enum.Parse<ScriptFieldType>(fieldTypeName, true);
|
||||||
|
|
||||||
if ((fieldType case .Err) || (fieldType != field.Type))
|
/*if ((fieldType case .Err) || (fieldType != field.Type))
|
||||||
{
|
{
|
||||||
Log.EngineLogger.Error($"Unexpected field type (\"{fieldTypeName}\" instead of \"{field.Type}\" for field: \"{fieldName}\" in script \"{component.ScriptClassName}\" of entity {entity.UUID} (\"{entity.Name}\")");
|
Log.EngineLogger.Error($"Unexpected field type (\"{fieldTypeName}\" instead of \"{field.Type}\" for field: \"{fieldName}\" in script \"{component.ScriptClassName}\" of entity {entity.UUID} (\"{entity.Name}\")");
|
||||||
reader.FileEntrySkip(1);
|
reader.FileEntrySkip(1);
|
||||||
dontRemoveComma = true;
|
dontRemoveComma = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
void* data = &field.[Friend]_data;
|
//void* data = &field.[Friend]_data;
|
||||||
|
|
||||||
|
uint8[128] data;
|
||||||
|
|
||||||
if (Deserialize.Value(reader, ValueView(field.Type.GetBeefType(), data), gBonEnv) case .Err)
|
//if (Deserialize.Value(reader, ValueView(field.Type.GetBeefType(), data), gBonEnv) case .Err)
|
||||||
|
if (Deserialize.Value(reader, ValueView(fieldType.Value.GetBeefType(), &data), gBonEnv) case .Err)
|
||||||
{
|
{
|
||||||
Log.EngineLogger.Error($"Failed to deserialize data for field: \"{fieldName}\" in script \"{component.ScriptClassName}\" of entity {entity.UUID} (\"{entity.Name}\")");
|
Log.EngineLogger.Error($"Failed to deserialize data for field: \"{fieldName}\" in script \"{component.ScriptClassName}\" of entity {entity.UUID} (\"{entity.Name}\")");
|
||||||
reader.FileEntrySkip(1);
|
reader.FileEntrySkip(1);
|
||||||
dontRemoveComma = true;
|
dontRemoveComma = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
/*}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Log.EngineLogger.Error($"Script \"{component.ScriptClassName}\" doesn't have a field with name \"{fieldName}\". (Entity {entity.UUID} (\"{entity.Name}\"))");
|
Log.EngineLogger.Error($"Script \"{component.ScriptClassName}\" doesn't have a field with name \"{fieldName}\". (Entity {entity.UUID} (\"{entity.Name}\"))");
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
Try!(reader.ArrayBlockEnd());
|
Try!(reader.ArrayBlockEnd());
|
||||||
|
|||||||
+1
Submodule GlitchyEngine/vendor/NetHostBeef added at aeb099576d
@@ -1,2 +1,13 @@
|
|||||||
# glitchy-engine-beef
|
# glitchy-engine-beef
|
||||||
A complete refocusation, reimagination and reimplementation of the world-renowned "Glitchy Engine"
|
A complete refocusation, reimagination and reimplementation of the world-renowned "Glitchy Engine"
|
||||||
|
|
||||||
|
# Building
|
||||||
|
|
||||||
|
In order to build this repository you need the following requirements:
|
||||||
|
|
||||||
|
- Windows 10 or newer
|
||||||
|
- [Beef](https://www.beeflang.org/) (at least 0.43.5)
|
||||||
|
- Visual Studio 2022 with the Workloads: "Desktop development with C++" and ".NET desktop development" (TODO: I think it's probably possible to just install some standalone stuff, but idk...)
|
||||||
|
- TODO: I feel like I'm missing something...
|
||||||
|
|
||||||
|
If all of the requirements are met you need to run the following command in powershell (in the root directory of the repository): `./bin/prepare_dev.ps1`. This will run a script that initializes the dependencies. TODO: This script is currently not finished
|
||||||
|
|||||||
+5
-3
@@ -1,4 +1,5 @@
|
|||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace GlitchyEngine;
|
namespace GlitchyEngine;
|
||||||
|
|
||||||
@@ -44,7 +45,8 @@ public class Log
|
|||||||
{
|
{
|
||||||
LogMessage_Impl(LogLevel.Critical, message);
|
LogMessage_Impl(LogLevel.Critical, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
//[MethodImpl(MethodImplOptions.InternalCall)]
|
||||||
public static extern string LogMessage_Impl(LogLevel logLevel, string message);
|
[DllImport("GlitchyEditor.exe", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Log::LogMessage_Impl")]
|
||||||
|
public static extern void LogMessage_Impl(LogLevel logLevel, string message);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,23 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netstandard2.0</TargetFramework>
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
<LangVersion>latest</LangVersion>
|
<LangVersion>latest</LangVersion>
|
||||||
<BaseOutputPath></BaseOutputPath>
|
<BaseOutputPath></BaseOutputPath>
|
||||||
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
|
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
|
||||||
|
|
||||||
|
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
|
||||||
|
<EnableDynamicLoading>true</EnableDynamicLoading>
|
||||||
|
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<!--<DebugType>embedded</DebugType>-->
|
||||||
|
<!--<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>-->
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
|
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
|
||||||
<Exec Command="PowerShell ./postbuild.ps1 -sourceDir $(OutDir) -destinationDir "..\GlitchyEditor\resources\scripts"" />
|
<Exec Command="PowerShell ./postbuild.ps1 -sourceDir $(OutDir) -destinationDir "..\GlitchyEditor\resources\scripts"" />
|
||||||
</Target>
|
</Target>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="Half" Version="1.0.0" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\ScriptCoreGenerator\ScriptCoreGenerator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
|
<ProjectReference Include="..\ScriptCoreGenerator\ScriptCoreGenerator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -1,5 +1,18 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Linq.Expressions;
|
||||||
|
using System.Net.Mime;
|
||||||
|
using System.Net.Security;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Reflection.Emit;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Runtime.Loader;
|
||||||
|
using System.Text;
|
||||||
using GlitchyEngine.Core;
|
using GlitchyEngine.Core;
|
||||||
using GlitchyEngine.Math;
|
using GlitchyEngine.Math;
|
||||||
|
|
||||||
@@ -74,5 +87,390 @@ internal static class ScriptGlue
|
|||||||
internal static extern float4 modf_float4(float4 x, out float4 integerPart);
|
internal static extern float4 modf_float4(float4 x, out float4 integerPart);
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
private static AssemblyLoadContext? _scriptAssemblyContext;
|
||||||
|
|
||||||
|
private static Assembly? _appAssembly;
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
|
public static unsafe void LoadScriptAssembly(byte* assemblyData, long assemblyLength, byte* pdbData, long pdbLength)
|
||||||
|
{
|
||||||
|
using UnmanagedMemoryStream assemblyStream = new(assemblyData, assemblyLength);
|
||||||
|
|
||||||
|
using UnmanagedMemoryStream? pdbStream = (pdbData != null) ? new UnmanagedMemoryStream(pdbData, pdbLength) : null;
|
||||||
|
|
||||||
|
LoadAssembly(assemblyStream, pdbStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void LoadAssembly(Stream assemblyStream, Stream? pdbStream)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_scriptAssemblyContext ??= new AssemblyLoadContext("ScriptContext", true);
|
||||||
|
|
||||||
|
_appAssembly = _scriptAssemblyContext.LoadFromStream(assemblyStream, pdbStream);
|
||||||
|
|
||||||
|
Debug.Assert(_appAssembly != null);
|
||||||
|
|
||||||
|
// Test the loaded assembly
|
||||||
|
_appAssembly.GetType("Sandbox.TestClass")?.GetMethod("InternalTest")?.Invoke(null, null);
|
||||||
|
|
||||||
|
AssemblyLoadContext.EnterContextualReflection(_appAssembly);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Fehler: {e}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
|
public static void UnloadAssemblies()
|
||||||
|
{
|
||||||
|
_scriptAssemblyContext?.Unload();
|
||||||
|
_scriptAssemblyContext = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ScriptClassInfo
|
||||||
|
{
|
||||||
|
public byte[] Name;
|
||||||
|
public Guid Guid;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static NativeScriptClassInfo[]? _unsafeClasses;
|
||||||
|
|
||||||
|
struct NativeScriptClassInfo
|
||||||
|
{
|
||||||
|
public IntPtr Name;
|
||||||
|
public Guid Guid;
|
||||||
|
public ScriptMethods Methods;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Flags]
|
||||||
|
public enum ScriptMethods
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
OnCreate = 0x1,
|
||||||
|
OnUpdate = 0x2,
|
||||||
|
OnDestroy = 0x4,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
|
public static unsafe void GetScriptClasses(void** outBuffer, long* length)
|
||||||
|
{
|
||||||
|
AssemblyLoadContext.EnterContextualReflection(_appAssembly);
|
||||||
|
|
||||||
|
Debug.Assert(_appAssembly != null);
|
||||||
|
|
||||||
|
Internal_FreeScriptClassNames();
|
||||||
|
|
||||||
|
var types = _appAssembly.GetTypes();
|
||||||
|
|
||||||
|
List<(string Name, Guid Guid, ScriptMethods Methods)> scriptClasses = new();
|
||||||
|
|
||||||
|
_updateMethods.Clear();
|
||||||
|
|
||||||
|
foreach (var type in types)
|
||||||
|
{
|
||||||
|
if (type.IsSubclassOf(typeof(Entity)))
|
||||||
|
{
|
||||||
|
string? name = type.FullName;
|
||||||
|
|
||||||
|
if (name == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Guid guid = type.GUID;
|
||||||
|
|
||||||
|
ScriptMethods methods = ScriptMethods.None;
|
||||||
|
|
||||||
|
MethodInfo? onUpdateMethod = type.GetMethod("OnUpdate");
|
||||||
|
if (onUpdateMethod != null)
|
||||||
|
{
|
||||||
|
_updateMethods[type] = onUpdateMethod;
|
||||||
|
|
||||||
|
methods |= ScriptMethods.OnUpdate;
|
||||||
|
}
|
||||||
|
|
||||||
|
scriptClasses.Add((name, guid, methods));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_unsafeClasses = new NativeScriptClassInfo[scriptClasses.Count];
|
||||||
|
|
||||||
|
for (int i = 0; i < _unsafeClasses.Length; i++)
|
||||||
|
{
|
||||||
|
_unsafeClasses[i] = new NativeScriptClassInfo()
|
||||||
|
{
|
||||||
|
Guid = scriptClasses[i].Guid,
|
||||||
|
Name = Marshal.StringToCoTaskMemUTF8(scriptClasses[i].Name),
|
||||||
|
Methods = scriptClasses[i].Methods
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
*outBuffer = (void*)Marshal.UnsafeAddrOfPinnedArrayElement(_unsafeClasses, 0);
|
||||||
|
*length = _unsafeClasses.Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
|
public static void FreeScriptClassNames()
|
||||||
|
{
|
||||||
|
Internal_FreeScriptClassNames();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void Internal_FreeScriptClassNames()
|
||||||
|
{
|
||||||
|
if (_unsafeClasses == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (NativeScriptClassInfo info in _unsafeClasses)
|
||||||
|
{
|
||||||
|
Marshal.FreeCoTaskMem(info.Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
_unsafeClasses = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Dictionary<UUID, (Entity Entity, Type Type)> _entityScripts = new();
|
||||||
|
private static Dictionary<Type, MethodInfo> _updateMethods = new();
|
||||||
|
|
||||||
|
public struct ScriptFunctions
|
||||||
|
{
|
||||||
|
public IntPtr OnCreateMethod;
|
||||||
|
public IntPtr OnUpdateMethod;
|
||||||
|
public IntPtr OnDestroyMethod;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define delegate with the same signature as your method
|
||||||
|
delegate void OnCreateMethodDelegate();
|
||||||
|
|
||||||
|
// Define delegate with the same signature as your method
|
||||||
|
delegate void OnUpdateMethodDelegate(float deltaTime);
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
|
public static void InvokeOnUpdate(UUID entityId, float deltaTime)
|
||||||
|
{
|
||||||
|
AssemblyLoadContext.EnterContextualReflection(_appAssembly);
|
||||||
|
|
||||||
|
Debug.Assert(_entityScripts.ContainsKey(entityId));
|
||||||
|
|
||||||
|
(Entity Entity, Type Type) entity = _entityScripts[entityId];
|
||||||
|
|
||||||
|
entity.Type.GetMethod("OnUpdate", BindingFlags.NonPublic | BindingFlags.Instance)
|
||||||
|
.Invoke(entity.Entity, new object?[]{deltaTime });
|
||||||
|
|
||||||
|
_updateMethods[entity.Type].Invoke(entity.Entity, BindingFlags.NonPublic | BindingFlags.Instance, null,
|
||||||
|
new object[] { deltaTime }, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
|
public static unsafe ScriptFunctions CreateScriptInstance(UUID entityId, byte* scriptClassName)
|
||||||
|
{
|
||||||
|
AssemblyLoadContext.EnterContextualReflection(_appAssembly);
|
||||||
|
|
||||||
|
Debug.Assert(_appAssembly != null);
|
||||||
|
|
||||||
|
string? typeName = Marshal.PtrToStringUTF8((IntPtr)scriptClassName);
|
||||||
|
|
||||||
|
Debug.Assert(typeName != null);
|
||||||
|
|
||||||
|
Type? scriptType = _appAssembly.GetType(typeName);
|
||||||
|
|
||||||
|
Debug.Assert(scriptType != null, "Script class Type not found.");
|
||||||
|
|
||||||
|
//Entity? scriptInstance = Activator.CreateInstance(scriptType, BindingFlags.Instance | BindingFlags.NonPublic, null, entityId) as Entity;
|
||||||
|
|
||||||
|
// Get the private constructor
|
||||||
|
ConstructorInfo constructor = scriptType.BaseType.GetConstructor(
|
||||||
|
BindingFlags.Instance | BindingFlags.NonPublic,
|
||||||
|
null,
|
||||||
|
new Type[] { typeof(UUID) }, // replace this with the types of your constructor parameters
|
||||||
|
null);
|
||||||
|
|
||||||
|
// Call the constructor to create an instance
|
||||||
|
Entity? scriptInstance = constructor?.Invoke(new object[] { entityId }) as Entity;
|
||||||
|
|
||||||
|
ScriptFunctions functions = new();
|
||||||
|
|
||||||
|
_entityScripts.Add(entityId, (scriptInstance!, scriptType));
|
||||||
|
|
||||||
|
//MethodInfo? onCreateMethod = scriptType.GetMethod("OnCreate", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||||
|
//if (onCreateMethod != null)
|
||||||
|
//{
|
||||||
|
// var v = MethodHelpers.GetFunctionPointerForNativeCode(onCreateMethod, null);
|
||||||
|
//}
|
||||||
|
//if (onCreateMethod != null)
|
||||||
|
//{
|
||||||
|
// //Delegate del = CreateDelegateWithTarget(onCreateMethod, scriptInstance);
|
||||||
|
|
||||||
|
// //var createDelegate = onCreateMethod.CreateDelegate<Action>(scriptInstance);
|
||||||
|
// //var createDelegate = onCreateMethod.CreateDelegate(typeof(OnCreateMethodDelegate), scriptInstance);
|
||||||
|
// //onCreateMethod.CreateDelegate(scriptInstance);
|
||||||
|
|
||||||
|
// //functions.OnCreateMethod = Marshal.GetFunctionPointerForDelegate(createDelegate);
|
||||||
|
//}
|
||||||
|
|
||||||
|
//MethodInfo? onUpdateMethod = scriptType.GetMethod("OnUpdate", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||||
|
//if (onUpdateMethod != null)
|
||||||
|
//{
|
||||||
|
// // Create the delegate from your method and instance
|
||||||
|
// OnUpdateMethodDelegate onUpdateDelegate = (OnUpdateMethodDelegate)Delegate.CreateDelegate(typeof(OnUpdateMethodDelegate), scriptInstance, onUpdateMethod);
|
||||||
|
|
||||||
|
// // Get the function pointer from your delegate
|
||||||
|
// functions.OnUpdateMethod = Marshal.GetFunctionPointerForDelegate(onUpdateDelegate);
|
||||||
|
//}
|
||||||
|
// //functions.OnUpdateMethod = Marshal.GetFunctionPointerForDelegate((float deltaTime) => onUpdateMethod.Invoke(scriptInstance, new object?[]{ deltaTime }));
|
||||||
|
|
||||||
|
//MethodInfo? onDestroyMethod = scriptType.GetMethod("OnUpdate", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||||
|
//if (onDestroyMethod != null)
|
||||||
|
// functions.OnDestroyMethod = Marshal.GetFunctionPointerForDelegate(() => onDestroyMethod.Invoke(scriptInstance, null));
|
||||||
|
|
||||||
|
return functions;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Delegate CreateDelegate(MethodInfo method)
|
||||||
|
{
|
||||||
|
if (method == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(method));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!method.IsStatic)
|
||||||
|
{
|
||||||
|
throw new ArgumentException("The provided method must be static.", nameof(method));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (method.IsGenericMethod)
|
||||||
|
{
|
||||||
|
throw new ArgumentException("The provided method must not be generic.", nameof(method));
|
||||||
|
}
|
||||||
|
|
||||||
|
return method.CreateDelegate(Expression.GetDelegateType(
|
||||||
|
(from parameter in method.GetParameters() select parameter.ParameterType)
|
||||||
|
.Concat(new[] { method.ReturnType })
|
||||||
|
.ToArray()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create delegate by methodinfo in target
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="method">method info</param>
|
||||||
|
/// <param name="target">A instance of the object which contains the method where will be execute</param>
|
||||||
|
/// <returns>delegate or null</returns>
|
||||||
|
public static Delegate? CreateDelegateWithTarget(MethodInfo? method, object? target)
|
||||||
|
{
|
||||||
|
if (method is null ||
|
||||||
|
target is null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
//if (method.IsStatic)
|
||||||
|
// return null;
|
||||||
|
|
||||||
|
if (method.IsGenericMethod)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return method.CreateDelegate(Expression.GetDelegateType(
|
||||||
|
(from parameter in method.GetParameters() select parameter.ParameterType)
|
||||||
|
.Concat(new[] { method.ReturnType })
|
||||||
|
.ToArray()), target);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static class MethodHelpers
|
||||||
|
{
|
||||||
|
private const string DelegateTypesAssemblyName = "JitDelegateTypes";
|
||||||
|
|
||||||
|
private static ModuleBuilder _modBuilder;
|
||||||
|
|
||||||
|
private static ConcurrentDictionary<(string, object), Delegate> _delegatesCache;
|
||||||
|
private static ConcurrentDictionary<string, Type> _delegateTypesCache;
|
||||||
|
|
||||||
|
static MethodHelpers()
|
||||||
|
{
|
||||||
|
AssemblyBuilder asmBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName(DelegateTypesAssemblyName), AssemblyBuilderAccess.Run);
|
||||||
|
|
||||||
|
_modBuilder = asmBuilder.DefineDynamicModule(DelegateTypesAssemblyName);
|
||||||
|
|
||||||
|
_delegatesCache = new ConcurrentDictionary<(string, object), Delegate>();
|
||||||
|
_delegateTypesCache = new ConcurrentDictionary<string, Type>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IntPtr GetFunctionPointerForNativeCode(MethodInfo meth, object instance = null)
|
||||||
|
{
|
||||||
|
string funcName = GetFullName(meth);
|
||||||
|
|
||||||
|
Delegate dlg = _delegatesCache.GetOrAdd((funcName, instance), (_) =>
|
||||||
|
{
|
||||||
|
Type[] parameters = meth.GetParameters().Select(x => x.ParameterType).ToArray();
|
||||||
|
|
||||||
|
Type delegateType = GetDelegateType(parameters, meth.ReturnType);
|
||||||
|
|
||||||
|
return Delegate.CreateDelegate(delegateType, instance, meth);
|
||||||
|
});
|
||||||
|
|
||||||
|
return Marshal.GetFunctionPointerForDelegate<Delegate>(dlg);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetFullName(MethodInfo meth)
|
||||||
|
{
|
||||||
|
return $"{meth.DeclaringType.FullName}.{meth.Name}";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Type GetDelegateType(Type[] parameters, Type returnType)
|
||||||
|
{
|
||||||
|
string key = GetFunctionSignatureKey(parameters, returnType);
|
||||||
|
|
||||||
|
return _delegateTypesCache.GetOrAdd(key, (_) => MakeDelegateType(parameters, returnType, key));
|
||||||
|
}
|
||||||
|
|
||||||
|
private const MethodAttributes CtorAttributes =
|
||||||
|
MethodAttributes.RTSpecialName |
|
||||||
|
MethodAttributes.HideBySig |
|
||||||
|
MethodAttributes.Public;
|
||||||
|
|
||||||
|
private const MethodImplAttributes ImplAttributes =
|
||||||
|
MethodImplAttributes.Runtime |
|
||||||
|
MethodImplAttributes.Managed;
|
||||||
|
|
||||||
|
private const MethodAttributes InvokeAttributes =
|
||||||
|
MethodAttributes.Public |
|
||||||
|
MethodAttributes.HideBySig |
|
||||||
|
MethodAttributes.NewSlot |
|
||||||
|
MethodAttributes.Virtual;
|
||||||
|
|
||||||
|
private const TypeAttributes DelegateTypeAttributes =
|
||||||
|
TypeAttributes.Class |
|
||||||
|
TypeAttributes.Public |
|
||||||
|
TypeAttributes.Sealed |
|
||||||
|
TypeAttributes.AnsiClass |
|
||||||
|
TypeAttributes.AutoClass;
|
||||||
|
|
||||||
|
private static readonly Type[] _delegateCtorSignature = { typeof(object), typeof(IntPtr) };
|
||||||
|
|
||||||
|
private static Type MakeDelegateType(Type[] parameters, Type returnType, string name)
|
||||||
|
{
|
||||||
|
TypeBuilder builder = _modBuilder.DefineType(name, DelegateTypeAttributes, typeof(MulticastDelegate));
|
||||||
|
|
||||||
|
builder.DefineConstructor(CtorAttributes, CallingConventions.Standard, _delegateCtorSignature).SetImplementationFlags(ImplAttributes);
|
||||||
|
|
||||||
|
builder.DefineMethod("Invoke", InvokeAttributes, returnType, parameters).SetImplementationFlags(ImplAttributes);
|
||||||
|
|
||||||
|
return builder.CreateTypeInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetFunctionSignatureKey(Type[] parameters, Type returnType)
|
||||||
|
{
|
||||||
|
string sig = GetTypeName(returnType);
|
||||||
|
|
||||||
|
foreach (Type type in parameters)
|
||||||
|
{
|
||||||
|
sig += '_' + GetTypeName(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sig;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetTypeName(Type type)
|
||||||
|
{
|
||||||
|
return type.FullName.Replace(".", string.Empty);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
Write-Output "Preparing repository for development..."
|
||||||
|
|
||||||
|
# Change working directory to repository root
|
||||||
|
Push-Location ($PSScriptRoot + "/..")
|
||||||
|
|
||||||
|
$RootDirectory = $(Get-Location);
|
||||||
|
|
||||||
|
# Note: When adding new scripts make sure to use "Set-Location $RootDirectory" if the script changes the working directory
|
||||||
|
|
||||||
|
# Prepare NetHost
|
||||||
|
Push-Location "GlitchyEngine/vendor/NetHostBeef"
|
||||||
|
Invoke-Expression -Command "./downloadNethost.ps1"
|
||||||
|
Pop-Location
|
||||||
|
|
||||||
|
# Return to original working directory
|
||||||
|
Pop-Location
|
||||||
Reference in New Issue
Block a user