Scene Serializer

This commit is contained in:
Josef 2025-07-18 09:52:32 +02:00
parent 94c90e03e7
commit 81ba5b2b40
16 changed files with 273 additions and 3 deletions

View File

@ -29,7 +29,7 @@ namespace Rokojori
void LoadScene() void LoadScene()
{ {
var text = FilesSync.LoadUTF8( path ); var text = FilesSync.LoadUTF8( ProjectSettings.GlobalizePath( path ) );
var parser = new SceneFileParser(); var parser = new SceneFileParser();

View File

@ -0,0 +1,13 @@
using System.Collections.Generic;
namespace Rokojori
{
public class MemberData
{
public string m;
public string v;
}
}

View File

@ -0,0 +1 @@
uid://cdj4hgq3jayai

View File

@ -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 );
}
}
}

View File

@ -0,0 +1 @@
uid://b2162d2y25ljf

View File

@ -0,0 +1,70 @@
using System.Collections.Generic;
using Godot;
using Godot.Collections;
namespace Rokojori
{
public class SerializedBase
{
// TYPE
public string t;
public List<MemberData> 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<Dictionary> 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 );
}
}
}
}

View File

@ -0,0 +1 @@
uid://bwv6cb1kkyhbo

View File

@ -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 );
}
}
}

View File

@ -0,0 +1,12 @@
using System.Collections.Generic;
namespace Rokojori
{
public class SerializedResource:SerializedBase
{
}
}

View File

@ -0,0 +1 @@
uid://c8wf6mwe8ehm

View File

@ -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<SerializedResource> resources = new List<SerializedResource>();
public List<SerializedNode> nodes = new List<SerializedNode>();
public void Serialize( Node rootNode, params Node[] skip )
{
int serializationID = 0;
var _nodeToIDMap = new Dictionary<Node, int>();
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 );
}
}
}

View File

@ -186,6 +186,15 @@ namespace Rokojori
} }
} }
public long longValue
{
get
{
var value = (JSONValue) this;
return value.GetLongValue();
}
}
public bool booleanValue public bool booleanValue
{ {
get get

View File

@ -22,6 +22,7 @@ namespace Rokojori
public JSONValue(){ SetNull(); } public JSONValue(){ SetNull(); }
public JSONValue( string value ){ Set( value ); } public JSONValue( string value ){ Set( value ); }
public JSONValue( double value ){ Set( value ); } public JSONValue( double value ){ Set( value ); }
public JSONValue( long value ){ Set( value ); }
public JSONValue( bool value ){ Set( value ); } public JSONValue( bool value ){ Set( value ); }
@ -31,6 +32,12 @@ namespace Rokojori
_dataType = JSONDataType.NUMBER; _dataType = JSONDataType.NUMBER;
} }
private void Set( long number )
{
_numberValue = number;
_dataType = JSONDataType.NUMBER;
}
private void Set( string value ) private void Set( string value )
{ {
_stringValue = value; _stringValue = value;
@ -51,6 +58,7 @@ namespace Rokojori
public double GetNumberValue(){ return _numberValue; } public double GetNumberValue(){ return _numberValue; }
public float GetFloatValue() { return (float) _numberValue; } public float GetFloatValue() { return (float) _numberValue; }
public int GetIntValue(){ return (int) System.Math.Round( _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 bool GetBooleanValue(){ return _booleanValue; }
public string GetStringValue(){ return _stringValue; } public string GetStringValue(){ return _stringValue; }
public T GetEnumFromString<T>( T enumValue ) where T : System.Enum public T GetEnumFromString<T>( T enumValue ) where T : System.Enum

View File

@ -138,6 +138,10 @@ namespace Rokojori
{ {
SetNumber( data, reference, INT ); SetNumber( data, reference, INT );
} }
if ( typeof( long ) == type )
{
SetNumber( data, reference, LONG );
}
else if ( typeof( float ) == type ) else if ( typeof( float ) == type )
{ {
SetNumber( data, reference, FLOAT ); SetNumber( data, reference, FLOAT );
@ -283,6 +287,7 @@ namespace Rokojori
const int INT = 0; const int INT = 0;
const int FLOAT = 1; const int FLOAT = 1;
const int DOUBLE = 2; const int DOUBLE = 2;
const int LONG = 3;
void SetNumber( JSONData data, Reference reference, int numberType ) void SetNumber( JSONData data, Reference reference, int numberType )
{ {
@ -299,6 +304,7 @@ namespace Rokojori
case INT:{ reference.AssignValue( data.intValue ); return; } case INT:{ reference.AssignValue( data.intValue ); return; }
case FLOAT:{ reference.AssignValue( data.floatValue ); return; } case FLOAT:{ reference.AssignValue( data.floatValue ); return; }
case DOUBLE:{ reference.AssignValue( data.numberValue ); return; } case DOUBLE:{ reference.AssignValue( data.numberValue ); return; }
case LONG:{ reference.AssignValue( data.longValue ); return; }
} }
RJLog.Log( "Unknown number type: " + reference.GetInfo() + ">>" + data ); RJLog.Log( "Unknown number type: " + reference.GetInfo() + ">>" + data );
@ -344,6 +350,13 @@ namespace Rokojori
} }
break; break;
case LONG:
{
var value = objectValue.Get( JSONSerializationSettings.NUMBER_VALUE ).longValue;
reference.AssignValue( value );
}
break;
} }
} }

View File

@ -41,6 +41,10 @@ namespace Rokojori
{ {
return JSON.Stringify( CreateNumber( (int) value ) ); return JSON.Stringify( CreateNumber( (int) value ) );
} }
else if ( value is long )
{
return JSON.Stringify( CreateNumber( (long) value ) );
}
else if ( value is double ) else if ( value is double )
{ {
return JSON.Stringify( CreateNumber( (double) value ) ); return JSON.Stringify( CreateNumber( (double) value ) );
@ -147,6 +151,20 @@ namespace Rokojori
return new JSONValue( value ); 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 ) JSONData CreateNumber( float value )
{ {
if ( settings.saveNumbersWithType ) if ( settings.saveNumbersWithType )
@ -177,7 +195,15 @@ namespace Rokojori
bool IsProcessableObject( object value ) 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; return true;
} }
@ -189,7 +215,7 @@ namespace Rokojori
if ( processedObjects.Contains( value ) ) if ( processedObjects.Contains( value ) )
{ {
RJLog.Error( "Cycle detected: " + value ); RJLog.Error( "Cycle detected: " + value, value.GetType() );
var interfaces = typeof( object ).GetInterfaces(); var interfaces = typeof( object ).GetInterfaces();
for ( int i = 0; i < interfaces.Length; i++ ) for ( int i = 0; i < interfaces.Length; i++ )
@ -277,6 +303,10 @@ namespace Rokojori
{ {
jsonObject.Set( name, CreateNumber( (int) value ) ); jsonObject.Set( name, CreateNumber( (int) value ) );
} }
else if ( value is long )
{
jsonObject.Set( name, CreateNumber( (long) value ) );
}
else if ( value is double ) else if ( value is double )
{ {
jsonObject.Set( name, CreateNumber( (double) value ) ); jsonObject.Set( name, CreateNumber( (double) value ) );
@ -344,6 +374,10 @@ namespace Rokojori
{ {
jsonArray.Set( index, CreateNumber( (int) value ) ); jsonArray.Set( index, CreateNumber( (int) value ) );
} }
else if ( value is long )
{
jsonArray.Set( index, CreateNumber( (long) value ) );
}
else if ( value is double ) else if ( value is double )
{ {
jsonArray.Set( index, CreateNumber( (double) value ) ); jsonArray.Set( index, CreateNumber( (double) value ) );
@ -394,6 +428,10 @@ namespace Rokojori
{ {
jsonObject.Set( name, CreateNumber( (int) value ) ); jsonObject.Set( name, CreateNumber( (int) value ) );
} }
else if ( value is long )
{
jsonObject.Set( name, CreateNumber( (long) value ) );
}
else if ( value is double ) else if ( value is double )
{ {
jsonObject.Set( name, CreateNumber( (double) value ) ); jsonObject.Set( name, CreateNumber( (double) value ) );

View File

@ -17,6 +17,7 @@ namespace Rokojori
public static readonly string INT_NUMBER_TYPE = "int"; public static readonly string INT_NUMBER_TYPE = "int";
public static readonly string FLOAT_NUMBER_TYPE = "float"; public static readonly string FLOAT_NUMBER_TYPE = "float";
public static readonly string DOUBLE_NUMBER_TYPE = "double"; public static readonly string DOUBLE_NUMBER_TYPE = "double";
public static readonly string LONG_NUMBER_TYPE = "long";
static List<Type> serializableDictionaryKeyTypes = new List<Type>() static List<Type> serializableDictionaryKeyTypes = new List<Type>()
{ {