From 9d8c7cf8e3e45cc0d433f22d4097061aeabe1544 Mon Sep 17 00:00:00 2001 From: Sythelux Rikd Date: Wed, 29 May 2024 00:02:26 +0200 Subject: [PATCH 1/6] added base Godot folder and added scripts to deploy as project and as addon --- Src/Godot/Common/DebugDrawer.cs | 371 +++++++++ Src/Godot/Common/GLlineZOff.gdshader | 12 + Src/Godot/Common/GLlineZOn.gdshader | 12 + Src/Godot/Common/ProjectionExtensions.cs | 30 + Src/Godot/Common/QuaternionExtensions.cs | 17 + Src/Godot/Common/RunevisionGodotExtensions.cs | 68 ++ Src/Godot/Editor/GenerationSourceEditor.cs | 60 ++ Src/Godot/Editor/LayerSpecEditor.cs | 9 + Src/Godot/LayerProcGen/GenerationSource.cs | 75 ++ Src/Godot/LayerProcGen/IGodotInstance.cs | 8 + .../LayerProcGen/LayerManagerBehavior.cs | 66 ++ Src/Godot/LayerProcGen/LayerSpec.cs | 49 ++ .../LayerProcGen/VisualizationManager.cs | 711 ++++++++++++++++++ Src/Godot/QueuedGameObjectDestruction.cs | 30 + Src/Godot/TransformWrapper.cs | 31 + godot_addon_release.py | 79 ++ godot_project_release.py | 82 ++ upm_release.py | 2 +- 18 files changed, 1711 insertions(+), 1 deletion(-) create mode 100644 Src/Godot/Common/DebugDrawer.cs create mode 100644 Src/Godot/Common/GLlineZOff.gdshader create mode 100644 Src/Godot/Common/GLlineZOn.gdshader create mode 100644 Src/Godot/Common/ProjectionExtensions.cs create mode 100644 Src/Godot/Common/QuaternionExtensions.cs create mode 100644 Src/Godot/Common/RunevisionGodotExtensions.cs create mode 100644 Src/Godot/Editor/GenerationSourceEditor.cs create mode 100644 Src/Godot/Editor/LayerSpecEditor.cs create mode 100644 Src/Godot/LayerProcGen/GenerationSource.cs create mode 100644 Src/Godot/LayerProcGen/IGodotInstance.cs create mode 100644 Src/Godot/LayerProcGen/LayerManagerBehavior.cs create mode 100644 Src/Godot/LayerProcGen/LayerSpec.cs create mode 100644 Src/Godot/LayerProcGen/VisualizationManager.cs create mode 100644 Src/Godot/QueuedGameObjectDestruction.cs create mode 100644 Src/Godot/TransformWrapper.cs create mode 100755 godot_addon_release.py create mode 100755 godot_project_release.py diff --git a/Src/Godot/Common/DebugDrawer.cs b/Src/Godot/Common/DebugDrawer.cs new file mode 100644 index 0000000..685b789 --- /dev/null +++ b/Src/Godot/Common/DebugDrawer.cs @@ -0,0 +1,371 @@ +/* + * Copyright (c) 2024 Rune Skovbo Johansen + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +using System.Collections.Generic; +using Godot; + +namespace Runevision.Common { + + /// + /// A utility for drawing lines for debug visualizations. + /// + /// + /// Functions that take Vector3 parameters draw in 3D space. Functions that take + /// Vector2 parameters draw in either the XY or XZ plane depending on whether + /// the xzMode property is set to true. + /// + public partial class DebugDrawer : Node { + struct Line { + public Vector3 start; + public Vector3 end; + public Color color; + public float startTime; + public float duration; + + public Line(Vector3 start, Vector3 end, Color color, float startTime, float duration) { + this.start = start; + this.end = end; + this.color = color; + this.startTime = startTime; + this.duration = duration; + } + + public bool DurationElapsed() { + return s_LastTime - startTime >= duration; + } + + public void Draw() { + DebugDraw3D.DrawLine(start, end, color, duration); + } + } + + // Methods that take Vector2 or Rect will draw in xz plane if true, otherwise xy plane. + public static bool xzMode = false; + + static DebugDrawer s_Instance; + static ShaderMaterial s_MatZOn; + static ShaderMaterial s_MatZOff; + static float s_LastTime = -1; + + [Export] + public bool display = true; + [Export(PropertyHint.Layers3DPhysics)] + public long debugLayers = ~0; + [Export] + public Shader shaderZOn; + [Export] + public Shader shaderZOff; + + public static float alpha = 1f; + public static Projection matrix = Projection.Identity; + + static Gradient.ColorSpace colorSpace; + // List linesZOn; + // List linesZOff; + List linesZOnMultiFrame; + List linesZOffMultiFrame; + + public override void _EnterTree() { + if (s_Instance != null) { + this.QueueFree(); + // DestroyImmediate(this); + return; + } + s_Instance = this; + SetMaterial(); + // linesZOn = new List(); + // linesZOff = new List(); + linesZOnMultiFrame = new List(); + linesZOffMultiFrame = new List(); + colorSpace = Gradient.ColorSpace.LinearSrgb; + // TODO: colorSpace = QualitySettings.activeColorSpace; + } + + void SetMaterial() { + s_MatZOn = new ShaderMaterial(); + s_MatZOn.Shader = shaderZOn; + // s_MatZOn.hideFlags = HideFlags.HideAndDontSave; //TODO + s_MatZOff = new ShaderMaterial(); + s_MatZOff.Shader = shaderZOff; + // s_MatZOff.hideFlags = HideFlags.HideAndDontSave; //TODO + } + + public override void _Process(double deltaTime) { + // linesZOn.Clear(); + // linesZOff.Clear(); + CullList(linesZOnMultiFrame); + CullList(linesZOffMultiFrame); + s_LastTime = (float)deltaTime; + } + + void CullList(List list) { + lock (list) { + for (int i = list.Count - 1; i >= 0; i--) { + if (list[i].DurationElapsed()) { + list[i] = list[^1]; + list.RemoveAt(list.Count - 1); + } + } + } + } + + void OnRenderObject() { + if (!display) + return; + // if ((Camera.current.cullingMask & debugLayers) == 0) //TODO + // return; + + s_MatZOn.Shader.Set("Pass",0); //TODO: s_MatZOn.SetPass(0); + // GL.Begin(GL.LINES); + // DrawList(linesZOn); + DrawList(linesZOnMultiFrame); + // GL.End(); + + s_MatZOff.Shader.Set("Pass",0); //TODO: s_MatZOff.SetPass(0); + // GL.Begin(GL.LINES); + // DrawList(linesZOff); + DrawList(linesZOffMultiFrame); + // GL.End(); + } + + void DrawList(List lines) { + lock (lines) { + for (int i = lines.Count - 1; i >= 0; i--) + lines[i].Draw(); + } + } + + public static void DrawLine(Vector3 start, Vector3 end) { + DrawLine(start, end, Colors.White); + } + + public static void DrawLine(Vector3 start, Vector3 end, Color color, float duration = 0, bool depthTest = false) { + //UnityEngine.Debug.DrawLine (start, end, color, duration, depthTest); + if (duration == 0 && !s_Instance.display) + return; + if (start == end) + return; + + color.A *= alpha; + if (colorSpace == Gradient.ColorSpace.LinearSrgb) + color.A *= color.A; + start = matrix.MultiplyPoint3x4(start); + end = matrix.MultiplyPoint3x4(end); + if (duration <= 0) + { + DebugDraw3D.DrawLine(start, end, color, duration); + + // if (depthTest) //TODO: not implemented by DebugDraw3D, yet: https://github.com/DmitriySalnikov/godot_debug_draw_3d/issues/44 + // { + // DebugDraw3D.DrawLine(start, end, color, duration); + // lock (s_Instance.linesZOn) { + // s_Instance.linesZOn.Add(new Line(start, end, color, s_LastTime, duration)); + // } + // } + // else { + // lock (s_Instance.linesZOff) + // { + // s_Instance.linesZOff.Add(new Line(start, end, color, s_LastTime, duration)); + // } + // } + } + else { + if (depthTest) { + lock (s_Instance.linesZOnMultiFrame) { + s_Instance.linesZOnMultiFrame.Add(new Line(start, end, color, s_LastTime, duration)); + } + } + else { + lock (s_Instance.linesZOffMultiFrame) { + s_Instance.linesZOffMultiFrame.Add(new Line(start, end, color, s_LastTime, duration)); + } + } + } + } + + // Draw a line from start to start + dir with color for a duration of time and with or without depth testing. + // If duration is 0 then the ray is rendered 1 frame. + public static void DrawRay(Vector3 start, Vector3 dir) { + DrawLine(start, start + dir, Colors.White); + } + + public static void DrawRay(Vector3 start, Vector3 dir, Color color, float duration = 0, bool depthTest = false) { + if (dir == Vector3.Zero) + return; + DrawLine(start, start + dir, color, duration, depthTest); + } + + public static void DrawRect(float xMin, float yMin, float xMax, float yMax, Color color) { + DrawRect(new Vector2(xMin, yMin), new Vector2(xMax, yMax), 0, color); + } + + public static void DrawRect(Vector2 min, Vector2 max, float depth, Color color) { + if (xzMode) { + DrawLine( + new Vector3(min.X, depth, min.Y), + new Vector3(min.X, depth, max.Y), + color + ); + DrawLine( + new Vector3(max.X, depth, min.Y), + new Vector3(max.X, depth, max.Y), + color + ); + DrawLine( + new Vector3(min.X, depth, min.Y), + new Vector3(max.X, depth, min.Y), + color + ); + DrawLine( + new Vector3(min.X, depth, max.Y), + new Vector3(max.X, depth, max.Y), + color + ); + } + else { + DrawLine( + new Vector3(min.X, min.Y, depth), + new Vector3(min.X, max.Y, depth), + color + ); + DrawLine( + new Vector3(max.X, min.Y, depth), + new Vector3(max.X, max.Y, depth), + color + ); + DrawLine( + new Vector3(min.X, min.Y, depth), + new Vector3(max.X, min.Y, depth), + color + ); + DrawLine( + new Vector3(min.X, max.Y, depth), + new Vector3(max.X, max.Y, depth), + color + ); + } + } + + static Vector3 Mode(Vector2 pos) { + if (xzMode) + return new Vector3(pos.X, 0, pos.Y); + else + return new Vector3(pos.X, pos.Y, 0); + } + + public static void DrawCross(Vector2 pos, float size, Color color, float duration = 0, bool depthTest = false) { + DrawCross(Mode(pos), size, color, duration, depthTest); + } + + public static void DrawCross(Vector3 pos, float size, Color color, float duration = 0, bool depthTest = false) { + DrawRay(pos + Mode(new Vector2(+1, +1) * size), Mode(new Vector2(-2, -2) * size), color, duration, depthTest); + DrawRay(pos + Mode(new Vector2(+1, -1) * size), Mode(new Vector2(-2, +2) * size), color, duration, depthTest); + } + + public static void DrawCircle(Vector2 pos, float radius, int segments, Color color, float duration = 0, bool depthTest = false) { + Vector2 p1 = Vector2.Right * radius + pos; + for (int i = 0; i < segments; i++) { + Vector2 p2 = CirclePoint((i + 1f) / segments) * radius + pos; + DrawLine(Mode(p1), Mode(p2), color, duration, depthTest); + p1 = p2; + } + } + + public static void DrawCircle(Vector3 pos, float radius, int segments, Color color, float duration = 0, bool depthTest = false) { + Vector3 p1 = Vector3.Right * radius + pos; + for (int i = 0; i < segments; i++) { + Vector3 rot = Vector3.Zero; + rot[xzMode ? 1 : 2] = (i + 1f) * 360f / segments; + Vector3 p2 = Quaternion.FromEuler(rot) * Vector3.Right * radius + pos; + DrawLine(p1, p2, color, duration, depthTest); + p1 = p2; + } + } + + static Vector2 CirclePoint(float fraction) { + float f = fraction * 2 * Mathf.Pi; + return new Vector2(Mathf.Cos(f), Mathf.Sin(f)); + } + + // Draw an arrow from start to end with color for a duration of time and with or without depth testing. + // If duration is 0 then the arrow is rendered 1 frame. + public static void DrawLineArrow(Vector3 start, Vector3 end, Color color, float arrowHeadLength = 0.25f, float arrowHeadAngle = 20, float duration = 0, bool depthTest = false) { + DrawArrow(start, end - start, color, arrowHeadLength, arrowHeadAngle, duration, depthTest); + } + + // Draw an arrow from start to start + dir with color for a duration of time and with or without depth testing. + // If duration is 0 then the arrow is rendered 1 frame. + public static void DrawArrow(Vector3 start, Vector3 dir, Color color, float arrowHeadLength = 0.25f, float arrowHeadAngle = 20, float duration = 0, bool depthTest = false) { + if (dir == Vector3.Zero) + return; + DrawRay(start, dir, color, duration, depthTest); + Vector3 right = QuaternionExtensions.LookRotation(dir) * Quaternion.FromEuler(new Vector3(0, 180 + arrowHeadAngle, 0)) * Vector3.Forward; + Vector3 left = QuaternionExtensions.LookRotation(dir) * Quaternion.FromEuler(new Vector3(0, 180 - arrowHeadAngle, 0)) * Vector3.Forward; + DrawRay(start + dir, right * arrowHeadLength, color, duration, depthTest); + DrawRay(start + dir, left * arrowHeadLength, color, duration, depthTest); + } + + // Draw a square with color for a duration of time and with or without depth testing. + // If duration is 0 then the square is renderer 1 frame. + public static void DrawSquare(Vector3 pos, Vector3 scale, Color color, Vector3? rot = null, float duration = 0, bool depthTest = false) { + + DrawSquare(ProjectionExtensions.TRS(pos, Quaternion.FromEuler(rot ?? Vector3.Zero), scale), color, duration, depthTest); + } + + // Draw a square with color for a duration of time and with or without depth testing. + // If duration is 0 then the square is renderer 1 frame. + public static void DrawSquare(Projection matrix, Color color, float duration = 0, bool depthTest = false) { + Vector3 + p1 = matrix.MultiplyPoint3x4(new Vector3(.5f, 0, .5f)), + p2 = matrix.MultiplyPoint3x4(new Vector3(.5f, 0, -.5f)), + p3 = matrix.MultiplyPoint3x4(new Vector3(-.5f, 0, -.5f)), + p4 = matrix.MultiplyPoint3x4(new Vector3(-.5f, 0, .5f)); + + DrawLine(p1, p2, color, duration, depthTest); + DrawLine(p2, p3, color, duration, depthTest); + DrawLine(p3, p4, color, duration, depthTest); + DrawLine(p4, p1, color, duration, depthTest); + } + + // Draw a cube with color for a duration of time and with or without depth testing. + // If duration is 0 then the square is renderer 1 frame. + public static void DrawCube(Vector3 pos, Vector3 scale, Color color, Vector3? rot = null, float duration = 0, bool depthTest = false) { + DrawCube(ProjectionExtensions.TRS(pos, Quaternion.FromEuler(rot ?? Vector3.Zero), scale), color, duration, depthTest); + } + + // Draw a cube with color for a duration of time and with or without depth testing. + // If duration is 0 then the square is renderer 1 frame. + public static void DrawCube(Projection matrix, Color color, float duration = 0, bool depthTest = false) { + Vector3 + down1 = matrix.MultiplyPoint3x4(new Vector3(.5f, -.5f, .5f)), + down2 = matrix.MultiplyPoint3x4(new Vector3(.5f, -.5f, -.5f)), + down3 = matrix.MultiplyPoint3x4(new Vector3(-.5f, -.5f, -.5f)), + down4 = matrix.MultiplyPoint3x4(new Vector3(-.5f, -.5f, .5f)), + up1 = matrix.MultiplyPoint3x4(new Vector3(.5f, .5f, .5f)), + up2 = matrix.MultiplyPoint3x4(new Vector3(.5f, .5f, -.5f)), + up3 = matrix.MultiplyPoint3x4(new Vector3(-.5f, .5f, -.5f)), + up4 = matrix.MultiplyPoint3x4(new Vector3(-.5f, .5f, .5f)); + + DrawLine(down1, down2, color, duration, depthTest); + DrawLine(down2, down3, color, duration, depthTest); + DrawLine(down3, down4, color, duration, depthTest); + DrawLine(down4, down1, color, duration, depthTest); + + DrawLine(down1, up1, color, duration, depthTest); + DrawLine(down2, up2, color, duration, depthTest); + DrawLine(down3, up3, color, duration, depthTest); + DrawLine(down4, up4, color, duration, depthTest); + + DrawLine(up1, up2, color, duration, depthTest); + DrawLine(up2, up3, color, duration, depthTest); + DrawLine(up3, up4, color, duration, depthTest); + DrawLine(up4, up1, color, duration, depthTest); + } + } + +} diff --git a/Src/Godot/Common/GLlineZOff.gdshader b/Src/Godot/Common/GLlineZOff.gdshader new file mode 100644 index 0000000..af55502 --- /dev/null +++ b/Src/Godot/Common/GLlineZOff.gdshader @@ -0,0 +1,12 @@ +shader_type spatial; + +render_mode blend_mix, cull_disabled, depth_draw_never; + +void vertex() { + // No custom vertex logic needed +} + +void fragment() { + // No custom fragment logic needed + // The shader will use the default behavior, which is to render the material's albedo color +} diff --git a/Src/Godot/Common/GLlineZOn.gdshader b/Src/Godot/Common/GLlineZOn.gdshader new file mode 100644 index 0000000..e533427 --- /dev/null +++ b/Src/Godot/Common/GLlineZOn.gdshader @@ -0,0 +1,12 @@ +shader_type spatial; + +render_mode blend_mix, cull_disabled, depth_test_disabled ,depth_draw_never; + +void vertex() { + // No custom vertex logic needed +} + +void fragment() { + // No custom fragment logic needed + // The shader will use the default behavior, which is to render the material's albedo color +} diff --git a/Src/Godot/Common/ProjectionExtensions.cs b/Src/Godot/Common/ProjectionExtensions.cs new file mode 100644 index 0000000..0e0aafe --- /dev/null +++ b/Src/Godot/Common/ProjectionExtensions.cs @@ -0,0 +1,30 @@ +using Godot; + +namespace Runevision.Common; + +public static class ProjectionExtensions +{ + public static Vector3 MultiplyPoint3x4(this Projection m, Vector3 v) + { + return new Vector3 + { + X = (m.X.X * v.X + m.X.Y * v.Y + m.X.Z * v.Z) + m.X.W, + Y = (m.Y.X * v.X + m.Y.Y * v.Y + m.Y.Z * v.Z) + m.Y.W, + Z = (m.Z.X * v.X + m.Z.Y * v.Y + m.Z.Z * v.Z) + m.Z.W + }; + } + + public static Projection TRS(Vector3 position, Quaternion rotation, Vector3 scale) + { + var v0 = rotation * new Vector3(scale.X, 0, 0); + var v1 = rotation * new Vector3(0, scale.Y, 0); + var v2 = rotation * new Vector3(0, 0, scale.Z); + + var c0 = new Vector4(v0.X, v0.Y, v0.Z, 0); + var c1 = new Vector4(v1.X, v1.Y, v1.Z, 0); + var c2 = new Vector4(v2.X, v2.Y, v2.Z, 0); + var c3 = new Vector4(position.X, position.Y, position.Z, 1); + + return new Projection(c0, c1, c2, c3); + } +} \ No newline at end of file diff --git a/Src/Godot/Common/QuaternionExtensions.cs b/Src/Godot/Common/QuaternionExtensions.cs new file mode 100644 index 0000000..a8c3eef --- /dev/null +++ b/Src/Godot/Common/QuaternionExtensions.cs @@ -0,0 +1,17 @@ +using Godot; + +namespace Runevision.Common; + +public class QuaternionExtensions +{ + public static Quaternion LookRotation(Vector3 forward, Vector3? up = default) + { + up ??= Vector3.Up; + + var xDir = forward; + var zDir = xDir.Cross((Vector3)up); + var yDir = zDir.Cross(xDir); + var matrix = new Basis(xDir, yDir, zDir); + return new Quaternion(matrix); + } +} \ No newline at end of file diff --git a/Src/Godot/Common/RunevisionGodotExtensions.cs b/Src/Godot/Common/RunevisionGodotExtensions.cs new file mode 100644 index 0000000..285477c --- /dev/null +++ b/Src/Godot/Common/RunevisionGodotExtensions.cs @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2024 Sythelux Rikd + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +using Godot; + +namespace Runevision.Common; + +public static class RunevisionGodotExtensions +{ + + //@formatter:off + // Select 2 components out of 3. + public static Vector2 xy(this Vector3 v) { return new Vector2(v.X, v.Y); } + public static Vector2 xz(this Vector3 v) { return new Vector2(v.X, v.Z); } + public static Vector2 yz(this Vector3 v) { return new Vector2(v.Y, v.Z); } + + // Flatten one component out of 3. + public static Vector3 oyz(this Vector3 v) { return new Vector3(0f, v.Y, v.Z); } + public static Vector3 xoz(this Vector3 v) { return new Vector3(v.X, 0f, v.Z); } + public static Vector3 xyo(this Vector3 v) { return new Vector3(v.X, v.Y, 0f); } + + // Expand 2 components to 3. + public static Vector3 xyo(this Vector2 v) { return new Vector3(v.X, v.Y, 0f); } + public static Vector3 xoy(this Vector2 v) { return new Vector3(v.X, 0f, v.Y); } + public static Vector3 oxy(this Vector2 v) { return new Vector3(0f, v.X, v.Y); } + //@formatter:on + + public static Vector3 Clamped(this Vector3 v, float length) + { + float l = v.Length(); + if (l > length) + return v / l * length; + return v; + } + + public static void Destroy(this Node obj) + { + obj.QueueFree(); + } + + /// + /// not necessary: https://docs.godotengine.org/en/3.2/classes/class_reference.html#class-reference + /// Meshes are References + /// Unlike Objects, References keep an internal reference counter so that they are automatically released when no longer in use, and only then. References therefore do not need to be freed manually with Object.free. + /// + /// + public static void DestroyIncludingMeshes(this Node go) + { + if (go == null) + return; + go.QueueFree(); + // MeshFilter[] filters = go.GetComponentsInChildren(); + // foreach (var filter in filters) + // { + // // Only destroy meshes with negative instance IDs, + // // which means they were not loaded from disk. + // if (filter.sharedMesh.GetInstanceID() < 0) + // Object.Destroy(filter.sharedMesh); + // } + // + // Object.Destroy(go); + } +} \ No newline at end of file diff --git a/Src/Godot/Editor/GenerationSourceEditor.cs b/Src/Godot/Editor/GenerationSourceEditor.cs new file mode 100644 index 0000000..cd0c9e5 --- /dev/null +++ b/Src/Godot/Editor/GenerationSourceEditor.cs @@ -0,0 +1,60 @@ +using System.Linq; +using Godot; +using Godot.Collections; +using Runevision.Common; +using AppDomain = System.AppDomain; +using Type = System.Type; + +namespace Runevision.LayerProcGen; + +[Tool] +public partial class GenerationSource +{ + static string[] layerTypeStrings; + + [Export] + private string Layer + { + get => layer.className; + set => layer.className = value; + } + + [Export] + private Vector2 Size + { + get => size; + set => size = (Point)value; + } + + public override Array _GetPropertyList() + { + var properties = new Array + { + new() + { + { "name", "Layer" }, + { "type", (int)Variant.Type.StringName }, + { "usage", (int)PropertyUsageFlags.Default }, + { "hint", (int)PropertyHint.Enum }, + { "hint_string", FillLayerHintString() } + } + }; + + return properties; + } + + public static string FillLayerHintString() + { + if (layerTypeStrings == null) + { + var layerBaseType = typeof(AbstractChunkBasedDataLayer); + layerTypeStrings = AppDomain.CurrentDomain.GetAssemblies() + .SelectMany(assembly => assembly.GetTypes()) + .Where(t => t != layerBaseType && layerBaseType.IsAssignableFrom(t) && !t.IsGenericType) + .Select(t => t.FullName) + .ToArray(); + } + + return string.Join(',', layerTypeStrings.Select(s => s[(s.LastIndexOf('.') + 1)..])); + } +} \ No newline at end of file diff --git a/Src/Godot/Editor/LayerSpecEditor.cs b/Src/Godot/Editor/LayerSpecEditor.cs new file mode 100644 index 0000000..2bbd55f --- /dev/null +++ b/Src/Godot/Editor/LayerSpecEditor.cs @@ -0,0 +1,9 @@ +using Godot; + +namespace Runevision.LayerProcGen; + +[Tool] +public partial class LayerSpec +{ + //TODO: https://docs.godotengine.org/en/stable/tutorials/plugins/editor/inspector_plugins.html +} \ No newline at end of file diff --git a/Src/Godot/LayerProcGen/GenerationSource.cs b/Src/Godot/LayerProcGen/GenerationSource.cs new file mode 100644 index 0000000..43988c5 --- /dev/null +++ b/Src/Godot/LayerProcGen/GenerationSource.cs @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2024 Rune Skovbo Johansen, Sythelux Rikd + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +using Runevision.Common; +using Godot; + + +namespace Runevision.LayerProcGen; + +/// +/// Unity component that creates a . +/// + +public partial class GenerationSource : Node3D +{ + public LayerNamedReference layer = new LayerNamedReference(); + public Point size = Point.zero; + + public TopLayerDependency dep { get; private set; } + + public override void _EnterTree() + { + if(!Engine.IsEditorHint()) + UpdateState(); + } + + public override void _ExitTree() + { + if (Engine.IsEditorHint()) return; + if (dep != null) + dep.isActive = false; + } + + void UpdateState() + { + if (layer == null) + return; + + // Get layer instance. + AbstractChunkBasedDataLayer instance = layer.GetLayerInstance(); + + // Create top layer dependency based on layer. + if (instance != null && (dep == null || dep.layer != instance)) + { + if (dep != null) + dep.isActive = false; + dep = new TopLayerDependency(instance, size); + if (instance is IGodotInstance gInst) + CallDeferred("add_child", gInst.LayerRoot()); + } + } + + public override void _Process(double delta) + { + if(Engine.IsEditorHint()) return; + base._Process(delta); + UpdateState(); + if (dep == null) + return; + + Vector3 focusPos = Position; + Point focus; + if (LayerManagerBehavior.instance?.generationPlane == LayerManagerBehavior.GenerationPlane.XZ) + focus = (Point)(focusPos.xz()); + else + focus = (Point)(focusPos.xy()); + dep.SetFocus(focus); + dep.SetSize(Point.Max(Point.one, size)); + } +} \ No newline at end of file diff --git a/Src/Godot/LayerProcGen/IGodotInstance.cs b/Src/Godot/LayerProcGen/IGodotInstance.cs new file mode 100644 index 0000000..2c69506 --- /dev/null +++ b/Src/Godot/LayerProcGen/IGodotInstance.cs @@ -0,0 +1,8 @@ +using Godot; + +namespace Runevision.LayerProcGen; + +internal interface IGodotInstance +{ + public Node LayerRoot(); +} \ No newline at end of file diff --git a/Src/Godot/LayerProcGen/LayerManagerBehavior.cs b/Src/Godot/LayerProcGen/LayerManagerBehavior.cs new file mode 100644 index 0000000..4e7edb2 --- /dev/null +++ b/Src/Godot/LayerProcGen/LayerManagerBehavior.cs @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2024 Rune Skovbo Johansen + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +using Runevision.Common; +using System; +using System.Collections; +using Godot; + +namespace Runevision.LayerProcGen { + + /// + /// Unity component that wraps the LayerManager class. + /// + public partial class LayerManagerBehavior : Node { + + public enum GenerationPlane { XY, XZ } + + public static LayerManagerBehavior instance { get; private set; } + + public static event Action OnUpdate; + + public LayerManager manager { get; private set; } + + [Export] + public bool useParallelThreads = true; + [Export] + public GenerationPlane generationPlane; + [Export] + public Label debugQueueText; + [Export] + public Label debugStatusText; + + public override void _EnterTree() + { + manager = new LayerManager(useParallelThreads); + instance = this; + } + + public override void _ExitTree() + { + manager.OnDestroy(); + } + + public override void _Process(double delta) + { + MainThreadActionQueue.ProcessQueue(); + DebugDrawer.xzMode = (generationPlane == GenerationPlane.XZ); + OnUpdate?.Invoke(); + + // DebugDraw2D.SetText("Action Queue", MainThreadActionQueue.idle ? string.Empty : MainThreadActionQueue.queueCount); alternative + if (debugQueueText is { Visible: true }) + debugQueueText.Text = MainThreadActionQueue.idle ? string.Empty : "Action Queue: " + MainThreadActionQueue.queueCount; + if (debugStatusText is { Visible: true }) + debugStatusText.Text = SimpleProfiler.GetStatus(); + } + + public void StartCoroutine(IEnumerator coroutine) + { + } + } +} \ No newline at end of file diff --git a/Src/Godot/LayerProcGen/LayerSpec.cs b/Src/Godot/LayerProcGen/LayerSpec.cs new file mode 100644 index 0000000..31494f3 --- /dev/null +++ b/Src/Godot/LayerProcGen/LayerSpec.cs @@ -0,0 +1,49 @@ +using Godot; +using Godot.Collections; + +namespace Runevision.LayerProcGen; + +[GlobalClass] +public partial class LayerSpec : Resource +{ + public StringName layerClassName; + [Export] public Color color = Colors.White; + + public override Variant _Get(StringName property) + { + return (string)property switch + { + nameof(layerClassName) => layerClassName ?? string.Empty, + _ => base._Get(property) + }; + } + + public override bool _Set(StringName property, Variant value) + { + switch (property) + { + case nameof(layerClassName): + layerClassName = value.AsStringName(); + return true; + default: + return base._Set(property, value); + } + } + + public override Array _GetPropertyList() + { + var properties = new Array + { + new() + { + { "name", nameof(layerClassName) }, + { "type", (int)Variant.Type.StringName }, + { "usage", (int)PropertyUsageFlags.Default }, + { "hint", (int)PropertyHint.Enum }, + { "hint_string", GenerationSource.FillLayerHintString() } + } + }; + + return properties; + } +} \ No newline at end of file diff --git a/Src/Godot/LayerProcGen/VisualizationManager.cs b/Src/Godot/LayerProcGen/VisualizationManager.cs new file mode 100644 index 0000000..be8017b --- /dev/null +++ b/Src/Godot/LayerProcGen/VisualizationManager.cs @@ -0,0 +1,711 @@ +/* + * Copyright (c) 2024 Rune Skovbo Johansen, Sythelux Rikd + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +using Runevision.Common; +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using Godot; + +namespace Runevision.LayerProcGen +{ + public interface ILayerVisualization + { + void VisualizationUpdate(); + } + + /// + /// A manager for displaying various visualizations of data layers. + /// + /// + /// The manager can visualize chunk bounds, layer bounds, layer dependencies, + /// and has hooks for letting you display your own debug layer visualizations. + /// + /// To use it, add the VisualizationManager component to a GameObject in Unity. + /// For each layer you want to visualize, add an entry in the Layers list where you + /// select the layer in the dropdown, and choose a color for that layer. + /// + /// When the game is running, the VisualizationManager is controlled via + /// DebugOptions. In the debug options you need to both + /// enable the LayerVis toggle and each layer you want visualized under the + /// Layers foldout. + /// + public partial class VisualizationManager : Node + { + [MaybeNull] + public static VisualizationManager instance; + + public DebugToggle debugChunkBounds = DebugToggle.Create("LayerVis/Chunk Bounds", true); + public DebugToggle debugLayerBounds = DebugToggle.Create("LayerVis/Layer Bounds", true); + public DebugToggle debugExactLayerBounds = DebugToggle.Create("LayerVis/Exact Layer Bounds", false); + public DebugToggle debugSources = DebugToggle.Create("LayerVis/Generation Sources", false); + public DebugToggle debugSeparate = DebugToggle.Create("LayerVis/Separate Layers", false); + public DebugToggle debugLayerLabels = DebugToggle.Create("LayerVis/Separate Layers/Layer Labels", true); + public DebugToggle debugDependencies = DebugToggle.Create("LayerVis/Separate Layers/Dependencies", true); + public DebugButton debugToggleAllLayers = DebugButton.Create(">Layers/Toggle All"); + + public class LayerLevelVis + { + public readonly IChunkBasedDataLayer layer; + public readonly int level; + public string name; + public Label nameContent; + public float depthValue; + public float depthValueRaw; + public Vector2 center; + public Vector2 size; + public DebugToggle debugLayerLevel; + public DebugToggle debugLayer; + public LayerSpec layerSpec; + + public Color color => layerSpec.color; + + public LayerLevelVis(IChunkBasedDataLayer layer, int level, LayerSpec layerSpec) + { + this.layer = layer; + this.level = level; + name = layer.GetType().PrettyName(); + if (((AbstractChunkBasedDataLayer)layer).GetLevelCount() > 1) + name += " " + level; + nameContent = new Label { Text = name }; + this.layerSpec = layerSpec; + string debugPath = ">Layers/" + layer.GetType().Name + "/>Levels/Level " + level; + debugLayerLevel = DebugToggle.Create(debugPath, true); + debugLayer = debugLayerLevel.parent.parent as DebugToggle; + if (layer.GetLevelCount() <= 1) + { + debugLayerLevel.hidden = true; + debugLayerLevel.parent.hidden = true; + } + } + } + + [Export] public Godot.Collections.Array layers = new(); + + public enum SeparationUnit + { + WorldUnits, + Chunks + } + + [ExportCategory("Layer Spacing")] [Export] + public float worldOffset; + + [Export] public SeparationUnit spacingUnit = SeparationUnit.Chunks; + [Export] public float spacingAmount = 4; + + List layerLevels; + + public override void _Ready() + { + layerLevels = new List(); + foreach (LayerSpec spec in layers) + { + AddLayer(spec); + } + + debugSeparate.animValueDuration = 0.5f; + instance = this; + + debugToggleAllLayers.Callback += () => + { + bool allEnabled = true; + foreach (LayerLevelVis vis in layerLevels) + { + if (!vis.debugLayer.enabledSelf) + { + allEnabled = false; + break; + } + } + + foreach (LayerLevelVis vis in layerLevels) + { + vis.debugLayer.SetEnabled(!allEnabled); + } + }; + } + + public override void _EnterTree() + { + // if (Engine.IsEditorHint()) + // UnityEditor.SceneView.duringSceneGui += OnDuringSceneGui; + } + + public override void _ExitTree() + { + // UnityEditor.SceneView.duringSceneGui -= OnDuringSceneGui; + } + + void AddLayer(LayerSpec layerSpec) + { + var layerNamedReference = new LayerNamedReference + { + className = layerSpec.layerClassName + }; + IChunkBasedDataLayer layer = (IChunkBasedDataLayer)layerNamedReference.GetLayerInstance(); + if (layer == null) + return; + for (int i = layer.GetLevelCount() - 1; i >= 0; i--) + { + layerLevels.Add(new LayerLevelVis(layer, i, layerSpec)); + } + } + + LayerLevelVis GetVisualizationInfo(IChunkBasedDataLayer layer, int level) + { + foreach (var vis in instance.layerLevels) + { + if (vis.layer == layer && vis.level == level) + return vis; + } + + return null; + } + + public static Projection BeginDebugDraw(IChunkBasedDataLayer layer, int level) + { + if (instance == null) + return Projection.Identity; + var vis = instance.GetVisualizationInfo(layer, level); + if (vis == null) + return Projection.Identity; + float depth = vis.depthValueRaw; + Projection matrix = Projection.Identity; + float animValue = instance.debugSeparate.animValue; + if (DebugDrawer.xzMode) + { + matrix.Y.Y = 1f - animValue; + matrix.Y.W = depth * animValue; + } + else + { + matrix.Z.Z = 1f - animValue; + matrix.Z.W = depth * animValue; + } + + DebugDrawer.matrix = matrix; + return matrix; + } + + public static void EndDebugDraw() + { + DebugDrawer.matrix = Projection.Identity; + } + + void DebugDrawBoundsOfLevel(AbstractLayerChunk chunk, float depth, Color color, float padding) + { + Color col = color; + DebugDrawer.DrawRect( + chunk.bounds.min + Vector2.One * padding, + chunk.bounds.max - Vector2.One * padding, + depth, col); + } + + public override void _Process(double delta) + { + // Draw top layer dependencies / generation sources. + if (debugSources.visible) + { + List topDependencies = LayerManager.instance.topDependencies; + Color col = Colors.White; + col.A = debugSources.animAlpha; + foreach (TopLayerDependency topDep in topDependencies) + { + Vector2 min = topDep.focus - (Vector2)topDep.size * 0.5f; + Vector2 max = min + (Vector2)topDep.size; + DebugDrawer.DrawRect(min, max, 0f, col); + + if (debugDependencies.visible) + { + var depVis = GetVisualizationInfo(topDep.layer, topDep.level); + if (depVis == null || !depVis.debugLayerLevel.visible) + continue; + + Color depCol = col; + depCol.A *= debugDependencies.animAlpha; + depCol.A *= depVis.debugLayerLevel.animAlpha; + DrawBoxDependency(new Vector3(min.X, min.Y, 0), new Vector3(max.X, max.Y, 0), 0, 0, 0, depVis.depthValue, depCol, true); + } + } + } + + // Draw layers. + float layerSeparation = debugSeparate.animValue; + float sign = DebugDrawer.xzMode ? -1 : 1; + float signedSpacingAmount = spacingAmount * sign; + float depth = worldOffset * sign; + IChunkBasedDataLayer lastLayer = null; + float lastChunkSize = 0; + float lastLayerAnimValue = 0; + for (int i = 0; i < layerLevels.Count; i++) + { + LayerLevelVis vis = layerLevels[i]; + if (spacingUnit == SeparationUnit.WorldUnits) + { + depth += vis.debugLayerLevel.animValue * signedSpacingAmount; + } + else + { + float currentChunkSize = Mathf.Max(vis.layer.chunkW, vis.layer.chunkH); + float currentLayerAnimValue = vis.debugLayerLevel.animValue; + float maxChunkSize = Mathf.Max(currentChunkSize, lastChunkSize); + maxChunkSize = Mathf.Lerp(currentChunkSize, maxChunkSize, lastLayerAnimValue); + depth += currentLayerAnimValue * maxChunkSize * signedSpacingAmount; + lastChunkSize = currentChunkSize; + lastLayerAnimValue = currentLayerAnimValue; + } + + vis.depthValueRaw = depth; + vis.depthValue = vis.depthValueRaw * layerSeparation; + + UpdateLayer(vis.layer, vis.level); + + if (vis.layer != lastLayer) + { + lastLayer = vis.layer; + if (vis.layer is ILayerVisualization layerVisualization) + layerVisualization.VisualizationUpdate(); + } + } + } + + void UpdateLayer(IChunkBasedDataLayer layer, int level) + { + var vis = GetVisualizationInfo(layer, level); + if (!vis.debugLayerLevel.visible) + return; + + // Calculate center and size. + Point chunkSize = layer.chunkSize; + Point minIndex = new Point(int.MaxValue, int.MaxValue); + Point maxIndex = new Point(int.MinValue, int.MinValue); + bool any = false; + layer.HandleAllAbstractChunks(level, c => + { + minIndex = Point.Min(minIndex, c.index); + maxIndex = Point.Max(maxIndex, c.index); + any = true; + }); + if (!any) + return; + + vis.center = (Vector2)((minIndex + maxIndex + Point.one) * chunkSize) * 0.5f; + vis.size = (Vector2)((maxIndex + Point.one - minIndex) * chunkSize); + + // Get layer color and opacity. + float alpha = vis.debugLayerLevel.animAlpha; + Color col = vis.color; + col.A = alpha; + + // Draw chunk boundaries and calculate index bounds. + if (debugChunkBounds.visible) + { + float depth = vis.depthValue; + Color chunkCol = col; + chunkCol.A *= debugChunkBounds.animValue * 0.3f; + layer.HandleAllAbstractChunks(level, c => { DebugDrawBoundsOfLevel(c, depth, chunkCol, 0f); }); + } + + // Draw layer bounds, either exact or bounding box. + Color colExact = col; + colExact.A *= debugExactLayerBounds.animAlpha; + if (colExact.A > 0f) + { + DrawExactLayerBounds(vis, layer, level, colExact); + } + + Color colBox = col; + colBox.A *= 1f - debugExactLayerBounds.animAlpha; + if (colBox.A > 0f) + { + DrawBoxLayerBounds(vis, layer, level, colBox); + } + } + + void DrawBoxLayerBounds(LayerLevelVis vis, IChunkBasedDataLayer layer, int level, Color col) + { + float depth = vis.depthValue; + + var min2 = vis.center - vis.size * 0.5f; + var max2 = vis.center + vis.size * 0.5f; + Vector3 min = new Vector3(min2.X, min2.Y, 0); + Vector3 max = new Vector3(max2.X, max2.Y, 0); + + // Draw layer dependencies. + if (debugDependencies.visible) + { + Color depCol = col; + depCol.A *= debugDependencies.animAlpha; + + // Draw dependencies on other layers. + layer.HandleDependenciesForLevel(level, dep => + { + var depVis = GetVisualizationInfo((IChunkBasedDataLayer)dep.layer, dep.level); + DrawBoxDependency(vis, depVis, min, max, dep.hPadding, dep.vPadding, depCol, true); + }); + + // Draw internal dependency on previous level of own layer. + if (level > 0) + { + var depVis = GetVisualizationInfo(layer, level - 1); + DrawBoxDependency(vis, depVis, min, max, layer.chunkW, layer.chunkH, depCol, false); + } + } + + // Draw layer bounds. + if (debugLayerBounds.visible) + { + Color layerCol = col; + layerCol.A *= debugLayerBounds.animAlpha; + DebugDrawer.DrawRect(min2, max2, depth, layerCol); + } + } + + // Temporary structures used in DrawExactLayerBounds. + static Dictionary borderDict = new Dictionary(); + static HashSet usedCorners = new HashSet(); + static List corners = new List(); + static readonly Point[] dirs = new Point[] { Point.right, Point.up, -Point.right, -Point.up }; + + void SetBorderBit(int bit, Point p) + { + byte value = 0; + borderDict.TryGetValue(p, out value); + value |= (byte)(1 << bit); + borderDict[p] = value; + } + + void DrawExactLayerBounds(LayerLevelVis vis, IChunkBasedDataLayer layer, int level, Color col) + { + borderDict.Clear(); + usedCorners.Clear(); + corners.Clear(); + + layer.HandleAllAbstractChunks(level, c => + { + Point p = c.index; + SetBorderBit(0, p); // Bottom left corner + SetBorderBit(1, p + Point.right); // Bottom right corner + SetBorderBit(2, p + Point.one); // Top right corner + SetBorderBit(3, p + Point.up); // Top left corner + }); + + Point chunkSize = layer.chunkSize; + foreach (var kvp in borderDict) + { + if (usedCorners.Contains(kvp.Key)) + continue; + byte val = kvp.Value; + for (int testDir = 0; testDir < 4; testDir++) + { + if (val == (1 << testDir)) + { + int dir = testDir; + Point p = kvp.Key; + Point start = p; + Point offset = dirs[dir]; + int count = 0; + Point cornerDir = dirs[(dir + 3) % 4] - offset; + Point lastCornerDir = cornerDir; + while (count < 1000) + { + Point lastCorner = p; + count++; + usedCorners.Add(p); + int numConvex = 1 << ((dir + 1) % 4); + int numDouble = (1 << ((dir + 3) % 4)) + numConvex; + int numConcave = 1 + 2 + 4 + 8 - (1 << ((dir + 2) % 4)); + while (count < 1000) + { + count++; + p += offset; + if (!borderDict.TryGetValue(p, out val)) + { + Logg.LogError("Border point " + p + " not in dictionary"); + break; + } + + if (val == numConcave || val == numDouble) + { + dir = (dir + 3) % 4; + cornerDir = dirs[dir] - offset; + offset = dirs[dir]; + break; + } + + if (val == numConvex) + { + dir = (dir + 1) % 4; + cornerDir = offset - dirs[dir]; + offset = dirs[dir]; + break; + } + } + + corners.Add((Vector2)lastCorner * chunkSize); + corners.Add((Vector2)lastCornerDir); + corners.Add((Vector2)p * chunkSize); + corners.Add((Vector2)cornerDir); + lastCornerDir = cornerDir; + if (p == start) + break; + } + } + } + } + + // Draw layer dependencies. + if (debugDependencies.visible) + { + Color depCol = col; + depCol.A *= debugDependencies.animAlpha; + + // Draw dependencies on other layers. + layer.HandleDependenciesForLevel(level, dep => + { + var depVis = GetVisualizationInfo((IChunkBasedDataLayer)dep.layer, dep.level); + DrawExactDependency(vis, depVis, corners, dep.hPadding, dep.vPadding, depCol, true); + }); + + // Draw internal dependency on previous level of own layer. + if (level > 0) + { + var depVis = GetVisualizationInfo(layer, level - 1); + DrawExactDependency(vis, depVis, corners, layer.chunkW, layer.chunkH, depCol, false); + } + } + + // Draw layer bounds. + float depth = vis.depthValue; + for (int i = 0; i < corners.Count; i += 4) + { + Vector3 p1 = new Vector3(corners[i + 0].X, corners[i + 0].Y, depth); + Vector3 p2 = new Vector3(corners[i + 2].X, corners[i + 2].Y, depth); + DebugDrawer.DrawLine(FlipYZ(p1), FlipYZ(p2), col); + } + } + + static void DrawBoxDependency( + LayerLevelVis vis, + LayerLevelVis depVis, + Vector3 min, Vector3 max, int hPadding, int vPadding, Color col, bool drawProjection + ) + { + if (depVis == null || !depVis.debugLayerLevel.visible) + return; + float depth = vis.depthValue; + float depthDif = (depVis.depthValue - vis.depthValue); + Color dCol = col; + dCol.A *= depVis.debugLayerLevel.animAlpha; + DrawBoxDependency(min, max, hPadding, vPadding, depth, depthDif, dCol, drawProjection); + } + + static void DrawBoxDependency( + Vector3 min, Vector3 max, int hPadding, int vPadding, + float depth, float depthDif, Color col, bool drawProjection + ) + { + col.A *= 0.5f; + + // Draw lines connecting the two layers. + DebugDrawer.DrawRay( + FlipYZ(new Vector3(min.X, min.Y, depth)), + FlipYZ(new Vector3(-hPadding, -vPadding, depthDif)), col); + DebugDrawer.DrawRay( + FlipYZ(new Vector3(max.X, min.Y, depth)), + FlipYZ(new Vector3(hPadding, -vPadding, depthDif)), col); + DebugDrawer.DrawRay( + FlipYZ(new Vector3(min.X, max.Y, depth)), + FlipYZ(new Vector3(-hPadding, vPadding, depthDif)), col); + DebugDrawer.DrawRay( + FlipYZ(new Vector3(max.X, max.Y, depth)), + FlipYZ(new Vector3(hPadding, vPadding, depthDif)), col); + + // Draw layers projecting dependency area onto depended on layer. + if (drawProjection) + { + min -= new Vector3(hPadding, vPadding, 0f); + max += new Vector3(hPadding, vPadding, 0f); + depth += depthDif; + DebugDrawer.DrawRect(new Vector2(min.X, min.Y), new Vector2(max.X, max.Y), depth, col); + } + } + + static void DrawExactDependency( + LayerLevelVis vis, + LayerLevelVis depVis, + List corners, int hPadding, int vPadding, Color col, bool drawProjection + ) + { + if (depVis == null || !depVis.debugLayerLevel.visible) + return; + float depth = vis.depthValue; + float depthDif = (depVis.depthValue - vis.depthValue); + Color dCol = col; + dCol.A *= depVis.debugLayerLevel.animAlpha; + DrawExactDependency(corners, hPadding, vPadding, depth, depthDif, dCol, drawProjection); + } + + static void DrawExactDependency( + List corners, int hPadding, int vPadding, + float depth, float depthDif, Color col, bool drawProjection + ) + { + col.A *= 0.5f; + for (int i = 0; i < corners.Count; i += 4) + { + Vector3 p1 = new Vector3(corners[i + 0].X, corners[i + 0].Y, 0); + Vector3 p2 = new Vector3(corners[i + 2].X, corners[i + 2].Y, 0); + p1.Z = p2.Z = depth; + Vector3 v1 = new Vector3(corners[i + 1].X, corners[i + 1].Y, 0); + v1.X *= hPadding; + v1.Y *= vPadding; + v1.Z = depthDif; + Vector3 v2 = new Vector3(corners[i + 3].X, corners[i + 3].Y, 0); + v2.X *= hPadding; + v2.Y *= vPadding; + v2.Z = depthDif; + // Draw lines connecting the two layers. + DebugDrawer.DrawRay(FlipYZ(p1), FlipYZ(v1), col); + // Draw layers projecting dependency area onto depended on layer. + if (drawProjection) + DebugDrawer.DrawLine(FlipYZ(p1 + v1), FlipYZ(p2 + v2), col); + } + } + + static Vector3 FlipYZ(Vector3 v) + { + return DebugDrawer.xzMode ? new Vector3(v.X, v.Z, v.Y) : v; + } + + static Label labelStyle; + + // void OnGUI() + // { + // DrawLayerLabels(Camera3D.main, DrawText); + // } + + // void DrawLayerLabels(Camera cam, Action labelMethod) + // { + // if (cam == null || layerLevels == null) + // return; + // + // if (!debugLayerLabels.visible) + // return; + // + // // Fade out labels when they would camera is looking in direction of depth axis. + // Vector3 depthAxis = DebugDrawer.xzMode ? Vector3.up : Vector3.forward; + // float angle = Mathf.Abs(90f - Vector3.Angle(cam.transform.forward, depthAxis)); + // float angleAlpha = Mathf.InverseLerp(55f, 45f, angle); + // if (angleAlpha == 0f) + // return; + // + // if (labelStyle == null) + // { + // labelStyle = new GUIStyle(); + // labelStyle.normal.textColor = Colors.White; + // labelStyle.hover.textColor = labelStyle.normal.textColor; + // labelStyle.padding = new RectOffset(0, 0, 3, 6); + // } + // + // Vector3 right = cam.transform.right.normalized; + // float planeExtendingRight = Vector3.Cross(depthAxis, right).magnitude; + // Vector2 screenOffset = Vector2.right * 10f; + // Vector2 textPivot = new Vector2(0f, 0.5f); + // + // for (int i = 0; i < layerLevels.Count; i++) + // { + // LayerLevelVis vis = layerLevels[i]; + // if (!vis.debugLayerLevel.visible) + // continue; + // Vector3 center = vis.center; + // center.Z = vis.depthValue; + // center = FlipYZ(center); + // Vector3 size = FlipYZ(vis.size); + // Color col = vis.color; + // col.A = vis.debugLayerLevel.animAlpha * debugLayerLabels.animAlpha * angleAlpha; + // col.A *= col.A; + // float sizeAlongRight = Vector3.Scale(right, size).magnitude * 0.5f; + // float sizeMagnitude = size.magnitude * 0.15f; + // Vector3 pos = center + right * (sizeAlongRight + sizeMagnitude) * planeExtendingRight; + // labelMethod(vis, pos, col, labelStyle, screenOffset, textPivot); + // } + // } + + // static void DrawText( + // LayerLevelVis vis, Vector3 worldPos, Color color, Label labelStyle, + // Vector2 screenOffset = default, Vector2 pivot = default + // ) + // { + // Vector3 screenPosRaw = Camera.main.WorldToScreenPoint(worldPos); + // if (screenPosRaw.Z < 0f) + // return; + // Vector2 screenPos = screenPosRaw; + // screenPos.Y = -screenPos.Y + Screen.height; + // screenPos += screenOffset; + // if (screenPos.Y < 0f || screenPos.Y > Screen.height || + // screenPos.X < 0f || screenPos.X > Screen.width + // ) + // return; + // + // GUIUtility.ScaleAroundPivot(Vector2.one * 2f, screenPos); + // Vector2 size = labelStyle.CalcSize(vis.nameContent); + // screenPos -= Vector2.Scale(size, pivot); + // Color restoreColor = GUI.color; + // GUI.color = color; + // GUI.Label(new Rect(screenPos.X, screenPos.Y, size.X, size.Y), vis.nameContent, labelStyle); + // GUI.color = restoreColor; + // GUI.matrix = Projection.Identity; + // } + +#if UNITY_EDITOR + void OnDuringSceneGui(UnityEditor.SceneView sceneView) { + UnityEditor.Handles.BeginGUI(); + DrawLayerLabels(sceneView.camera, DrawSceneViewTextMethod); + UnityEditor.Handles.EndGUI(); + } + + static void DrawSceneViewTextMethod( + LayerLevelVis vis, Vector3 worldPos, Color color, GUIStyle labelStyle, + Vector2 screenOffset = default, Vector2 pivot = default + ) { + UnityEditor.SceneView view = UnityEditor.SceneView.currentDrawingSceneView; + Vector3 screenPosRaw = view.camera.WorldToScreenPoint(worldPos); + if (screenPosRaw.Z < 0f) + return; + Vector2 screenPos = UnityEditor.EditorGUIUtility.PixelsToPoints(screenPosRaw); + #if UNITY_2022_2_OR_NEWER + screenPos += view.position.size - view.cameraViewport.size; + #else + screenPos += new Vector2(0, 20); + #endif + screenPos.Y = -screenPos.Y + view.position.height; + screenPos += screenOffset; + if (screenPos.Y < 0f || screenPos.Y > Screen.height || + screenPos.X < 0f || screenPos.X > Screen.width + ) + return; + + Vector2 size = labelStyle.CalcSize(vis.nameContent); + screenPos -= Vector2.Scale(size, pivot); + Color restoreColor = GUI.color; + GUI.color = color; + Rect position = new Rect(screenPos.X, screenPos.Y, size.X, size.Y); + if (GUI.Button(position, vis.nameContent, labelStyle)) { + Vector3 boundsCenter = vis.center; + boundsCenter.Z = vis.depthValue; + Vector3 boundsSize = vis.size; + Bounds bounds = new Bounds(FlipYZ(boundsCenter), FlipYZ(boundsSize)); + view.Frame(bounds, false); + } + GUI.color = restoreColor; + } +#endif + } +} \ No newline at end of file diff --git a/Src/Godot/QueuedGameObjectDestruction.cs b/Src/Godot/QueuedGameObjectDestruction.cs new file mode 100644 index 0000000..4fd5fdf --- /dev/null +++ b/Src/Godot/QueuedGameObjectDestruction.cs @@ -0,0 +1,30 @@ +using Godot; +using Runevision.LayerProcGen; + +public class QueuedGameObjectDestruction: IQueuedAction { + + TransformWrapper transform; + bool destroyMeshes; + + /// + /// Called by MainThreadActionQueue. + /// + public void Process() { + if (transform.transform != null) { + transform.transform.QueueFree(); //TODO: Godot handles queue free of meshes on itself, I think + // if (destroyMeshes) + // transform.transform.DestroyIncludingMeshes(); + // else + // transform.transform.gameObject.Destroy(); + } + } + + /// + /// Enqueue destruction on the main thread of the GameObject wrapped in the TransformWrapper. + /// + /// The TransformWrapper wrapping the Transform of the GameObject. + /// If true, MeshFilter components are searched for non-persistent meshes, and these will be destroyed too. + public static void Enqueue(TransformWrapper tr, bool destroyMeshes) { + MainThreadActionQueue.Enqueue(new QueuedGameObjectDestruction { transform = tr, destroyMeshes = destroyMeshes }); + } +} \ No newline at end of file diff --git a/Src/Godot/TransformWrapper.cs b/Src/Godot/TransformWrapper.cs new file mode 100644 index 0000000..eb90018 --- /dev/null +++ b/Src/Godot/TransformWrapper.cs @@ -0,0 +1,31 @@ +using Godot; +using Runevision.Common; + +/// +/// Transform stand-in that chunks can create outside of the main thread. +/// +public class TransformWrapper +{ + public Node3D? transform { get; private set; } + + Node3D layerParent; + Point chunkIndex; + + public TransformWrapper(Node3D layerParent, Point chunkIndex) { + this.layerParent = layerParent; + this.chunkIndex = chunkIndex; + } + + /// + /// Creates the wrapper's own Transform if it doesn't exist, then adds the child. + /// + public void AddChild(Node3D child) { + if (transform == null) { + transform = new Node3D{Name="Chunk" + chunkIndex}; + layerParent.AddChild(transform); + // transform.gameObject.layer = layerParent.gameObject.layer; -> only for collision objects in Godot, so we probably have to either change the type or make a child. + } + transform.AddChild(child); + // child.gameObject.layer = transform.gameObject.layer; //same as above + } +} \ No newline at end of file diff --git a/godot_addon_release.py b/godot_addon_release.py new file mode 100755 index 0000000..e973975 --- /dev/null +++ b/godot_addon_release.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python3 +# Sets up godot_addon folder with a Unity importable version of the source. +# Requires: sibling dir "godot_addon" set up as a git clone, checked out to branch "godot_addon". + +import os +import shutil +import re +from typing import List, IO, Tuple + +ADDON_DIR="../addon/" + +PLUGIN_CFG=""" +[plugin] + +name="LayerProcGen" +description="LayerProcGen is a framework that can be used to implement layer-based procedural generation that's infinite, deterministic and contextual." +author="Rune Skovbo Johansen - rune@runevision.com" +contributor="Sythelux Rikd - dersyth@gmail.com" +version="VERSION" +script="LayerProcGen.cs" +language="C-sharp" +documentationUrl="https://runevision.github.io/LayerProcGen/" +""" + +def get_version(): + is_preview = False + for line in open("CHANGELOG.md", "r").readlines(): + if line.startswith("##"): + version = line[2:].strip().lower().lstrip("v").split(" ")[0] + if version == "unreleased": + is_preview = True + continue + if not re.fullmatch("\d+\.\d+.\d", version): + raise Exception(f"Version doesn't appear to be semver: {version}") + return version + ("-preview" if is_preview else "") + + raise Exception("Couldn't find version") + +def build_addon_release(): + global PLUGIN_CFG + # Copy source data + ignored = shutil.ignore_patterns("*.meta", "Unity*", "*.asmdef") + shutil.copytree("Src/", ADDON_DIR, ignore=ignored, dirs_exist_ok=True) + + # Create repo readme from documentation front page + # For this one, images should point to local ones in repo, since GitHub otherwise doesn't support large ones. + readme = open("Documentation/README.md", "r").read() + # Fix image paths + readme = re.sub("\(./([^/]*).png", "(Documentation/\\1.png", readme) + readme = re.sub("\(./([^/]*).gif", "(Documentation/\\1.gif", readme) + # Reroute local links to online html docs + readme = readme.replace("(./", "(https://runevision.github.io/LayerProcGen/") + # Change links to other markdown pages to links to generated html pages + readme = re.sub("/([^/]*).md", "/md_\\1.html", readme) + # Write file with warning at top + open("README.md", "w").write("\n\n\n\n\n" + readme) + + # Create UPM readme from documentation front page + # For this one, images should point to ones in online documentation. + readme = open("Documentation/README.md", "r").read() + # Reroute local links to online html docs + readme = readme.replace("(./", "(https://runevision.github.io/LayerProcGen/") + # Change links to other markdown pages to links to generated html pages + readme = re.sub("/([^/]*).md", "/md_\\1.html", readme) + # Write file with warning at top + open(ADDON_DIR + "README.md", "w").write("\n\n\n\n\n" + readme) + + # Copy other files + shutil.copy("CHANGELOG.md", ADDON_DIR + "CHANGELOG.md") + shutil.copy("LICENSE.md", ADDON_DIR + "LICENSE.md") + shutil.copy("Third Party Notices.md", ADDON_DIR + "Third Party Notices.md") + + # Create package.json file + PLUGIN_CFG = PLUGIN_CFG.replace("VERSION", get_version()) + open(ADDON_DIR + "plugin.cfg", "w").write(PLUGIN_CFG) + + +if __name__ == "__main__": + build_addon_release() \ No newline at end of file diff --git a/godot_project_release.py b/godot_project_release.py new file mode 100755 index 0000000..bd88679 --- /dev/null +++ b/godot_project_release.py @@ -0,0 +1,82 @@ +#!/usr/bin/env python3 +# Sets up godot_addon folder with a Unity importable version of the source. +# Requires: sibling dir "godot_addon" set up as a git clone, checked out to branch "godot_addon". + +import os +import shutil +import re +from typing import List, IO, Tuple + +PROJECT_DIR="../godot_project/" +ADDON_DIR=PROJECT_DIR + "/addons/LayerProcGen/" + +PLUGIN_CFG=""" +[plugin] + +name="LayerProcGen" +description="LayerProcGen is a framework that can be used to implement layer-based procedural generation that's infinite, deterministic and contextual." +author="Rune Skovbo Johansen - rune@runevision.com" +contributor="Sythelux Rikd - dersyth@gmail.com" +version="VERSION" +script="LayerProcGen.cs" +language="C-sharp" +documentationUrl="https://runevision.github.io/LayerProcGen/" +""" + +def get_version(): + is_preview = False + for line in open("CHANGELOG.md", "r").readlines(): + if line.startswith("##"): + version = line[2:].strip().lower().lstrip("v").split(" ")[0] + if version == "unreleased": + is_preview = True + continue + if not re.fullmatch("\d+\.\d+.\d", version): + raise Exception(f"Version doesn't appear to be semver: {version}") + return version + ("-preview" if is_preview else "") + + raise Exception("Couldn't find version") + +def build_addon_release(): + global PLUGIN_CFG + version = get_version() + # Copy source data + ignored = shutil.ignore_patterns("*.meta", "*.asmdef") + shutil.copytree("Src/", ADDON_DIR, ignore=ignored, dirs_exist_ok=True) + # shutil.copytree("Samples/", PROJECT_DIR + "Samples/"+version+"/", ignore=ignored, dirs_exist_ok=True) # Samples stay in that repo + + # Create repo readme from documentation front page + # For this one, images should point to local ones in repo, since GitHub otherwise doesn't support large ones. + readme = open("Documentation/README.md", "r").read() + # Fix image paths + readme = re.sub("\(./([^/]*).png", "(Documentation/\\1.png", readme) + readme = re.sub("\(./([^/]*).gif", "(Documentation/\\1.gif", readme) + # Reroute local links to online html docs + readme = readme.replace("(./", "(https://runevision.github.io/LayerProcGen/") + # Change links to other markdown pages to links to generated html pages + readme = re.sub("/([^/]*).md", "/md_\\1.html", readme) + # Write file with warning at top + open("README.md", "w").write("\n\n\n\n\n" + readme) + + # Create UPM readme from documentation front page + # For this one, images should point to ones in online documentation. + readme = open("Documentation/README.md", "r").read() + # Reroute local links to online html docs + readme = readme.replace("(./", "(https://runevision.github.io/LayerProcGen/") + # Change links to other markdown pages to links to generated html pages + readme = re.sub("/([^/]*).md", "/md_\\1.html", readme) + # Write file with warning at top + open(PROJECT_DIR + "README.md", "w").write("\n\n\n\n\n" + readme) + + # Copy other files + shutil.copy("CHANGELOG.md", ADDON_DIR + "CHANGELOG.md") + shutil.copy("LICENSE.md", ADDON_DIR + "LICENSE.md") + shutil.copy("Third Party Notices.md", ADDON_DIR + "Third Party Notices.md") + + # Create package.json file + PLUGIN_CFG = PLUGIN_CFG.replace("VERSION", version) + open(ADDON_DIR + "plugin.cfg", "w").write(PLUGIN_CFG) + + +if __name__ == "__main__": + build_addon_release() \ No newline at end of file diff --git a/upm_release.py b/upm_release.py index 7887121..d79bf30 100644 --- a/upm_release.py +++ b/upm_release.py @@ -67,7 +67,7 @@ def get_version(): def build_upm_release(): # Copy source data - ignored = shutil.ignore_patterns() + ignored = shutil.ignore_patterns("Godot*") shutil.copytree("Src/", UPM_DIR, ignore=ignored, dirs_exist_ok=True) shutil.copytree("Samples/", UPM_DIR + "Samples~/", ignore=ignored, dirs_exist_ok=True) From 9e256877190649368a695e4803da889953e6757c Mon Sep 17 00:00:00 2001 From: Sythelux Rikd Date: Wed, 29 May 2024 00:15:35 +0200 Subject: [PATCH 2/6] added compiler flags for Unity and Godot --- Src/Godot/Common/DebugDrawer.cs | 2 ++ Src/Godot/Common/ProjectionExtensions.cs | 4 +++- Src/Godot/Common/QuaternionExtensions.cs | 4 +++- Src/Godot/Common/RunevisionGodotExtensions.cs | 4 +++- Src/Godot/Editor/GenerationSourceEditor.cs | 4 +++- Src/Godot/Editor/LayerSpecEditor.cs | 4 +++- Src/Godot/LayerProcGen/GenerationSource.cs | 4 +++- Src/Godot/LayerProcGen/IGodotInstance.cs | 4 +++- Src/Godot/LayerProcGen/LayerManagerBehavior.cs | 4 +++- Src/Godot/LayerProcGen/LayerSpec.cs | 4 +++- Src/Godot/LayerProcGen/VisualizationManager.cs | 4 +++- Src/Godot/QueuedGameObjectDestruction.cs | 4 +++- Src/Godot/TransformWrapper.cs | 4 +++- Src/Unity/Common/CallbackHub.cs | 3 ++- Src/Unity/Common/DebugDrawer.cs | 2 ++ Src/Unity/Common/DebugOptions.cs | 2 ++ Src/Unity/Common/ForwardingUnityWrapper.cs | 2 ++ Src/Unity/Common/RunevisionUnityExtensions.cs | 2 ++ Src/Unity/Editor/DebugOptionsWindow.cs | 2 ++ Src/Unity/Editor/GenerationSourceEditor.cs | 2 ++ Src/Unity/Editor/GridBounds3Drawer.cs | 2 ++ Src/Unity/Editor/GridBoundsDrawer.cs | 2 ++ Src/Unity/Editor/LayerNamedReferenceDrawer.cs | 2 ++ Src/Unity/Editor/LayerSpecDrawer.cs | 2 ++ Src/Unity/Editor/Point3Drawer.cs | 2 ++ Src/Unity/Editor/PointDrawer.cs | 2 ++ Src/Unity/Editor/UnitTests/MathTests.cs | 2 ++ Src/Unity/LayerProcGen/GenerationSource.cs | 2 ++ Src/Unity/LayerProcGen/LayerManagerBehavior.cs | 2 ++ Src/Unity/LayerProcGen/TransformWrapper.cs | 2 ++ Src/Unity/LayerProcGen/VisualizationManager.cs | 2 ++ Src/Unity/SaveState/FBPPChooser.cs | 2 ++ Src/Unity/SaveState/FileBasedPlayerPrefs/Runtime/FBPP.cs | 2 ++ .../SaveState/FileBasedPlayerPrefs/Runtime/FBPPConfig.cs | 2 ++ .../FileBasedPlayerPrefs/Runtime/FBPPSaveFileModel.cs | 4 +++- Src/Unity/SaveState/WorldStateFBPP.cs | 2 ++ 36 files changed, 85 insertions(+), 14 deletions(-) diff --git a/Src/Godot/Common/DebugDrawer.cs b/Src/Godot/Common/DebugDrawer.cs index 685b789..3950029 100644 --- a/Src/Godot/Common/DebugDrawer.cs +++ b/Src/Godot/Common/DebugDrawer.cs @@ -5,6 +5,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +#if GODOT4 using System.Collections.Generic; using Godot; @@ -369,3 +370,4 @@ public static void DrawCube(Projection matrix, Color color, float duration = 0, } } +#endif \ No newline at end of file diff --git a/Src/Godot/Common/ProjectionExtensions.cs b/Src/Godot/Common/ProjectionExtensions.cs index 0e0aafe..235fbfc 100644 --- a/Src/Godot/Common/ProjectionExtensions.cs +++ b/Src/Godot/Common/ProjectionExtensions.cs @@ -1,3 +1,4 @@ +#if GODOT4 using Godot; namespace Runevision.Common; @@ -27,4 +28,5 @@ public static Projection TRS(Vector3 position, Quaternion rotation, Vector3 scal return new Projection(c0, c1, c2, c3); } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/Src/Godot/Common/QuaternionExtensions.cs b/Src/Godot/Common/QuaternionExtensions.cs index a8c3eef..14627a7 100644 --- a/Src/Godot/Common/QuaternionExtensions.cs +++ b/Src/Godot/Common/QuaternionExtensions.cs @@ -1,3 +1,4 @@ +#if GODOT4 using Godot; namespace Runevision.Common; @@ -14,4 +15,5 @@ public static Quaternion LookRotation(Vector3 forward, Vector3? up = default) var matrix = new Basis(xDir, yDir, zDir); return new Quaternion(matrix); } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/Src/Godot/Common/RunevisionGodotExtensions.cs b/Src/Godot/Common/RunevisionGodotExtensions.cs index 285477c..31c134e 100644 --- a/Src/Godot/Common/RunevisionGodotExtensions.cs +++ b/Src/Godot/Common/RunevisionGodotExtensions.cs @@ -5,6 +5,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +#if GODOT4 using Godot; @@ -65,4 +66,5 @@ public static void DestroyIncludingMeshes(this Node go) // // Object.Destroy(go); } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/Src/Godot/Editor/GenerationSourceEditor.cs b/Src/Godot/Editor/GenerationSourceEditor.cs index cd0c9e5..95a72f3 100644 --- a/Src/Godot/Editor/GenerationSourceEditor.cs +++ b/Src/Godot/Editor/GenerationSourceEditor.cs @@ -1,3 +1,4 @@ +#if GODOT4 using System.Linq; using Godot; using Godot.Collections; @@ -57,4 +58,5 @@ public static string FillLayerHintString() return string.Join(',', layerTypeStrings.Select(s => s[(s.LastIndexOf('.') + 1)..])); } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/Src/Godot/Editor/LayerSpecEditor.cs b/Src/Godot/Editor/LayerSpecEditor.cs index 2bbd55f..d0511b1 100644 --- a/Src/Godot/Editor/LayerSpecEditor.cs +++ b/Src/Godot/Editor/LayerSpecEditor.cs @@ -1,3 +1,4 @@ +#if GODOT4 using Godot; namespace Runevision.LayerProcGen; @@ -6,4 +7,5 @@ namespace Runevision.LayerProcGen; public partial class LayerSpec { //TODO: https://docs.godotengine.org/en/stable/tutorials/plugins/editor/inspector_plugins.html -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/Src/Godot/LayerProcGen/GenerationSource.cs b/Src/Godot/LayerProcGen/GenerationSource.cs index 43988c5..d241360 100644 --- a/Src/Godot/LayerProcGen/GenerationSource.cs +++ b/Src/Godot/LayerProcGen/GenerationSource.cs @@ -5,6 +5,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +#if GODOT4 using Runevision.Common; using Godot; @@ -72,4 +73,5 @@ public override void _Process(double delta) dep.SetFocus(focus); dep.SetSize(Point.Max(Point.one, size)); } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/Src/Godot/LayerProcGen/IGodotInstance.cs b/Src/Godot/LayerProcGen/IGodotInstance.cs index 2c69506..208dc4a 100644 --- a/Src/Godot/LayerProcGen/IGodotInstance.cs +++ b/Src/Godot/LayerProcGen/IGodotInstance.cs @@ -1,3 +1,4 @@ +#if GODOT4 using Godot; namespace Runevision.LayerProcGen; @@ -5,4 +6,5 @@ namespace Runevision.LayerProcGen; internal interface IGodotInstance { public Node LayerRoot(); -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/Src/Godot/LayerProcGen/LayerManagerBehavior.cs b/Src/Godot/LayerProcGen/LayerManagerBehavior.cs index 4e7edb2..8528d8f 100644 --- a/Src/Godot/LayerProcGen/LayerManagerBehavior.cs +++ b/Src/Godot/LayerProcGen/LayerManagerBehavior.cs @@ -5,6 +5,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +#if GODOT4 using Runevision.Common; using System; @@ -63,4 +64,5 @@ public void StartCoroutine(IEnumerator coroutine) { } } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/Src/Godot/LayerProcGen/LayerSpec.cs b/Src/Godot/LayerProcGen/LayerSpec.cs index 31494f3..e06825c 100644 --- a/Src/Godot/LayerProcGen/LayerSpec.cs +++ b/Src/Godot/LayerProcGen/LayerSpec.cs @@ -1,3 +1,4 @@ +#if GODOT4 using Godot; using Godot.Collections; @@ -46,4 +47,5 @@ public override Array _GetPropertyList() return properties; } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/Src/Godot/LayerProcGen/VisualizationManager.cs b/Src/Godot/LayerProcGen/VisualizationManager.cs index be8017b..af2238a 100644 --- a/Src/Godot/LayerProcGen/VisualizationManager.cs +++ b/Src/Godot/LayerProcGen/VisualizationManager.cs @@ -5,6 +5,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +#if GODOT4 using Runevision.Common; using System; @@ -708,4 +709,5 @@ static void DrawSceneViewTextMethod( } #endif } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/Src/Godot/QueuedGameObjectDestruction.cs b/Src/Godot/QueuedGameObjectDestruction.cs index 4fd5fdf..30387e6 100644 --- a/Src/Godot/QueuedGameObjectDestruction.cs +++ b/Src/Godot/QueuedGameObjectDestruction.cs @@ -1,3 +1,4 @@ +#if GODOT4 using Godot; using Runevision.LayerProcGen; @@ -27,4 +28,5 @@ public void Process() { public static void Enqueue(TransformWrapper tr, bool destroyMeshes) { MainThreadActionQueue.Enqueue(new QueuedGameObjectDestruction { transform = tr, destroyMeshes = destroyMeshes }); } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/Src/Godot/TransformWrapper.cs b/Src/Godot/TransformWrapper.cs index eb90018..34ccaf2 100644 --- a/Src/Godot/TransformWrapper.cs +++ b/Src/Godot/TransformWrapper.cs @@ -1,3 +1,4 @@ +#if GODOT4 using Godot; using Runevision.Common; @@ -28,4 +29,5 @@ public void AddChild(Node3D child) { transform.AddChild(child); // child.gameObject.layer = transform.gameObject.layer; //same as above } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/Src/Unity/Common/CallbackHub.cs b/Src/Unity/Common/CallbackHub.cs index 56904e0..8cee1e9 100644 --- a/Src/Unity/Common/CallbackHub.cs +++ b/Src/Unity/Common/CallbackHub.cs @@ -5,7 +5,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ - +#if UNITY_2019_4_OR_NEWER using System; using UnityEngine; @@ -67,3 +67,4 @@ public static void ExecuteOnMainThread(Action action) { update += handler; } } +#endif \ No newline at end of file diff --git a/Src/Unity/Common/DebugDrawer.cs b/Src/Unity/Common/DebugDrawer.cs index b93c789..0715897 100644 --- a/Src/Unity/Common/DebugDrawer.cs +++ b/Src/Unity/Common/DebugDrawer.cs @@ -5,6 +5,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +#if UNITY_2019_4_OR_NEWER using System.Collections.Generic; using UnityEngine; @@ -356,3 +357,4 @@ public static void DrawCube(Matrix4x4 matrix, Color color, float duration = 0, b } } +#endif \ No newline at end of file diff --git a/Src/Unity/Common/DebugOptions.cs b/Src/Unity/Common/DebugOptions.cs index 0cab904..aff8950 100644 --- a/Src/Unity/Common/DebugOptions.cs +++ b/Src/Unity/Common/DebugOptions.cs @@ -5,6 +5,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +#if UNITY_2019_4_OR_NEWER using UnityEngine; @@ -147,3 +148,4 @@ void OnGUI() { } } +#endif \ No newline at end of file diff --git a/Src/Unity/Common/ForwardingUnityWrapper.cs b/Src/Unity/Common/ForwardingUnityWrapper.cs index ea4fce6..c8cb4f0 100644 --- a/Src/Unity/Common/ForwardingUnityWrapper.cs +++ b/Src/Unity/Common/ForwardingUnityWrapper.cs @@ -5,6 +5,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +#if UNITY_2019_4_OR_NEWER using UnityEngine; using UnityEngine.Profiling; @@ -34,3 +35,4 @@ static void RegisterAfterSceneLoad() { } } +#endif \ No newline at end of file diff --git a/Src/Unity/Common/RunevisionUnityExtensions.cs b/Src/Unity/Common/RunevisionUnityExtensions.cs index d4562a8..eb3912f 100644 --- a/Src/Unity/Common/RunevisionUnityExtensions.cs +++ b/Src/Unity/Common/RunevisionUnityExtensions.cs @@ -5,6 +5,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +#if UNITY_2019_4_OR_NEWER using UnityEngine; @@ -53,3 +54,4 @@ public static void DestroyIncludingMeshes(this GameObject go) { } } +#endif \ No newline at end of file diff --git a/Src/Unity/Editor/DebugOptionsWindow.cs b/Src/Unity/Editor/DebugOptionsWindow.cs index a96739d..b41ee4a 100644 --- a/Src/Unity/Editor/DebugOptionsWindow.cs +++ b/Src/Unity/Editor/DebugOptionsWindow.cs @@ -5,6 +5,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +#if UNITY_2019_4_OR_NEWER using Runevision.Common; using UnityEngine; @@ -80,3 +81,4 @@ void DrawOption(DebugOption option, int level) { } } +#endif \ No newline at end of file diff --git a/Src/Unity/Editor/GenerationSourceEditor.cs b/Src/Unity/Editor/GenerationSourceEditor.cs index 77a806a..d7140e4 100644 --- a/Src/Unity/Editor/GenerationSourceEditor.cs +++ b/Src/Unity/Editor/GenerationSourceEditor.cs @@ -5,6 +5,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +#if UNITY_2019_4_OR_NEWER using Runevision.LayerProcGen; using UnityEditor; @@ -27,3 +28,4 @@ public Bounds OnGetFrameBounds() { } } +#endif \ No newline at end of file diff --git a/Src/Unity/Editor/GridBounds3Drawer.cs b/Src/Unity/Editor/GridBounds3Drawer.cs index fb7c30b..c9d02e4 100644 --- a/Src/Unity/Editor/GridBounds3Drawer.cs +++ b/Src/Unity/Editor/GridBounds3Drawer.cs @@ -5,6 +5,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +#if UNITY_2019_4_OR_NEWER using Runevision.Common; using UnityEditor; @@ -41,3 +42,4 @@ public override float GetPropertyHeight(SerializedProperty property, GUIContent } } +#endif \ No newline at end of file diff --git a/Src/Unity/Editor/GridBoundsDrawer.cs b/Src/Unity/Editor/GridBoundsDrawer.cs index 924642d..3b5d312 100644 --- a/Src/Unity/Editor/GridBoundsDrawer.cs +++ b/Src/Unity/Editor/GridBoundsDrawer.cs @@ -5,6 +5,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +#if UNITY_2019_4_OR_NEWER using Runevision.Common; using UnityEditor; @@ -40,3 +41,4 @@ public override float GetPropertyHeight(SerializedProperty property, GUIContent } } +#endif \ No newline at end of file diff --git a/Src/Unity/Editor/LayerNamedReferenceDrawer.cs b/Src/Unity/Editor/LayerNamedReferenceDrawer.cs index 439fcc1..d9cf580 100644 --- a/Src/Unity/Editor/LayerNamedReferenceDrawer.cs +++ b/Src/Unity/Editor/LayerNamedReferenceDrawer.cs @@ -5,6 +5,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +#if UNITY_2019_4_OR_NEWER using Runevision.LayerProcGen; using System; @@ -43,3 +44,4 @@ public override void OnGUI(Rect position, SerializedProperty property, GUIConten } } +#endif \ No newline at end of file diff --git a/Src/Unity/Editor/LayerSpecDrawer.cs b/Src/Unity/Editor/LayerSpecDrawer.cs index c5d7a94..beef02c 100644 --- a/Src/Unity/Editor/LayerSpecDrawer.cs +++ b/Src/Unity/Editor/LayerSpecDrawer.cs @@ -5,6 +5,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +#if UNITY_2019_4_OR_NEWER using Runevision.LayerProcGen; using UnityEditor; @@ -28,3 +29,4 @@ public override void OnGUI(Rect position, SerializedProperty property, GUIConten } } +#endif diff --git a/Src/Unity/Editor/Point3Drawer.cs b/Src/Unity/Editor/Point3Drawer.cs index c9e1bc7..a82f954 100644 --- a/Src/Unity/Editor/Point3Drawer.cs +++ b/Src/Unity/Editor/Point3Drawer.cs @@ -5,6 +5,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +#if UNITY_2019_4_OR_NEWER using Runevision.Common; using UnityEditor; @@ -27,3 +28,4 @@ public override void OnGUI(Rect position, SerializedProperty property, GUIConten } } +#endif \ No newline at end of file diff --git a/Src/Unity/Editor/PointDrawer.cs b/Src/Unity/Editor/PointDrawer.cs index 6f51c2f..9314091 100644 --- a/Src/Unity/Editor/PointDrawer.cs +++ b/Src/Unity/Editor/PointDrawer.cs @@ -5,6 +5,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +#if UNITY_2019_4_OR_NEWER using Runevision.Common; using UnityEditor; @@ -26,3 +27,4 @@ public override void OnGUI(Rect position, SerializedProperty property, GUIConten } } +#endif \ No newline at end of file diff --git a/Src/Unity/Editor/UnitTests/MathTests.cs b/Src/Unity/Editor/UnitTests/MathTests.cs index 81089bc..4f303de 100644 --- a/Src/Unity/Editor/UnitTests/MathTests.cs +++ b/Src/Unity/Editor/UnitTests/MathTests.cs @@ -5,6 +5,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +#if UNITY_2019_4_OR_NEWER using NUnit.Framework; using Runevision.Common; @@ -68,3 +69,4 @@ public void DPointMagnitude() { } +#endif \ No newline at end of file diff --git a/Src/Unity/LayerProcGen/GenerationSource.cs b/Src/Unity/LayerProcGen/GenerationSource.cs index 78d20ab..75c900c 100644 --- a/Src/Unity/LayerProcGen/GenerationSource.cs +++ b/Src/Unity/LayerProcGen/GenerationSource.cs @@ -5,6 +5,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +#if UNITY_2019_4_OR_NEWER using Runevision.Common; using UnityEngine; @@ -62,3 +63,4 @@ void Update() { } } +#endif \ No newline at end of file diff --git a/Src/Unity/LayerProcGen/LayerManagerBehavior.cs b/Src/Unity/LayerProcGen/LayerManagerBehavior.cs index 3ec3339..9600f16 100644 --- a/Src/Unity/LayerProcGen/LayerManagerBehavior.cs +++ b/Src/Unity/LayerProcGen/LayerManagerBehavior.cs @@ -5,6 +5,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +#if UNITY_2019_4_OR_NEWER using Runevision.Common; using System; @@ -59,3 +60,4 @@ protected virtual void Update() { } } } +#endif \ No newline at end of file diff --git a/Src/Unity/LayerProcGen/TransformWrapper.cs b/Src/Unity/LayerProcGen/TransformWrapper.cs index eb24a55..5b0fbf3 100644 --- a/Src/Unity/LayerProcGen/TransformWrapper.cs +++ b/Src/Unity/LayerProcGen/TransformWrapper.cs @@ -5,6 +5,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +#if UNITY_2019_4_OR_NEWER using Runevision.Common; using UnityEngine; @@ -41,3 +42,4 @@ public void AddChild(Transform child) { } } +#endif \ No newline at end of file diff --git a/Src/Unity/LayerProcGen/VisualizationManager.cs b/Src/Unity/LayerProcGen/VisualizationManager.cs index 2bf551b..3e3a006 100644 --- a/Src/Unity/LayerProcGen/VisualizationManager.cs +++ b/Src/Unity/LayerProcGen/VisualizationManager.cs @@ -5,6 +5,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +#if UNITY_2019_4_OR_NEWER using Runevision.Common; using System; @@ -631,3 +632,4 @@ static void DrawSceneViewTextMethod( } } +#endif \ No newline at end of file diff --git a/Src/Unity/SaveState/FBPPChooser.cs b/Src/Unity/SaveState/FBPPChooser.cs index 86a1fb4..4ee29f5 100644 --- a/Src/Unity/SaveState/FBPPChooser.cs +++ b/Src/Unity/SaveState/FBPPChooser.cs @@ -5,6 +5,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +#if UNITY_2019_4_OR_NEWER using UnityEngine; @@ -19,3 +20,4 @@ static void Register() { } } +#endif \ No newline at end of file diff --git a/Src/Unity/SaveState/FileBasedPlayerPrefs/Runtime/FBPP.cs b/Src/Unity/SaveState/FileBasedPlayerPrefs/Runtime/FBPP.cs index 3c1d67c..7b865c9 100644 --- a/Src/Unity/SaveState/FileBasedPlayerPrefs/Runtime/FBPP.cs +++ b/Src/Unity/SaveState/FileBasedPlayerPrefs/Runtime/FBPP.cs @@ -1,3 +1,4 @@ +#if UNITY_2019_4_OR_NEWER using System; using System.Text; using System.IO; @@ -276,3 +277,4 @@ private static string DataScrambler(string data) { } +#endif \ No newline at end of file diff --git a/Src/Unity/SaveState/FileBasedPlayerPrefs/Runtime/FBPPConfig.cs b/Src/Unity/SaveState/FileBasedPlayerPrefs/Runtime/FBPPConfig.cs index 3af8b9d..e829bdf 100755 --- a/Src/Unity/SaveState/FileBasedPlayerPrefs/Runtime/FBPPConfig.cs +++ b/Src/Unity/SaveState/FileBasedPlayerPrefs/Runtime/FBPPConfig.cs @@ -1,3 +1,4 @@ +#if UNITY_2019_4_OR_NEWER using System; using UnityEngine; @@ -23,3 +24,4 @@ internal string GetSaveFilePath() { } +#endif \ No newline at end of file diff --git a/Src/Unity/SaveState/FileBasedPlayerPrefs/Runtime/FBPPSaveFileModel.cs b/Src/Unity/SaveState/FileBasedPlayerPrefs/Runtime/FBPPSaveFileModel.cs index b344300..41c415e 100644 --- a/Src/Unity/SaveState/FileBasedPlayerPrefs/Runtime/FBPPSaveFileModel.cs +++ b/Src/Unity/SaveState/FileBasedPlayerPrefs/Runtime/FBPPSaveFileModel.cs @@ -1,4 +1,5 @@ -using System; +#if UNITY_2019_4_OR_NEWER +using System; using System.Linq; [Serializable] @@ -304,3 +305,4 @@ public bool Equals(FBPPFileModel other) { return true; } } +#endif \ No newline at end of file diff --git a/Src/Unity/SaveState/WorldStateFBPP.cs b/Src/Unity/SaveState/WorldStateFBPP.cs index 306d2e0..29a7c43 100644 --- a/Src/Unity/SaveState/WorldStateFBPP.cs +++ b/Src/Unity/SaveState/WorldStateFBPP.cs @@ -5,6 +5,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +#if UNITY_2019_4_OR_NEWER using System.IO; @@ -39,3 +40,4 @@ public override void DeleteSave(string saveName) { } } +#endif \ No newline at end of file From 048f8d4b7f013e363d7eff4daa374af3bada28bf Mon Sep 17 00:00:00 2001 From: Sythelux Rikd Date: Wed, 29 May 2024 20:16:22 +0200 Subject: [PATCH 3/6] fixed Godot specific things. Added only halfway working _Get and _Set in editor. Added extra line at the end in some files --- Src/Common/_Common.asmdef | 15 +++++++ Src/Godot/Common/DebugDrawer.cs | 2 +- Src/Godot/Common/ProjectionExtensions.cs | 2 +- Src/Godot/Common/QuaternionExtensions.cs | 2 +- Src/Godot/Common/RunevisionGodotExtensions.cs | 2 +- Src/Godot/Editor/GenerationSourceEditor.cs | 30 ++++++++++++-- Src/Godot/Editor/LayerSpecEditor.cs | 2 +- Src/Godot/LayerProcGen/GenerationSource.cs | 2 +- Src/Godot/LayerProcGen/IGodotInstance.cs | 2 +- .../LayerProcGen/LayerManagerBehavior.cs | 2 +- Src/Godot/LayerProcGen/LayerSpec.cs | 2 +- .../LayerProcGen/VisualizationManager.cs | 2 +- Src/Godot/QueuedGameObjectDestruction.cs | 2 +- Src/Godot/TransformWrapper.cs | 2 +- Src/Interop/GodotSpecific/DPoint3Godot.cs | 29 +++++++++++++ Src/Interop/GodotSpecific/DPointGodot.cs | 41 +++++++++++++++++++ Src/Interop/GodotSpecific/Point3Godot.cs | 28 +++++++++++++ Src/Interop/GodotSpecific/PointGodot.cs | 40 ++++++++++++++++++ Src/Interop/_Interop.asmdef | 22 ++++++++++ Src/LayerProcGen/_LayerProcGen.asmdef | 17 ++++++++ Src/SaveState/_SaveState.asmdef | 16 ++++++++ .../LayerProcGen/GameObjectDestruction.cs | 4 +- 22 files changed, 248 insertions(+), 18 deletions(-) create mode 100644 Src/Common/_Common.asmdef create mode 100644 Src/Interop/GodotSpecific/DPoint3Godot.cs create mode 100644 Src/Interop/GodotSpecific/DPointGodot.cs create mode 100644 Src/Interop/GodotSpecific/Point3Godot.cs create mode 100644 Src/Interop/GodotSpecific/PointGodot.cs create mode 100644 Src/Interop/_Interop.asmdef create mode 100644 Src/LayerProcGen/_LayerProcGen.asmdef create mode 100644 Src/SaveState/_SaveState.asmdef diff --git a/Src/Common/_Common.asmdef b/Src/Common/_Common.asmdef new file mode 100644 index 0000000..23441be --- /dev/null +++ b/Src/Common/_Common.asmdef @@ -0,0 +1,15 @@ +{ + "name": "Runevision.Common", + "references": [ + "GUID:bdf51211cba1541cca26870e4d9c763d" + ], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": true +} \ No newline at end of file diff --git a/Src/Godot/Common/DebugDrawer.cs b/Src/Godot/Common/DebugDrawer.cs index 3950029..2dfd49f 100644 --- a/Src/Godot/Common/DebugDrawer.cs +++ b/Src/Godot/Common/DebugDrawer.cs @@ -370,4 +370,4 @@ public static void DrawCube(Projection matrix, Color color, float duration = 0, } } -#endif \ No newline at end of file +#endif diff --git a/Src/Godot/Common/ProjectionExtensions.cs b/Src/Godot/Common/ProjectionExtensions.cs index 235fbfc..5cdc73a 100644 --- a/Src/Godot/Common/ProjectionExtensions.cs +++ b/Src/Godot/Common/ProjectionExtensions.cs @@ -29,4 +29,4 @@ public static Projection TRS(Vector3 position, Quaternion rotation, Vector3 scal return new Projection(c0, c1, c2, c3); } } -#endif \ No newline at end of file +#endif diff --git a/Src/Godot/Common/QuaternionExtensions.cs b/Src/Godot/Common/QuaternionExtensions.cs index 14627a7..e9bee78 100644 --- a/Src/Godot/Common/QuaternionExtensions.cs +++ b/Src/Godot/Common/QuaternionExtensions.cs @@ -16,4 +16,4 @@ public static Quaternion LookRotation(Vector3 forward, Vector3? up = default) return new Quaternion(matrix); } } -#endif \ No newline at end of file +#endif diff --git a/Src/Godot/Common/RunevisionGodotExtensions.cs b/Src/Godot/Common/RunevisionGodotExtensions.cs index 31c134e..2402808 100644 --- a/Src/Godot/Common/RunevisionGodotExtensions.cs +++ b/Src/Godot/Common/RunevisionGodotExtensions.cs @@ -67,4 +67,4 @@ public static void DestroyIncludingMeshes(this Node go) // Object.Destroy(go); } } -#endif \ No newline at end of file +#endif diff --git a/Src/Godot/Editor/GenerationSourceEditor.cs b/Src/Godot/Editor/GenerationSourceEditor.cs index 95a72f3..abf1289 100644 --- a/Src/Godot/Editor/GenerationSourceEditor.cs +++ b/Src/Godot/Editor/GenerationSourceEditor.cs @@ -11,9 +11,9 @@ namespace Runevision.LayerProcGen; [Tool] public partial class GenerationSource { - static string[] layerTypeStrings; + static string[]? layerTypeStrings; - [Export] + // [Export] //with export enabled the serialisation works, but not the dynamical layer name private string Layer { get => layer.className; @@ -27,13 +27,34 @@ private Vector2 Size set => size = (Point)value; } + + // with _get and _set enabled the "FillLayerHintString()" works, but it looses serialisation after recompiling, so serialisation is broken. + public override Variant _Get(StringName property) => + (property + string.Empty) switch + { + nameof(Layer) => layer.className, + _ => base._Get(property) + }; + + public override bool _Set(StringName property, Variant value) + { + switch (property) + { + case nameof(Layer): + layer.className = value+""; + return true; + default: + return base._Set(property, value); + } + } + public override Array _GetPropertyList() { var properties = new Array { new() { - { "name", "Layer" }, + { "name", nameof(Layer)}, { "type", (int)Variant.Type.StringName }, { "usage", (int)PropertyUsageFlags.Default }, { "hint", (int)PropertyHint.Enum }, @@ -53,10 +74,11 @@ public static string FillLayerHintString() .SelectMany(assembly => assembly.GetTypes()) .Where(t => t != layerBaseType && layerBaseType.IsAssignableFrom(t) && !t.IsGenericType) .Select(t => t.FullName) + .OfType() .ToArray(); } return string.Join(',', layerTypeStrings.Select(s => s[(s.LastIndexOf('.') + 1)..])); } } -#endif \ No newline at end of file +#endif diff --git a/Src/Godot/Editor/LayerSpecEditor.cs b/Src/Godot/Editor/LayerSpecEditor.cs index d0511b1..71d2600 100644 --- a/Src/Godot/Editor/LayerSpecEditor.cs +++ b/Src/Godot/Editor/LayerSpecEditor.cs @@ -8,4 +8,4 @@ public partial class LayerSpec { //TODO: https://docs.godotengine.org/en/stable/tutorials/plugins/editor/inspector_plugins.html } -#endif \ No newline at end of file +#endif diff --git a/Src/Godot/LayerProcGen/GenerationSource.cs b/Src/Godot/LayerProcGen/GenerationSource.cs index d241360..f84e8d2 100644 --- a/Src/Godot/LayerProcGen/GenerationSource.cs +++ b/Src/Godot/LayerProcGen/GenerationSource.cs @@ -74,4 +74,4 @@ public override void _Process(double delta) dep.SetSize(Point.Max(Point.one, size)); } } -#endif \ No newline at end of file +#endif diff --git a/Src/Godot/LayerProcGen/IGodotInstance.cs b/Src/Godot/LayerProcGen/IGodotInstance.cs index 208dc4a..174490b 100644 --- a/Src/Godot/LayerProcGen/IGodotInstance.cs +++ b/Src/Godot/LayerProcGen/IGodotInstance.cs @@ -7,4 +7,4 @@ internal interface IGodotInstance { public Node LayerRoot(); } -#endif \ No newline at end of file +#endif diff --git a/Src/Godot/LayerProcGen/LayerManagerBehavior.cs b/Src/Godot/LayerProcGen/LayerManagerBehavior.cs index 8528d8f..284fbee 100644 --- a/Src/Godot/LayerProcGen/LayerManagerBehavior.cs +++ b/Src/Godot/LayerProcGen/LayerManagerBehavior.cs @@ -65,4 +65,4 @@ public void StartCoroutine(IEnumerator coroutine) } } } -#endif \ No newline at end of file +#endif diff --git a/Src/Godot/LayerProcGen/LayerSpec.cs b/Src/Godot/LayerProcGen/LayerSpec.cs index e06825c..64f64d8 100644 --- a/Src/Godot/LayerProcGen/LayerSpec.cs +++ b/Src/Godot/LayerProcGen/LayerSpec.cs @@ -48,4 +48,4 @@ public override Array _GetPropertyList() return properties; } } -#endif \ No newline at end of file +#endif diff --git a/Src/Godot/LayerProcGen/VisualizationManager.cs b/Src/Godot/LayerProcGen/VisualizationManager.cs index af2238a..bff5b4c 100644 --- a/Src/Godot/LayerProcGen/VisualizationManager.cs +++ b/Src/Godot/LayerProcGen/VisualizationManager.cs @@ -710,4 +710,4 @@ static void DrawSceneViewTextMethod( #endif } } -#endif \ No newline at end of file +#endif diff --git a/Src/Godot/QueuedGameObjectDestruction.cs b/Src/Godot/QueuedGameObjectDestruction.cs index 30387e6..062bc18 100644 --- a/Src/Godot/QueuedGameObjectDestruction.cs +++ b/Src/Godot/QueuedGameObjectDestruction.cs @@ -29,4 +29,4 @@ public static void Enqueue(TransformWrapper tr, bool destroyMeshes) { MainThreadActionQueue.Enqueue(new QueuedGameObjectDestruction { transform = tr, destroyMeshes = destroyMeshes }); } } -#endif \ No newline at end of file +#endif diff --git a/Src/Godot/TransformWrapper.cs b/Src/Godot/TransformWrapper.cs index 34ccaf2..84f7ddf 100644 --- a/Src/Godot/TransformWrapper.cs +++ b/Src/Godot/TransformWrapper.cs @@ -30,4 +30,4 @@ public void AddChild(Node3D child) { // child.gameObject.layer = transform.gameObject.layer; //same as above } } -#endif \ No newline at end of file +#endif diff --git a/Src/Interop/GodotSpecific/DPoint3Godot.cs b/Src/Interop/GodotSpecific/DPoint3Godot.cs new file mode 100644 index 0000000..791a1b9 --- /dev/null +++ b/Src/Interop/GodotSpecific/DPoint3Godot.cs @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2024 Rune Skovbo Johansen, Sythelux Rikd + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#if GODOT4 +using Godot; + +namespace Runevision.Common; + +public partial struct DPoint3 +{ + // User-defined conversion from DPoint3 to Vector3 + public static explicit operator Vector3(DPoint3 p) + { + return new Vector3((float)p.x, (float)p.y, (float)p.z); + } + + // User-defined conversion from Vector3 to DPoint3 + public static implicit operator DPoint3(Vector3 p) + { + return new DPoint3(p.X, p.Y, p.Z); + } +} + +#endif \ No newline at end of file diff --git a/Src/Interop/GodotSpecific/DPointGodot.cs b/Src/Interop/GodotSpecific/DPointGodot.cs new file mode 100644 index 0000000..b0dd743 --- /dev/null +++ b/Src/Interop/GodotSpecific/DPointGodot.cs @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2024 Rune Skovbo Johansen, Sythelux Rikd + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#if GODOT4 +using Godot; + +namespace Runevision.Common; + +public partial struct DPoint +{ + // User-defined conversion from DPoint to Vector3 + public static explicit operator Vector3(DPoint p) + { + return new Vector3((float)p.x, (float)p.y, 0); + } + + // User-defined conversion from Vector3 to DPoint + public static explicit operator DPoint(Vector3 p) + { + return new DPoint(p.X, p.Y); + } + + // User-defined conversion from DPoint to Vector2 + public static explicit operator Vector2(DPoint p) + { + return new Vector2((float)p.x, (float)p.y); + } + + // User-defined conversion from Vector2 to DPoint + public static implicit operator DPoint(Vector2 p) + { + return new DPoint(p.X, p.Y); + } +} + +#endif \ No newline at end of file diff --git a/Src/Interop/GodotSpecific/Point3Godot.cs b/Src/Interop/GodotSpecific/Point3Godot.cs new file mode 100644 index 0000000..0a3ff4b --- /dev/null +++ b/Src/Interop/GodotSpecific/Point3Godot.cs @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2024 Rune Skovbo Johansen, Sythelux Rikd + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#if GODOT4 +using Godot; + +namespace Runevision.Common; + +public partial struct Point3 +{ + // User-defined conversion from Point to Vector3 + public static implicit operator Vector3(Point3 p) + { + return new Vector3(p.x, p.y, p.z); + } + + // User-defined conversion from Vector3 to Point + public static explicit operator Point3(Vector3 p) + { + return new Point3(Mathf.FloorToInt(p.X), Mathf.FloorToInt(p.Y), Mathf.FloorToInt(p.Z)); + } +} +#endif \ No newline at end of file diff --git a/Src/Interop/GodotSpecific/PointGodot.cs b/Src/Interop/GodotSpecific/PointGodot.cs new file mode 100644 index 0000000..b917699 --- /dev/null +++ b/Src/Interop/GodotSpecific/PointGodot.cs @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2024 Rune Skovbo Johansen, Sythelux Rikd + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#if GODOT4 +using Godot; + +namespace Runevision.Common; + +public partial struct Point { + + // User-defined conversion from Point to Vector3 + public static explicit operator Vector3(Point p) { + return new Vector3(p.x, p.y, 0); + } + + // User-defined conversion from Vector3 to Point + public static explicit operator Point(Vector3 p) { + return new Point(Mathf.FloorToInt(p.X), Mathf.FloorToInt(p.Y)); + } + + // User-defined conversion from Point to Vector2 + public static implicit operator Vector2(Point p) { + return new Vector2(p.x, p.y); + } + + // User-defined conversion from Vector2 to Point + public static explicit operator Point(Vector2 p) { + return new Point(Mathf.FloorToInt(p.X), Mathf.FloorToInt(p.Y)); + } + + public static Point GetRoundedPoint(Vector2 p) { + return new Point(Mathf.RoundToInt(p.X), Mathf.RoundToInt(p.Y)); + } +} +#endif diff --git a/Src/Interop/_Interop.asmdef b/Src/Interop/_Interop.asmdef new file mode 100644 index 0000000..a70cc7e --- /dev/null +++ b/Src/Interop/_Interop.asmdef @@ -0,0 +1,22 @@ +{ + "name": "Runevision.Interop", + "rootNamespace": "", + "references": [ + "GUID:d8b63aba1907145bea998dd612889d6b" + ], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [ + { + "name": "com.unity.mathematics", + "expression": "", + "define": "PACKAGE_UNITY_MATHEMATICS" + } + ], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Src/LayerProcGen/_LayerProcGen.asmdef b/Src/LayerProcGen/_LayerProcGen.asmdef new file mode 100644 index 0000000..02de35b --- /dev/null +++ b/Src/LayerProcGen/_LayerProcGen.asmdef @@ -0,0 +1,17 @@ +{ + "name": "Runevision.LayerProcGen", + "references": [ + "GUID:af01629e909984b56b6ddac3cc8fe766", + "GUID:bdf51211cba1541cca26870e4d9c763d", + "GUID:97462eeaf6ea341848ff6b8b6119c1f0" + ], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": true +} \ No newline at end of file diff --git a/Src/SaveState/_SaveState.asmdef b/Src/SaveState/_SaveState.asmdef new file mode 100644 index 0000000..4ee3193 --- /dev/null +++ b/Src/SaveState/_SaveState.asmdef @@ -0,0 +1,16 @@ +{ + "name": "Runevision.WorldState", + "references": [ + "GUID:af01629e909984b56b6ddac3cc8fe766", + "GUID:bdf51211cba1541cca26870e4d9c763d" + ], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": true +} \ No newline at end of file diff --git a/Src/Unity/LayerProcGen/GameObjectDestruction.cs b/Src/Unity/LayerProcGen/GameObjectDestruction.cs index 1cada19..9f62587 100644 --- a/Src/Unity/LayerProcGen/GameObjectDestruction.cs +++ b/Src/Unity/LayerProcGen/GameObjectDestruction.cs @@ -5,7 +5,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ - +#if UNITY_2019_4_OR_NEWER using Runevision.Common; namespace Runevision.LayerProcGen { @@ -39,5 +39,5 @@ public static void Enqueue(TransformWrapper tr, bool destroyMeshes) { MainThreadActionQueue.Enqueue(new QueuedGameObjectDestruction { transform = tr, destroyMeshes = destroyMeshes }); } } - } +#endif From d009ce7d0eed85b9c0786d0fa62a4e2453172dec Mon Sep 17 00:00:00 2001 From: Sythelux Rikd Date: Wed, 29 May 2024 20:39:12 +0200 Subject: [PATCH 4/6] fixed the sibling dir text in godot_project_release.py --- godot_project_release.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/godot_project_release.py b/godot_project_release.py index bd88679..7a7561e 100755 --- a/godot_project_release.py +++ b/godot_project_release.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 -# Sets up godot_addon folder with a Unity importable version of the source. -# Requires: sibling dir "godot_addon" set up as a git clone, checked out to branch "godot_addon". +# Sets up godot_project folder with a Unity importable version of the source. +# Requires: sibling dir "godot_project" set up as a git clone, checked out to branch "godot_project". import os import shutil From e25d6cbb4d33a5e29c37b7fc5286098cb39c4f82 Mon Sep 17 00:00:00 2001 From: Sythelux Rikd Date: Sun, 2 Jun 2024 23:30:54 +0200 Subject: [PATCH 5/6] new: added Debugging Tree on the side. --- Src/Godot/Common/CallbackHub.cs | 70 +++++++++++ Src/Godot/Editor/DebugOptionsWindow.cs | 115 ++++++++++++++++++ Src/Godot/Editor/DebugWindowPlugin.cs | 13 ++ .../LayerProcGen/LayerManagerBehavior.cs | 10 +- Src/Godot/TransformWrapper.cs | 16 ++- 5 files changed, 218 insertions(+), 6 deletions(-) create mode 100644 Src/Godot/Common/CallbackHub.cs create mode 100644 Src/Godot/Editor/DebugOptionsWindow.cs create mode 100644 Src/Godot/Editor/DebugWindowPlugin.cs diff --git a/Src/Godot/Common/CallbackHub.cs b/Src/Godot/Common/CallbackHub.cs new file mode 100644 index 0000000..4f11e8c --- /dev/null +++ b/Src/Godot/Common/CallbackHub.cs @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2024 Rune Skovbo Johansen, Sythelux Rikd + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ +#if GODOT4 +using System; +using Godot; +using Runevision.Common; + +[Tool] +public partial class CallbackHub : Node +{ + + public static event Action? update; + public static event Action? lateUpdate; + public static event Action? fixedUpdate; + + static CallbackHub? instance; + + static int mainThreadID; + public static bool isMainThread + { + get => System.Environment.CurrentManagedThreadId == mainThreadID; + } + + public override void _Ready() + { + mainThreadID = System.Environment.CurrentManagedThreadId; + instance ??= this; + + //Hooks have to be setup here, there is no hook for "OnSceneLoad" etc. + update += delta => DebugOption.UpdateAnimValues((float)delta); + } + + public override void _Process(double delta) + { + update?.Invoke(delta); + lateUpdate?.Invoke(delta); //no lateupdate in Godot natively, but we can do it after all the updates + } + + public override void _PhysicsProcess(double delta) + { + fixedUpdate?.Invoke(delta); + } + + public static void ExecuteOnMainThread(Action? action) + { + if (action == null) + return; + if (isMainThread) + { + // If already on main thread, call action right away. + action(); + return; + } + + // Otherwise add a callback that calls action and then removes itself. + Action? handler = null; + handler = _ => + { + action(); + update -= handler; + }; + update += handler; + } +} +#endif diff --git a/Src/Godot/Editor/DebugOptionsWindow.cs b/Src/Godot/Editor/DebugOptionsWindow.cs new file mode 100644 index 0000000..07ef808 --- /dev/null +++ b/Src/Godot/Editor/DebugOptionsWindow.cs @@ -0,0 +1,115 @@ +using Godot; +using Runevision.Common; +using System.Collections.Generic; + +namespace Runevision.LayerProcGen; + +public partial class DebugOptionsWindow : ScrollContainer +{ + [Export] + public Texture2D ButtonTexture { get; set; } + [Export] + public Texture2D ToggleOn { get; set; } + [Export] + public Texture2D ToggleOff { get; set; } + protected Dictionary matchingOptions = new Dictionary(); + + protected Tree wrapper; + protected Vector2 calculatedMinSize = new Vector2(); + + public override void _Ready() + { + if (GetChildCount() == 0) + { + wrapper = new Tree(); + AddChild(wrapper); + } + else + wrapper = GetChild(0); + + DebugOption.UIChanged += RefreshUI; + + wrapper.SizeFlagsHorizontal = SizeFlags.ExpandFill; + wrapper.SizeFlagsVertical = SizeFlags.ExpandFill; + + var root = wrapper.CreateItem(); + wrapper.HideRoot = true; + wrapper.SelectMode = Tree.SelectModeEnum.Multi; + + foreach (DebugOption option in DebugOption.root.children) + CreateOption(root, option, 0); + + CustomMinimumSize = calculatedMinSize with { X = calculatedMinSize.X * 1.3f }; //add some buffer... I know this should be calculated based on level and scrollbar etc. + } + + public void RefreshUI() + { + foreach ((DebugOption? debugOption, TreeItem? treeItem) in matchingOptions) + { + if (treeItem.GetButtonCount(0) > 0 && debugOption is DebugToggle debugToggle) + { + treeItem.SetButton(0, 0, debugToggle.enabledSelf ? ToggleOn : ToggleOff); + treeItem.Collapsed = !debugToggle.enabledSelf; + } + } + } + + private void CreateOption(TreeItem parentControl, DebugOption option, int level) + { + TreeItem? control = parentControl.CreateChild(0); + matchingOptions.Add(option, control); + control.SetSelectable(0, false); + if (level <= 10) + switch (option) + { + case DebugButton: + { + control.AddButton(0, ButtonTexture); + wrapper.ButtonClicked += WrapperOnButtonClicked; + + void WrapperOnButtonClicked(TreeItem item, long column, long id, long mousebuttonindex) + { + if (item == control) + option.HandleClick(); + } + + break; + } + case DebugToggle toggle: + { + control.AddButton(0, toggle.enabledSelf ? ToggleOn : ToggleOff); + wrapper.ButtonClicked += WrapperOnButtonClicked; + + void WrapperOnButtonClicked(TreeItem item, long column, long id, long mousebuttonindex) + { + if (item == control) + { + toggle.HandleClick(); + item.SetButton((int)column, (int)id, toggle.enabledSelf ? ToggleOn : ToggleOff); + } + } + + break; + } + } + + Vector2 minSize = GetThemeDefaultFont().GetStringSize(option.name) * ((level + 1) * .7f); //magic number, should be changed to the inset of the foldout + // aka: Vector2 minSize = GetThemeDefaultFont().GetStringSize(option.name) + ((level + 1) * foldoutWidth); + if (minSize > calculatedMinSize) + calculatedMinSize = minSize; + control.SetText(0, option.name /*+ $" ({option.GetType().Name})"*/); + control.Visible = !option.hidden; + + if (option is DebugFoldout parent) + { + control.Collapsed = !parent.enabledSelf; + foreach (DebugOption child in parent.children) + CreateOption(control, child, level + 1); + } + } + + public override void _ExitTree() + { + DebugOption.UIChanged -= RefreshUI; + } +} diff --git a/Src/Godot/Editor/DebugWindowPlugin.cs b/Src/Godot/Editor/DebugWindowPlugin.cs new file mode 100644 index 0000000..a35569c --- /dev/null +++ b/Src/Godot/Editor/DebugWindowPlugin.cs @@ -0,0 +1,13 @@ +// using Godot; +// +// namespace Runevision.LayerProcGen; +// +// [Tool] +// public partial class DebugWindowPlugin: EditorInspectorPlugin +// { +// public override bool _CanHandle(GodotObject @object) +// { +// GD.Print(nameof(DebugWindowPlugin)); +// return base._CanHandle(@object); +// } +// } \ No newline at end of file diff --git a/Src/Godot/LayerProcGen/LayerManagerBehavior.cs b/Src/Godot/LayerProcGen/LayerManagerBehavior.cs index 284fbee..0d157cc 100644 --- a/Src/Godot/LayerProcGen/LayerManagerBehavior.cs +++ b/Src/Godot/LayerProcGen/LayerManagerBehavior.cs @@ -10,6 +10,7 @@ using Runevision.Common; using System; using System.Collections; +using System.Collections.Concurrent; using Godot; namespace Runevision.LayerProcGen { @@ -19,6 +20,9 @@ namespace Runevision.LayerProcGen { /// public partial class LayerManagerBehavior : Node { + protected readonly ConcurrentQueue Coroutines = new(); + protected IEnumerator? activeCoroutine; + public enum GenerationPlane { XY, XZ } public static LayerManagerBehavior instance { get; private set; } @@ -49,6 +53,9 @@ public override void _ExitTree() public override void _Process(double delta) { + if (activeCoroutine == null || !activeCoroutine.MoveNext()) + if (!Coroutines.TryDequeue(out activeCoroutine)) + activeCoroutine = null; MainThreadActionQueue.ProcessQueue(); DebugDrawer.xzMode = (generationPlane == GenerationPlane.XZ); OnUpdate?.Invoke(); @@ -60,8 +67,9 @@ public override void _Process(double delta) debugStatusText.Text = SimpleProfiler.GetStatus(); } - public void StartCoroutine(IEnumerator coroutine) + public void StartCoroutine(IEnumerator? coroutine) { + Coroutines.Enqueue(coroutine); } } } diff --git a/Src/Godot/TransformWrapper.cs b/Src/Godot/TransformWrapper.cs index 84f7ddf..fed0f97 100644 --- a/Src/Godot/TransformWrapper.cs +++ b/Src/Godot/TransformWrapper.cs @@ -12,7 +12,8 @@ public class TransformWrapper Node3D layerParent; Point chunkIndex; - public TransformWrapper(Node3D layerParent, Point chunkIndex) { + public TransformWrapper(Node3D layerParent, Point chunkIndex) + { this.layerParent = layerParent; this.chunkIndex = chunkIndex; } @@ -20,13 +21,18 @@ public TransformWrapper(Node3D layerParent, Point chunkIndex) { /// /// Creates the wrapper's own Transform if it doesn't exist, then adds the child. /// - public void AddChild(Node3D child) { - if (transform == null) { - transform = new Node3D{Name="Chunk" + chunkIndex}; + public void AddChild(Node3D child) + { + if (transform == null) + { + transform = new Node3D { Name = "Chunk" + chunkIndex }; layerParent.AddChild(transform); // transform.gameObject.layer = layerParent.gameObject.layer; -> only for collision objects in Godot, so we probably have to either change the type or make a child. } - transform.AddChild(child); + if (child.GetParent() == null) + transform.AddChild(child); + else + child.Reparent(transform); // child.gameObject.layer = transform.gameObject.layer; //same as above } } From 867f92c58b0e8233ba5721eb0c4f395fbf348412 Mon Sep 17 00:00:00 2001 From: Sythelux Rikd Date: Sun, 9 Jun 2024 00:16:17 +0200 Subject: [PATCH 6/6] new: Groundwork for Height generation finished new: height maps are now being rendered chg: all files should have a new line at the end chg: license header was wrong --- Src/Godot/Common/CallbackHub.cs | 5 ++++- Src/Godot/LayerProcGen/GenerationSource.cs | 17 +++++++++++++---- Src/Godot/LayerProcGen/IGodotInstance.cs | 2 +- Src/Godot/LayerProcGen/VisualizationManager.cs | 5 ++++- 4 files changed, 22 insertions(+), 7 deletions(-) diff --git a/Src/Godot/Common/CallbackHub.cs b/Src/Godot/Common/CallbackHub.cs index 4f11e8c..6003b9d 100644 --- a/Src/Godot/Common/CallbackHub.cs +++ b/Src/Godot/Common/CallbackHub.cs @@ -1,5 +1,8 @@ /* - * Copyright (c) 2024 Rune Skovbo Johansen, Sythelux Rikd + * Godot adaptation copyright (c) 2024 Sythelux Rikd + * + * Based on: + * LayerProcGen copyright (c) 2024 Rune Skovbo Johansen * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this diff --git a/Src/Godot/LayerProcGen/GenerationSource.cs b/Src/Godot/LayerProcGen/GenerationSource.cs index f84e8d2..c23d79b 100644 --- a/Src/Godot/LayerProcGen/GenerationSource.cs +++ b/Src/Godot/LayerProcGen/GenerationSource.cs @@ -1,5 +1,8 @@ /* - * Copyright (c) 2024 Rune Skovbo Johansen, Sythelux Rikd + * Godot adaptation copyright (c) 2024 Sythelux Rikd + * + * Based on: + * LayerProcGen copyright (c) 2024 Rune Skovbo Johansen * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this @@ -9,12 +12,13 @@ using Runevision.Common; using Godot; +using System.Linq; namespace Runevision.LayerProcGen; /// -/// Unity component that creates a . +/// Godot component that creates a . /// public partial class GenerationSource : Node3D @@ -51,8 +55,6 @@ void UpdateState() if (dep != null) dep.isActive = false; dep = new TopLayerDependency(instance, size); - if (instance is IGodotInstance gInst) - CallDeferred("add_child", gInst.LayerRoot()); } } @@ -64,6 +66,13 @@ public override void _Process(double delta) if (dep == null) return; + foreach (IGodotInstance layer in AbstractDataLayer.layers.OfType()) + { + Node? layerRoot = layer.LayerRoot(); + if(layerRoot != null && layerRoot.GetParent() == null) + CallDeferred("add_child", layerRoot); //TODO: would be cool to do this after build end + } + Vector3 focusPos = Position; Point focus; if (LayerManagerBehavior.instance?.generationPlane == LayerManagerBehavior.GenerationPlane.XZ) diff --git a/Src/Godot/LayerProcGen/IGodotInstance.cs b/Src/Godot/LayerProcGen/IGodotInstance.cs index 174490b..1e057f6 100644 --- a/Src/Godot/LayerProcGen/IGodotInstance.cs +++ b/Src/Godot/LayerProcGen/IGodotInstance.cs @@ -5,6 +5,6 @@ namespace Runevision.LayerProcGen; internal interface IGodotInstance { - public Node LayerRoot(); + public Node? LayerRoot(); } #endif diff --git a/Src/Godot/LayerProcGen/VisualizationManager.cs b/Src/Godot/LayerProcGen/VisualizationManager.cs index bff5b4c..79c8a67 100644 --- a/Src/Godot/LayerProcGen/VisualizationManager.cs +++ b/Src/Godot/LayerProcGen/VisualizationManager.cs @@ -1,5 +1,8 @@ /* - * Copyright (c) 2024 Rune Skovbo Johansen, Sythelux Rikd + * Godot adaptation copyright (c) 2024 Sythelux Rikd + * + * Based on: + * LayerProcGen copyright (c) 2024 Rune Skovbo Johansen * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this