From 81ba5b2b407f6e8aa5254ea769a274e0a0b69652 Mon Sep 17 00:00:00 2001 From: Josef Date: Fri, 18 Jul 2025 09:52:32 +0200 Subject: [PATCH] Scene Serializer --- Runtime/Godot/Scenes/SceneFileReader.cs | 2 +- Runtime/Scenes/Serializer/MemberData.cs | 13 ++++ Runtime/Scenes/Serializer/MemberData.cs.uid | 1 + Runtime/Scenes/Serializer/SerializeScene.cs | 29 ++++++++ .../Scenes/Serializer/SerializeScene.cs.uid | 1 + Runtime/Scenes/Serializer/SerializedBase.cs | 70 +++++++++++++++++++ .../Scenes/Serializer/SerializedBase.cs.uid | 1 + Runtime/Scenes/Serializer/SerializedNode.cs | 23 ++++++ .../Scenes/Serializer/SerializedResource.cs | 12 ++++ .../Serializer/SerializedResource.cs.uid | 1 + Runtime/Scenes/Serializer/SerializedScene.cs | 50 +++++++++++++ Runtime/Text/JSON/JSONData.cs | 9 +++ Runtime/Text/JSON/JSONValue.cs | 8 +++ .../Text/JSON/Serializers/JSONDeserializer.cs | 13 ++++ .../Text/JSON/Serializers/JSONSerializer.cs | 42 ++++++++++- .../Serializers/JSONSerializiationSettings.cs | 1 + 16 files changed, 273 insertions(+), 3 deletions(-) create mode 100644 Runtime/Scenes/Serializer/MemberData.cs create mode 100644 Runtime/Scenes/Serializer/MemberData.cs.uid create mode 100644 Runtime/Scenes/Serializer/SerializeScene.cs create mode 100644 Runtime/Scenes/Serializer/SerializeScene.cs.uid create mode 100644 Runtime/Scenes/Serializer/SerializedBase.cs create mode 100644 Runtime/Scenes/Serializer/SerializedBase.cs.uid create mode 100644 Runtime/Scenes/Serializer/SerializedNode.cs create mode 100644 Runtime/Scenes/Serializer/SerializedResource.cs create mode 100644 Runtime/Scenes/Serializer/SerializedResource.cs.uid create mode 100644 Runtime/Scenes/Serializer/SerializedScene.cs diff --git a/Runtime/Godot/Scenes/SceneFileReader.cs b/Runtime/Godot/Scenes/SceneFileReader.cs index 36bd16b..0bc2e9c 100644 --- a/Runtime/Godot/Scenes/SceneFileReader.cs +++ b/Runtime/Godot/Scenes/SceneFileReader.cs @@ -29,7 +29,7 @@ namespace Rokojori void LoadScene() { - var text = FilesSync.LoadUTF8( path ); + var text = FilesSync.LoadUTF8( ProjectSettings.GlobalizePath( path ) ); var parser = new SceneFileParser(); diff --git a/Runtime/Scenes/Serializer/MemberData.cs b/Runtime/Scenes/Serializer/MemberData.cs new file mode 100644 index 0000000..10dc35f --- /dev/null +++ b/Runtime/Scenes/Serializer/MemberData.cs @@ -0,0 +1,13 @@ +using System.Collections.Generic; + +namespace Rokojori +{ + +public class MemberData +{ + public string m; + public string v; + +} + +} \ No newline at end of file diff --git a/Runtime/Scenes/Serializer/MemberData.cs.uid b/Runtime/Scenes/Serializer/MemberData.cs.uid new file mode 100644 index 0000000..2f92d80 --- /dev/null +++ b/Runtime/Scenes/Serializer/MemberData.cs.uid @@ -0,0 +1 @@ +uid://cdj4hgq3jayai diff --git a/Runtime/Scenes/Serializer/SerializeScene.cs b/Runtime/Scenes/Serializer/SerializeScene.cs new file mode 100644 index 0000000..06665b4 --- /dev/null +++ b/Runtime/Scenes/Serializer/SerializeScene.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using Godot; + +namespace Rokojori +{ + [Tool] + [GlobalClass] + public partial class SerializeScene:Action + { + [Export] + public Node root; + + [Export] + public string outputPath; + + protected override void _OnTrigger( ) + { + var serializedScene = new SerializedScene(); + + serializedScene.Serialize( root, [ this ] ); + + FilesSync.SaveJSON( outputPath, serializedScene ); + + } + + } +} diff --git a/Runtime/Scenes/Serializer/SerializeScene.cs.uid b/Runtime/Scenes/Serializer/SerializeScene.cs.uid new file mode 100644 index 0000000..198bcf9 --- /dev/null +++ b/Runtime/Scenes/Serializer/SerializeScene.cs.uid @@ -0,0 +1 @@ +uid://b2162d2y25ljf diff --git a/Runtime/Scenes/Serializer/SerializedBase.cs b/Runtime/Scenes/Serializer/SerializedBase.cs new file mode 100644 index 0000000..aced359 --- /dev/null +++ b/Runtime/Scenes/Serializer/SerializedBase.cs @@ -0,0 +1,70 @@ +using System.Collections.Generic; +using Godot; +using Godot.Collections; + +namespace Rokojori +{ + + public class SerializedBase + { + // TYPE + public string t; + public List m = []; + + + public static bool isInteral( int usage ) + { + return ( usage & (int) PropertyUsageFlags.ScriptVariable ) == 0 && + ( usage & (int) PropertyUsageFlags.Storage ) == 0 ; + } + + + public void Serialize( GodotObject obj ) + { + + var script = (Script)obj.GetScript(); + + if ( script != null ) + { + RJLog.Log( script ); + this.t = ResourceLoader.GetResourceUid( script.ResourcePath ) + ""; + } + else + { + this.t = obj.GetClass(); + } + + + + Array propertyList = obj.GetPropertyList(); + + foreach ( Dictionary prop in propertyList ) + { + if ( ! ( prop.ContainsKey( "name" ) && prop.ContainsKey( "usage" ) ) ) + { + continue; + } + + var name = prop[ "name" ].AsString(); + + var usage = (int) prop[ "usage" ]; + + if ( isInteral( usage ) ) + { + continue; + } + + var value = obj.Get( name ); + + var member = new MemberData(); + member.m = name + " " + value.VariantType.ToString(); + member.v = value.ToString(); + + m.Add( member ); + } + + + } + } + +} \ No newline at end of file diff --git a/Runtime/Scenes/Serializer/SerializedBase.cs.uid b/Runtime/Scenes/Serializer/SerializedBase.cs.uid new file mode 100644 index 0000000..6b72ef1 --- /dev/null +++ b/Runtime/Scenes/Serializer/SerializedBase.cs.uid @@ -0,0 +1 @@ +uid://bwv6cb1kkyhbo diff --git a/Runtime/Scenes/Serializer/SerializedNode.cs b/Runtime/Scenes/Serializer/SerializedNode.cs new file mode 100644 index 0000000..604f706 --- /dev/null +++ b/Runtime/Scenes/Serializer/SerializedNode.cs @@ -0,0 +1,23 @@ +using System.Collections.Generic; +using Godot; + +namespace Rokojori +{ + + public class SerializedNode:SerializedBase + { + public int p; + public string n; + + public void Serialize( int serializationID, int parentID, Node node ) + { + this.n = node.Name; + this.p = parentID; + + Serialize( node ); + + } + } + + +} \ No newline at end of file diff --git a/Runtime/Scenes/Serializer/SerializedResource.cs b/Runtime/Scenes/Serializer/SerializedResource.cs new file mode 100644 index 0000000..cc1334e --- /dev/null +++ b/Runtime/Scenes/Serializer/SerializedResource.cs @@ -0,0 +1,12 @@ +using System.Collections.Generic; + +namespace Rokojori +{ + + public class SerializedResource:SerializedBase + { + + } + + +} \ No newline at end of file diff --git a/Runtime/Scenes/Serializer/SerializedResource.cs.uid b/Runtime/Scenes/Serializer/SerializedResource.cs.uid new file mode 100644 index 0000000..1138353 --- /dev/null +++ b/Runtime/Scenes/Serializer/SerializedResource.cs.uid @@ -0,0 +1 @@ +uid://c8wf6mwe8ehm diff --git a/Runtime/Scenes/Serializer/SerializedScene.cs b/Runtime/Scenes/Serializer/SerializedScene.cs new file mode 100644 index 0000000..d8069b3 --- /dev/null +++ b/Runtime/Scenes/Serializer/SerializedScene.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using Godot; + +namespace Rokojori +{ + + public class SerializedScene + { + public List resources = new List(); + public List nodes = new List(); + + public void Serialize( Node rootNode, params Node[] skip ) + { + int serializationID = 0; + + var _nodeToIDMap = new Dictionary(); + + Nodes.Iterate( [ rootNode ], + ( n )=> + { + if ( n == null || skip.Contains( n ) ) + { + return; + } + + var id = serializationID; + serializationID ++; + + var serializedNode = new SerializedNode(); + + _nodeToIDMap[ n ] = id; + + nodes.Add( serializedNode ); + + var parentID = _nodeToIDMap.ContainsKey( n.GetParent() ) ? _nodeToIDMap[ n.GetParent() ] : -1; + + serializedNode.Serialize( id, parentID, n ); + + } + ); + + RJLog.Log( "Num Nodes:", nodes.Count ); + } + + } + +} \ No newline at end of file diff --git a/Runtime/Text/JSON/JSONData.cs b/Runtime/Text/JSON/JSONData.cs index 0ed9448..f9bf513 100644 --- a/Runtime/Text/JSON/JSONData.cs +++ b/Runtime/Text/JSON/JSONData.cs @@ -186,6 +186,15 @@ namespace Rokojori } } + public long longValue + { + get + { + var value = (JSONValue) this; + return value.GetLongValue(); + } + } + public bool booleanValue { get diff --git a/Runtime/Text/JSON/JSONValue.cs b/Runtime/Text/JSON/JSONValue.cs index 96dc05e..7143273 100644 --- a/Runtime/Text/JSON/JSONValue.cs +++ b/Runtime/Text/JSON/JSONValue.cs @@ -22,6 +22,7 @@ namespace Rokojori public JSONValue(){ SetNull(); } public JSONValue( string value ){ Set( value ); } public JSONValue( double value ){ Set( value ); } + public JSONValue( long value ){ Set( value ); } public JSONValue( bool value ){ Set( value ); } @@ -31,6 +32,12 @@ namespace Rokojori _dataType = JSONDataType.NUMBER; } + private void Set( long number ) + { + _numberValue = number; + _dataType = JSONDataType.NUMBER; + } + private void Set( string value ) { _stringValue = value; @@ -51,6 +58,7 @@ namespace Rokojori public double GetNumberValue(){ return _numberValue; } public float GetFloatValue() { return (float) _numberValue; } public int GetIntValue(){ return (int) System.Math.Round( _numberValue ); } + public long GetLongValue(){ return (int) System.Math.Round( _numberValue ); } public bool GetBooleanValue(){ return _booleanValue; } public string GetStringValue(){ return _stringValue; } public T GetEnumFromString( T enumValue ) where T : System.Enum diff --git a/Runtime/Text/JSON/Serializers/JSONDeserializer.cs b/Runtime/Text/JSON/Serializers/JSONDeserializer.cs index 5f807d0..2047b5c 100644 --- a/Runtime/Text/JSON/Serializers/JSONDeserializer.cs +++ b/Runtime/Text/JSON/Serializers/JSONDeserializer.cs @@ -138,6 +138,10 @@ namespace Rokojori { SetNumber( data, reference, INT ); } + if ( typeof( long ) == type ) + { + SetNumber( data, reference, LONG ); + } else if ( typeof( float ) == type ) { SetNumber( data, reference, FLOAT ); @@ -283,6 +287,7 @@ namespace Rokojori const int INT = 0; const int FLOAT = 1; const int DOUBLE = 2; + const int LONG = 3; void SetNumber( JSONData data, Reference reference, int numberType ) { @@ -299,6 +304,7 @@ namespace Rokojori case INT:{ reference.AssignValue( data.intValue ); return; } case FLOAT:{ reference.AssignValue( data.floatValue ); return; } case DOUBLE:{ reference.AssignValue( data.numberValue ); return; } + case LONG:{ reference.AssignValue( data.longValue ); return; } } RJLog.Log( "Unknown number type: " + reference.GetInfo() + ">>" + data ); @@ -343,6 +349,13 @@ namespace Rokojori reference.AssignValue( value ); } break; + + case LONG: + { + var value = objectValue.Get( JSONSerializationSettings.NUMBER_VALUE ).longValue; + reference.AssignValue( value ); + } + break; } diff --git a/Runtime/Text/JSON/Serializers/JSONSerializer.cs b/Runtime/Text/JSON/Serializers/JSONSerializer.cs index c8497f7..664f064 100644 --- a/Runtime/Text/JSON/Serializers/JSONSerializer.cs +++ b/Runtime/Text/JSON/Serializers/JSONSerializer.cs @@ -41,6 +41,10 @@ namespace Rokojori { return JSON.Stringify( CreateNumber( (int) value ) ); } + else if ( value is long ) + { + return JSON.Stringify( CreateNumber( (long) value ) ); + } else if ( value is double ) { return JSON.Stringify( CreateNumber( (double) value ) ); @@ -147,6 +151,20 @@ namespace Rokojori return new JSONValue( value ); } + JSONData CreateNumber( long value ) + { + if ( settings.saveNumbersWithType ) + { + var jsonObject = new JSONObject(); + jsonObject.Set( JSONSerializationSettings.NUMBER_TYPE, JSONSerializationSettings.LONG_NUMBER_TYPE ); + jsonObject.Set( JSONSerializationSettings.NUMBER_VALUE, value ); + + return jsonObject; + } + + return new JSONValue( value ); + } + JSONData CreateNumber( float value ) { if ( settings.saveNumbersWithType ) @@ -177,7 +195,15 @@ namespace Rokojori bool IsProcessableObject( object value ) { - if (System.Attribute.IsDefined( value.GetType(), typeof(JSONAlwaysProcessable) ) ) + if ( + value is int intValue || + value is long longValue + ) + { + return true; + } + + if ( System.Attribute.IsDefined( value.GetType(), typeof(JSONAlwaysProcessable) ) ) { return true; } @@ -189,7 +215,7 @@ namespace Rokojori if ( processedObjects.Contains( value ) ) { - RJLog.Error( "Cycle detected: " + value ); + RJLog.Error( "Cycle detected: " + value, value.GetType() ); var interfaces = typeof( object ).GetInterfaces(); for ( int i = 0; i < interfaces.Length; i++ ) @@ -277,6 +303,10 @@ namespace Rokojori { jsonObject.Set( name, CreateNumber( (int) value ) ); } + else if ( value is long ) + { + jsonObject.Set( name, CreateNumber( (long) value ) ); + } else if ( value is double ) { jsonObject.Set( name, CreateNumber( (double) value ) ); @@ -344,6 +374,10 @@ namespace Rokojori { jsonArray.Set( index, CreateNumber( (int) value ) ); } + else if ( value is long ) + { + jsonArray.Set( index, CreateNumber( (long) value ) ); + } else if ( value is double ) { jsonArray.Set( index, CreateNumber( (double) value ) ); @@ -394,6 +428,10 @@ namespace Rokojori { jsonObject.Set( name, CreateNumber( (int) value ) ); } + else if ( value is long ) + { + jsonObject.Set( name, CreateNumber( (long) value ) ); + } else if ( value is double ) { jsonObject.Set( name, CreateNumber( (double) value ) ); diff --git a/Runtime/Text/JSON/Serializers/JSONSerializiationSettings.cs b/Runtime/Text/JSON/Serializers/JSONSerializiationSettings.cs index 3eaa500..4cf67c1 100644 --- a/Runtime/Text/JSON/Serializers/JSONSerializiationSettings.cs +++ b/Runtime/Text/JSON/Serializers/JSONSerializiationSettings.cs @@ -17,6 +17,7 @@ namespace Rokojori public static readonly string INT_NUMBER_TYPE = "int"; public static readonly string FLOAT_NUMBER_TYPE = "float"; public static readonly string DOUBLE_NUMBER_TYPE = "double"; + public static readonly string LONG_NUMBER_TYPE = "long"; static List serializableDictionaryKeyTypes = new List() {