UI Sync/Procedural

This commit is contained in:
Josef 2025-06-23 13:16:01 +02:00
parent dab72b46d9
commit 8c8b50b6da
45 changed files with 1705 additions and 405 deletions

View File

@ -13,11 +13,13 @@ namespace Rokojori
[Export] [Export]
public Node3D target; public Node3D target;
[Export]
public bool global = true;
public override void _Process( double delta ) // public override void _Process( double delta )
{ // {
_OnTrigger(); // _OnTrigger();
} // }
protected override void _OnTrigger() protected override void _OnTrigger()
@ -27,8 +29,17 @@ namespace Rokojori
return; return;
} }
target.GlobalPosition = source.GlobalPosition; if ( global )
target.GlobalRotation = source.GlobalRotation; {
target.GlobalPosition = source.GlobalPosition;
target.GlobalRotation = source.GlobalRotation;
}
else
{
target.Position = source.Position;
target.Rotation = source.Rotation;
}
} }
} }
} }

View File

@ -13,11 +13,14 @@ namespace Rokojori
[Export] [Export]
public Node3D target; public Node3D target;
[Export]
public bool global = true;
public override void _Process( double delta )
{ // public override void _Process( double delta )
_OnTrigger(); // {
} // _OnTrigger();
// }
protected override void _OnTrigger() protected override void _OnTrigger()
{ {
@ -26,7 +29,14 @@ namespace Rokojori
return; return;
} }
target.GlobalPosition = source.GlobalPosition; if ( global )
{
target.GlobalPosition = source.GlobalPosition;
}
else
{
target.Position = source.Position;
}
} }
} }
} }

View File

@ -0,0 +1,39 @@
using Godot;
namespace Rokojori
{
[GlobalClass, Tool ]
public partial class CopyRotation : Action
{
[Export]
public Node3D source;
[Export]
public Node3D target;
[Export]
public bool global = true;
protected override void _OnTrigger()
{
if ( source == null || target == null )
{
return;
}
if ( global )
{
target.GlobalRotation = source.GlobalRotation;
}
else
{
target.Rotation = source.Rotation;
}
}
}
}

View File

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

View File

@ -354,6 +354,35 @@ namespace Rokojori
return null; return null;
} }
public int GetAncestorDistance( N child, N ancestor )
{
if ( ancestor == null )
{
return -1;
}
if ( child == ancestor )
{
return 0;
}
var p = Parent( child );
var distance = 1;
while ( p != null )
{
if ( p == ancestor )
{
return distance;
}
p = Parent( p );
distance ++;
}
return -1;
}
public int GetDepth( N node, Dictionary<N, int> depthMap = null ) public int GetDepth( N node, Dictionary<N, int> depthMap = null )
{ {

View File

@ -39,7 +39,7 @@ namespace Rokojori
public override void _Process( double delta ) public override void _Process( double delta )
{ {
if ( graphics == null || body == null ) if ( Engine.IsEditorHint() || graphics == null || body == null )
{ {
return; return;
} }

View File

@ -9,6 +9,12 @@ namespace Rokojori
[GlobalClass] [GlobalClass]
public partial class MultiRayCaster:Caster public partial class MultiRayCaster:Caster
{ {
public enum UpdateMode
{
Process,
Physics_Process
}
[Export] [Export]
public float rayLength = 10; public float rayLength = 10;
@ -27,6 +33,9 @@ namespace Rokojori
[Export] [Export]
public Node collider; public Node collider;
[Export]
public UpdateMode updateMode = UpdateMode.Physics_Process;
public override int NumColliders() public override int NumColliders()
{ {
return numCollisions; return numCollisions;
@ -55,8 +64,35 @@ namespace Rokojori
PhysicsRayQueryParameters3D rayParameters = new PhysicsRayQueryParameters3D(); PhysicsRayQueryParameters3D rayParameters = new PhysicsRayQueryParameters3D();
public override void _PhysicsProcess (double delta )
{
if ( UpdateMode.Physics_Process != updateMode )
{
return;
}
Update( delta );
}
public override void _Process( double delta ) public override void _Process( double delta )
{ {
if ( UpdateMode.Process != updateMode )
{
return;
}
Update( delta );
}
void Update( double delta )
{
if ( Engine.IsEditorHint() )
{
return;
}
Action.Trigger( beforeProcess ); Action.Trigger( beforeProcess );
ResolveCollisions(); ResolveCollisions();
@ -72,8 +108,7 @@ namespace Rokojori
} }
Action.Trigger( afterProcess ); Action.Trigger( afterProcess );
}
}
ValueSorter<CollisionData> singleSorter; ValueSorter<CollisionData> singleSorter;
MultiValueSorter<CollisionData> multiSorter; MultiValueSorter<CollisionData> multiSorter;

View File

@ -29,6 +29,9 @@ namespace Rokojori
[Export] [Export]
public Mesh mesh; public Mesh mesh;
[Export]
public GeometryInstance3D.ShadowCastingSetting castShadows = GeometryInstance3D.ShadowCastingSetting.On;
[Export] [Export]
public Material materialOveride; public Material materialOveride;
@ -50,10 +53,16 @@ namespace Rokojori
public float multiMeshSplitSize = 25; public float multiMeshSplitSize = 25;
[Export] [Export]
public Vector3 multiMeshSplitScatterRelative = new Vector3( 2, 0, 2 ); public float cullDistance = 100;
[Export] [Export]
public Vector3 multiMeshSplitScatterScale = new Vector3( 10, 10, 10 ); public float cullRange = 50;
[Export]
public Vector3 multiMeshSplitNoiseAmount = new Vector3( 2, 0, 2 );
[Export]
public Vector3 multiMeshSplitNoiseFrequency = new Vector3( 10, 10, 10 );
Dictionary<Vector3I,LODMultiMeshInstance3D> multiMeshMapping = new Dictionary<Vector3I, LODMultiMeshInstance3D>(); Dictionary<Vector3I,LODMultiMeshInstance3D> multiMeshMapping = new Dictionary<Vector3I, LODMultiMeshInstance3D>();
@ -160,10 +169,12 @@ namespace Rokojori
var instancesSorted = new MapList<Vector3I,int>(); var instancesSorted = new MapList<Vector3I,int>();
for ( int i = 0; i < positions.Length; i++ ) for ( int i = 0; i < positions.Length; i++ )
{ {
var floatIndex = ( positions[ i ] / multiMeshSplitSize ); var floatIndex = ( positions[ i ] / multiMeshSplitSize );
floatIndex += Noise.Perlin3( positions[ i ] * multiMeshSplitScatterScale ) * multiMeshSplitScatterRelative; floatIndex += Noise.Perlin3( positions[ i ] * multiMeshSplitNoiseFrequency ) * multiMeshSplitNoiseAmount;
var index = floatIndex.RoundToInt(); var index = floatIndex.RoundToInt();
instancesSorted.Add( index, i ); instancesSorted.Add( index, i );
@ -177,6 +188,10 @@ namespace Rokojori
for ( int i = 0; i < numMultiMeshes; i++ ) for ( int i = 0; i < numMultiMeshes; i++ )
{ {
var multiMeshNode = this.CreateChild<LODMultiMeshInstance3D>(); var multiMeshNode = this.CreateChild<LODMultiMeshInstance3D>();
var center = new Vector3( keys[ i ].X, keys[ i ].Y, keys[ i ].Z ) * multiMeshSplitSize;
multiMeshNode.GlobalPosition = center;
multiMeshNode.cullDistance = cullDistance;
multiMeshNode.cullRange = cullRange;
multiMeshNode.Multimesh = new MultiMesh(); multiMeshNode.Multimesh = new MultiMesh();
multiMeshNode.Multimesh.TransformFormat = MultiMesh.TransformFormatEnum.Transform3D; multiMeshNode.Multimesh.TransformFormat = MultiMesh.TransformFormatEnum.Transform3D;
@ -186,6 +201,7 @@ namespace Rokojori
var meshIndices = instancesSorted[ keys[ i ] ]; var meshIndices = instancesSorted[ keys[ i ] ];
mm.Mesh = mesh; mm.Mesh = mesh;
multiMeshNode.CastShadow = castShadows;
mm.InstanceCount = meshIndices.Count; mm.InstanceCount = meshIndices.Count;
if ( materialOveride != null ) if ( materialOveride != null )
@ -193,12 +209,12 @@ namespace Rokojori
multiMeshNode.MaterialOverride = materialOveride; multiMeshNode.MaterialOverride = materialOveride;
} }
this.LogInfo( i, ">>", keys[ i ], ">>", meshIndices.Count ); // this.LogInfo( i, ">>", keys[ i ], ">>", meshIndices.Count );
for ( int j = 0; j < meshIndices.Count; j++ ) for ( int j = 0; j < meshIndices.Count; j++ )
{ {
var index = meshIndices[ j ]; var index = meshIndices[ j ];
var trsf = Math3D.TRS( positions[ index ], rotations[ index ], scales[ index ] ); var trsf = Math3D.TRS( positions[ index ] - center, rotations[ index ], scales[ index ] );
mm.SetInstanceTransform( j, trsf ); mm.SetInstanceTransform( j, trsf );
} }

View File

@ -10,6 +10,7 @@ namespace Rokojori
public class MaterialType public class MaterialType
{ {
public Trillean isStandard = Trillean.Any; public Trillean isStandard = Trillean.Any;
public Shader shader = null;
public BaseMaterial3D.TransparencyEnum transparency; public BaseMaterial3D.TransparencyEnum transparency;
public BaseMaterial3D.BlendModeEnum blendMode; public BaseMaterial3D.BlendModeEnum blendMode;
public BaseMaterial3D.CullModeEnum cullMode; public BaseMaterial3D.CullModeEnum cullMode;
@ -24,12 +25,18 @@ namespace Rokojori
public bool Equals( MaterialType materialType ) public bool Equals( MaterialType materialType )
{ {
if ( isStandard != materialType.isStandard ) if ( isStandard != materialType.isStandard )
{ {
return false; return false;
} }
if ( Trillean.False == isStandard )
{
return shader == materialType.shader;
}
if ( transparency != materialType.transparency ) if ( transparency != materialType.transparency )
{ {
return false; return false;
@ -161,6 +168,8 @@ namespace Rokojori
{ {
isStandard = materialType.isStandard; isStandard = materialType.isStandard;
shader = materialType.shader;
transparency = materialType.transparency; transparency = materialType.transparency;
blendMode = materialType.blendMode; blendMode = materialType.blendMode;
cullMode = materialType.cullMode; cullMode = materialType.cullMode;
@ -186,7 +195,33 @@ namespace Rokojori
return From( sm ); return From( sm );
} }
return null;
return From( material as ShaderMaterial );
}
public static MaterialType From( ShaderMaterial shaderMaterial )
{
var mt = new MaterialType();
mt.isStandard = Trillean.False;
mt.shader = shaderMaterial.Shader;
// public (?:\w+\.)?\w+ (\w+).*?;
// mt.$1 = standardMaterial3D.$1;
// mt.transparency = standardMaterial3D.;
// mt.blendMode = standardMaterial3D.BlendMode;
// mt.cullMode = standardMaterial3D.CullMode;
// mt.depthDrawMode = standardMaterial3D.DepthDrawMode;
// mt.noDepthTest = standardMaterial3D.NoDepthTest;
// mt.shadingMode = standardMaterial3D.ShadingMode;
// mt.diffuseMode = standardMaterial3D.DiffuseMode;
// mt.specularMode = standardMaterial3D.SpecularMode;
// mt.disableAmbientLight = standardMaterial3D.DisableAmbientLight;
// mt.disableFog = standardMaterial3D.DisableFog;
return mt;
} }
public static MaterialType From( StandardMaterial3D standardMaterial3D ) public static MaterialType From( StandardMaterial3D standardMaterial3D )

View File

@ -34,6 +34,22 @@ namespace Rokojori
[Export] [Export]
public Node3D pivot; public Node3D pivot;
public enum SortMode
{
No_Sorting,
Sort_By_Pivot_Distance,
Randomize
}
[Export]
public SortMode sortMode = SortMode.No_Sorting;
[Export]
public bool reverseSortOrder = false;
[Export]
public int randomSortSeed = 1234;
[ExportGroup( "Material")] [ExportGroup( "Material")]
[Export] [Export]
public bool combineMaterials = true; public bool combineMaterials = true;
@ -72,7 +88,18 @@ namespace Rokojori
{ {
if ( ! _meshGeometryCache.Has( surface.mesh, surface.index ) ) if ( ! _meshGeometryCache.Has( surface.mesh, surface.index ) )
{ {
var mg = MeshGeometry.From( surface.mesh as ArrayMesh, null, surface.index ); // var arrayMesh = surface.mesh as ArrayMesh;
// if ( arrayMesh == null )
// {
// arrayMesh = new ArrayMesh();
// var st = new SurfaceTool();
// st.Begin( Mesh.PrimitiveType.Triangles );
// st.CreateFrom( surface.mesh, surface.index );
// st.Commit( arrayMesh );
// }
var mg = MeshGeometry.From( surface.mesh, null, surface.index );
_meshGeometryCache.Set( surface.mesh, surface.index, mg ); _meshGeometryCache.Set( surface.mesh, surface.index, mg );
this.LogInfo( "Created mesh with triangles:", mg.numTriangles ); this.LogInfo( "Created mesh with triangles:", mg.numTriangles );
@ -132,6 +159,8 @@ namespace Rokojori
{ {
MeshExtractor.ExtractSurfacesInHierarchy( n, _surfaces ); MeshExtractor.ExtractSurfacesInHierarchy( n, _surfaces );
} }
this.LogInfo( "Surfaces found:", _surfaces.Count );
} }
async Task GrabMaterials() async Task GrabMaterials()
@ -369,6 +398,42 @@ namespace Rokojori
var surfaces = _materiaList[ m ]; var surfaces = _materiaList[ m ];
if ( SortMode.Sort_By_Pivot_Distance == sortMode )
{
var center = pivot == null ? Vector3.Zero : pivot.GlobalPosition;
surfaces.Sort(
( a, b )=>
{
var distanceA = ( a.transform.Origin - center ).LengthSquared();
var distanceB = ( b.transform.Origin - center ).LengthSquared();
return Mathf.Sign( distanceA - distanceB );
}
);
}
if ( SortMode.Randomize == sortMode )
{
var random = LCG.WithSeed( randomSortSeed );
var randomValues = new Dictionary<Transformable<MeshSurface>,float>();
surfaces.ForEach( s => randomValues[ s ] = random.Next() );
surfaces.Sort(
( a, b )=>
{
var distanceA = randomValues[ a ];
var distanceB = randomValues[ b ];
return Mathf.Sign( distanceA - distanceB );
}
);
}
if ( reverseSortOrder )
{
surfaces.Reverse();
}
this.LogInfo( "Combining for Material", "combined?:",isCombinedMaterial,"material:", usedMaterial, surfaces.Count, "meshes" ); this.LogInfo( "Combining for Material", "combined?:",isCombinedMaterial,"material:", usedMaterial, surfaces.Count, "meshes" );
var meshGeometry = new MeshGeometry(); var meshGeometry = new MeshGeometry();
@ -466,12 +531,10 @@ namespace Rokojori
if ( combineMeshes ) if ( combineMeshes )
{ {
if ( outputMesh == null ) outputMesh = null;
{ this.DestroyChildren();
this.LogInfo( "Created outputMesh");
outputMesh = this.CreateChild<MeshInstance3D>();
}
outputMesh = this.CreateChild<MeshInstance3D>();
outputMesh.Mesh = arrayMesh; outputMesh.Mesh = arrayMesh;
} }

View File

@ -285,10 +285,32 @@ namespace Rokojori
return From( (ArrayMesh)meshInstance3D.Mesh, meshInstance3D.GlobalTransform ); return From( (ArrayMesh)meshInstance3D.Mesh, meshInstance3D.GlobalTransform );
} }
public static MeshGeometry From( Mesh mesh, Transform3D? trsf = null, int index = 0 )
{
var arrayMesh = mesh as ArrayMesh;
if ( arrayMesh == null )
{
arrayMesh = new ArrayMesh();
var st = new SurfaceTool();
st.Begin( Mesh.PrimitiveType.Triangles );
st.CreateFrom( mesh, index );
st.Commit( arrayMesh );
}
return From( arrayMesh, trsf, 0 );
}
public static MeshGeometry From( ArrayMesh mesh, Transform3D? trsf = null, int index = 0 ) public static MeshGeometry From( ArrayMesh mesh, Transform3D? trsf = null, int index = 0 )
{ {
var mg = new MeshGeometry(); var mg = new MeshGeometry();
if ( mesh == null )
{
return mg;
}
var arrays = mesh.SurfaceGetArrays( index ); var arrays = mesh.SurfaceGetArrays( index );
var vertices = arrays[ (int) Mesh.ArrayType.Vertex ]; var vertices = arrays[ (int) Mesh.ArrayType.Vertex ];

View File

@ -23,12 +23,30 @@ namespace Rokojori
[Export] [Export]
public bool getMeshInstanceChild = false; public bool getMeshInstanceChild = false;
[ExportGroup("Instancing")]
[Export] [Export]
public bool useInstancing = false; public bool useInstancing = false;
[Export]
public float instancingCullDistance = 1000;
[Export]
public float instancingCullRange = 500;
[Export] [Export]
public float instancingSplitSize = 25; public float instancingSplitSize = 25;
[Export]
public Vector3 instancingSplitScatterNoiseAmount = Vector3.Zero;
[Export]
public Vector3 instancingSplitScatterNoiseFrequency = Vector3.Zero;
[ExportGroup("")]
protected PackedScene _cachedNode3DScene; protected PackedScene _cachedNode3DScene;
public PackedScene GetPackedScene() public PackedScene GetPackedScene()

View File

@ -64,6 +64,17 @@ namespace Rokojori
p.parent = gs.container != null ? gs.container : container; p.parent = gs.container != null ? gs.container : container;
p.instanced = gs.useInstancing; p.instanced = gs.useInstancing;
p.instanceSplitSize = gs.instancingSplitSize; p.instanceSplitSize = gs.instancingSplitSize;
p.instancingSplitScatterNoiseAmount = gs.instancingSplitScatterNoiseAmount;
p.instancingSplitScatterNoiseFrequency = gs.instancingSplitScatterNoiseFrequency;
p.instanceCullDistance = gs.instancingCullDistance;
p.instanceCullRange = gs.instancingCullRange;
if ( gs.node3D != null && gs.node3D is MeshInstance3D mi )
{
p.shadowCasting = mi.CastShadow;
}
} }
} }

View File

@ -10,7 +10,15 @@ namespace Rokojori
public class ScatterPoint:PointData public class ScatterPoint:PointData
{ {
public bool instanced = false; public bool instanced = false;
public float instanceCullDistance = 200;
public float instanceCullRange = 100;
public float instanceSplitSize = 25; public float instanceSplitSize = 25;
public Vector3 instancingSplitScatterNoiseAmount = Vector3.Zero;
public Vector3 instancingSplitScatterNoiseFrequency = Vector3.Zero;
public GeometryInstance3D.ShadowCastingSetting shadowCasting = GeometryInstance3D.ShadowCastingSetting.On;
protected Scatterer _creator; protected Scatterer _creator;
public Scatterer creator => _creator; public Scatterer creator => _creator;
protected int _creatorID; protected int _creatorID;

View File

@ -344,6 +344,11 @@ namespace Rokojori
c.materialOveride = mwm.material; c.materialOveride = mwm.material;
c.mesh = mwm.mesh; c.mesh = mwm.mesh;
c.multiMeshSplitSize = sp.instanceSplitSize; c.multiMeshSplitSize = sp.instanceSplitSize;
c.multiMeshSplitNoiseAmount = sp.instancingSplitScatterNoiseAmount;
c.multiMeshSplitNoiseFrequency = sp.instancingSplitScatterNoiseFrequency;
c.cullDistance = sp.instanceCullDistance;
c.cullRange = sp.instanceCullRange;
c.castShadows = sp.shadowCasting;
_instancedMassRenderers.Add( mwm.mesh, c ); _instancedMassRenderers.Add( mwm.mesh, c );

View File

@ -27,6 +27,10 @@ namespace Rokojori
[Export] [Export]
public Vector3 positionNoiseOffset = Vector3.Zero; public Vector3 positionNoiseOffset = Vector3.Zero;
[Export]
public Vector3 staticOffset = Vector3.Zero;
[ExportGroup( "Rotation" )] [ExportGroup( "Rotation" )]
[Export] [Export]
public Vector3 rotationOffset = Vector3.Zero; public Vector3 rotationOffset = Vector3.Zero;
@ -75,7 +79,7 @@ namespace Rokojori
var scaleRandom = Noise.Perlin3( scalePerlin ); var scaleRandom = Noise.Perlin3( scalePerlin );
var uniformScaleRandom = Noise.Perlin( scalePerlin + new Vector3( 100002, -10002, 1000 ) ); var uniformScaleRandom = Noise.Perlin( scalePerlin + new Vector3( 100002, -10002, 1000 ) );
p.position += positionOffset * positionRandom * positionOffsetScale; p.position += positionOffset * positionRandom * positionOffsetScale + staticOffset;
p.rotation *= Quaternion.FromEuler( rotationOffset * MathX.DegreesToRadians * rotationRandom * rotationOffsetScale ); p.rotation *= Quaternion.FromEuler( rotationOffset * MathX.DegreesToRadians * rotationRandom * rotationOffsetScale );

View File

@ -252,6 +252,18 @@ namespace Rokojori
return list[ index ]; return list[ index ];
} }
public T From<T>( List<T> list, int start, int end )
{
if ( list.Count == 0 )
{
return default ( T );
}
var index = this.IntegerInclusive( start, end );
return list[ index ];
}
public T RemoveFrom<T>( List<T> list ) public T RemoveFrom<T>( List<T> list )
{ {
if ( list.Count == 0 ) if ( list.Count == 0 )

View File

@ -229,6 +229,11 @@ namespace Rokojori
} }
//this.LogInfo( "Register", s ); //this.LogInfo( "Register", s );
if ( ! sensorToRunner.ContainsKey( s ) )
{
return;
}
var sensorRunner = sensorToRunner[ s ]; var sensorRunner = sensorToRunner[ s ];
if ( sensorRunner.listeners.Contains( sih ) ) if ( sensorRunner.listeners.Contains( sih ) )
@ -337,6 +342,28 @@ namespace Rokojori
HashSet<object> _scannedObjects = new HashSet<object>(); HashSet<object> _scannedObjects = new HashSet<object>();
bool IsIgnoreType( object obj )
{
var ignoreTypes = new List<Type>()
{
typeof( GpuParticles3D ),
typeof( MeshInstance3D ),
typeof( Node3D ),
typeof( CollisionShape3D ),
typeof( OmniLight3D ),
typeof( DirectionalLight3D ),
typeof( WorldEnvironment ),
typeof( Area3D ),
typeof( CharacterBody3D ),
typeof( AudioStreamPlayer3D ),
typeof( ReflectionProbe )
};
return ignoreTypes.IndexOf( obj.GetType() ) != -1;
}
void AddSensorsFrom( object obj ) void AddSensorsFrom( object obj )
{ {
if ( Engine.IsEditorHint() ) if ( Engine.IsEditorHint() )
@ -345,52 +372,68 @@ namespace Rokojori
} }
//this.LogInfo( "AddSensorsFrom", obj ); //this.LogInfo( "AddSensorsFrom", obj );
if ( obj == null || _scannedObjects.Contains( obj ) )
{
return;
}
_scannedObjects.Add( obj );
var sensors = ReflectionHelper.GetDataMemberValues<Sensor>( obj );
if ( sensors.Count > 0 )
{
if ( obj is Node n )
{
n.LogInfo( sensors );
}
else if ( obj is Resource r )
{
r.LogInfo( sensors );
}
}
try
{
sensors.ForEach( if ( obj == null || _scannedObjects.Contains( obj ) )
s =>
{ {
AddSensor( s ); return;
} }
);
var sensorArrays = ReflectionHelper.GetDataMemberValues<Sensor[]>( obj );
_scannedObjects.Add( obj );
sensorArrays.ForEach( if ( IsIgnoreType( obj ) )
s =>
{ {
for ( int i = 0; i < s.Length; i++ ) return;
}
var sensors = ReflectionHelper.GetDataMemberValues<Sensor>( obj );
if ( sensors.Count > 0 )
{
if ( obj is Node n )
{ {
AddSensor( s[ i ] ); n.LogInfo( sensors );
}
else if ( obj is Resource r )
{
r.LogInfo( sensors );
} }
} }
);
var resources = ReflectionHelper.GetDataMemberValues<Resource>( obj ); sensors.ForEach(
s =>
{
AddSensor( s );
}
);
resources.ForEach( r => AddSensorsFrom( r ) ); var sensorArrays = ReflectionHelper.GetDataMemberValues<Sensor[]>( obj );
sensorArrays.ForEach(
s =>
{
for ( int i = 0; i < s.Length; i++ )
{
AddSensor( s[ i ] );
}
}
);
var resources = ReflectionHelper.GetDataMemberValues<Resource>( obj );
resources.ForEach( r => AddSensorsFrom( r ) );
}
catch( System.Exception e )
{
this.LogError( e );
}
} }
void CreateRunners() void CreateRunners()

View File

@ -30,7 +30,7 @@ namespace Rokojori
roots.ForEach( roots.ForEach(
( r )=> ( r )=>
{ {
Nodes.ForEach<Node3D>( r, n => CheckWarningsOf( n ) ); Nodes.ForEach<Node>( r, n => CheckWarningsOf( n ) );
} }
); );

View File

@ -10,6 +10,8 @@ namespace Rokojori
{ {
public static class DateMath public static class DateMath
{ {
public static float GetDifference( this DateTime a, DateTime b ) public static float GetDifference( this DateTime a, DateTime b )
{ {
return (float) ( ( a - b ).TotalSeconds ); return (float) ( ( a - b ).TotalSeconds );

View File

@ -27,6 +27,7 @@ namespace Rokojori
[Export] [Export]
public bool autoStart = true; public bool autoStart = true;
public static float osTime => (float)( Time.GetTicksMsec() / 1000.0 );
public TimeLineRunner runner public TimeLineRunner runner
{ {

View File

@ -605,6 +605,42 @@ namespace Rokojori
return copy; return copy;
} }
public static bool Has<T>( this List<T> list, Func<T,bool> evaluater )
{
foreach ( var t in list )
{
if ( evaluater( t ) )
{
return true;
}
}
return false;
}
public static void SwapTowardsBegin<T>( this List<T> list, int index, int steps = 1 )
{
list.Swap( index, index - steps );
}
public static void SwapTowardsEnd<T>( this List<T> list, int index, int steps = 1 )
{
list.Swap( index, index + steps );
}
public static void Swap<T>( this List<T> list, int indexA, int indexB )
{
if ( list == null || indexA == indexB || indexA < 0 || indexB < 0 || indexA >= list.Count || indexA >= list.Count )
{
return;
}
var buffer = list[ indexA ];
list[ indexA ] = list[ indexB ];
list[ indexB ] = buffer;
}
public static List<U> FilterAndMap<T,U>( List<T> list, Func<T,int,bool> filter, Func<T,U> map) public static List<U> FilterAndMap<T,U>( List<T> list, Func<T,int,bool> filter, Func<T,U> map)
{ {
var mapped = new List<U>(); var mapped = new List<U>();

View File

@ -8,6 +8,18 @@ namespace Rokojori
{ {
public class UIDragging public class UIDragging
{ {
public class MappedEvent
{
public MouseButton mouseButton;
public EditableUIDraggingEvent uiEvent;
}
public class ButtonState
{
public MouseButton mouseButton;
public bool dragging;
}
public class UIDraggingCallbacks: ICustomDisposer public class UIDraggingCallbacks: ICustomDisposer
{ {
public UI ui; public UI ui;
@ -15,13 +27,23 @@ namespace Rokojori
public bool wasDisposed = false; public bool wasDisposed = false;
public bool notValid =>
wasDisposed ||
onMouseClick == null ||
onDragging == null ||
onProcess == null ||
mouseEvents == null || mouseEvents.FilterNulls().Count == 0 ||
mouseEventsDragging == null || mouseEventsDragging.FilterNulls().Count == 0;
public Action<InputEvent> onMouseClick; public Action<InputEvent> onMouseClick;
public Callable callable; public Callable callable;
public Action<InputEvent> onDragging; public Action<InputEvent> onDragging;
public Action<float> onProcess; public Action<float> onProcess;
public Dictionary<MouseButton,EditableUIDraggingEvent> mouseEvents = new Dictionary<MouseButton, EditableUIDraggingEvent>(); // public Dictionary<MouseButton,EditableUIDraggingEvent> mouseEvents = new Dictionary<MouseButton, EditableUIDraggingEvent>();
public Dictionary<MouseButton,bool> mouseEventsDragging = new Dictionary<MouseButton, bool>(); public List<MappedEvent> mouseEvents = new List<MappedEvent>();
public List<ButtonState> mouseEventsDragging = new List<ButtonState>();
// public Dictionary<MouseButton,bool> mouseEventsDragging = new Dictionary<MouseButton, bool>();
public string uid = IDGenerator.GenerateID(); public string uid = IDGenerator.GenerateID();
public string GetUID(){ return uid; } public string GetUID(){ return uid; }
@ -42,10 +64,16 @@ namespace Rokojori
callbacks.onProcess = (float delta )=> callbacks.onProcess = (float delta )=>
{ {
foreach ( var m in callbacks.mouseEvents ) callbacks.mouseEvents.ForEach(
{ ( m )=>
callback( callbacks.mouseEvents[ m.Key ] ); {
} callback( m.uiEvent );
}
);
// foreach ( var m in callbacks.mouseEvents )
// {
// callback( callbacks.mouseEvents[ m.Key ] );
// }
}; };
callbacks.onDragging = ( InputEvent ie ) => callbacks.onDragging = ( InputEvent ie ) =>
@ -53,11 +81,13 @@ namespace Rokojori
if ( ie is InputEventMouseButton mb && ! mb.Pressed ) if ( ie is InputEventMouseButton mb && ! mb.Pressed )
{ {
callbacks.mouseEventsDragging[ mb.ButtonIndex ] = false; var mdIndex = callbacks.mouseEventsDragging.FindIndex( me => me.mouseButton == mb.ButtonIndex );
var meIndex = callbacks.mouseEvents.FindIndex( md => md.mouseButton == mb.ButtonIndex );
callbacks.mouseEventsDragging[ mdIndex ].dragging = false;
callbacks.mouseEvents[ mb.ButtonIndex ].UpdatePosition( mb.GlobalPosition, true ); callbacks.mouseEvents[ meIndex ].uiEvent.UpdatePosition( mb.GlobalPosition, true );
callback( callbacks.mouseEvents[ mb.ButtonIndex ] ); callback( callbacks.mouseEvents[ meIndex ].uiEvent );
if ( ! callbacks.hasAnyMouseDragging ) if ( ! callbacks.hasAnyMouseDragging )
{ {
@ -76,11 +106,18 @@ namespace Rokojori
{ {
var globalPosition = mo.GlobalPosition; var globalPosition = mo.GlobalPosition;
foreach ( var m in callbacks.mouseEvents ) // foreach ( var m in callbacks.mouseEvents )
// {
// callbacks.mouseEvents[ m.Key ].UpdatePosition( globalPosition );
// // callback( callbacks.mouseEvents[ m.Key ] );
// }
callbacks.mouseEvents.ForEach(
( m )=>
{ {
callbacks.mouseEvents[ m.Key ].UpdatePosition( globalPosition ); m.uiEvent.UpdatePosition( globalPosition );
// callback( callbacks.mouseEvents[ m.Key ] );
} }
);
} }
@ -111,7 +148,19 @@ namespace Rokojori
{ {
sc.GetUISelectorFlags().AddIfNotPresent( UISelectorFlag.Dragging ); sc.GetUISelectorFlags().AddIfNotPresent( UISelectorFlag.Dragging );
} }
callbacks.mouseEventsDragging[ button ] = true;
var buttonIndex = callbacks.mouseEventsDragging.FindIndex( bs => bs.mouseButton == button );
if ( buttonIndex == -1 )
{
var bs = new ButtonState();
bs.mouseButton = button;
callbacks.mouseEventsDragging.Add( bs );
buttonIndex = callbacks.mouseEventsDragging.Count - 1;
}
callbacks.mouseEventsDragging[ buttonIndex ].dragging = true;
if ( ! callbacks.hasDraggingCallback ) if ( ! callbacks.hasDraggingCallback )
{ {
@ -162,7 +211,7 @@ namespace Rokojori
{ {
foreach ( var mb in mouseEventsDragging ) foreach ( var mb in mouseEventsDragging )
{ {
if ( mb.Value ) if ( mb.dragging )
{ {
return true; return true;
} }
@ -177,14 +226,20 @@ namespace Rokojori
public EditableUIDraggingEvent GetMouseEvent( MouseButton mb ) public EditableUIDraggingEvent GetMouseEvent( MouseButton mb )
{ {
if ( ! mouseEvents.ContainsKey( mb ) ) var index = mouseEvents.FindIndex( m => m.mouseButton == mb );
if ( index == -1)
{ {
mouseEvents[ mb ] = new EditableUIDraggingEvent( mb ); var mappedEvent = new MappedEvent();
mappedEvent.mouseButton = mb;
mappedEvent.uiEvent = new EditableUIDraggingEvent( mb );
mouseEvents.Add( mappedEvent );
index = mouseEvents.Count - 1;
} }
mouseEvents[ mb ].SetUI( ui ); mouseEvents[ index ].uiEvent.SetUI( ui );
return mouseEvents[ mb ]; return mouseEvents[ index ].uiEvent;
} }
public void Clear() public void Clear()

View File

@ -121,7 +121,7 @@ namespace Rokojori
ui.onProcess.AddAction( UpdatePosition ); ui.onProcess.AddAction( UpdatePosition );
( button as UIStylePropertyContainer ).AddUISelectorFlag( UISelectorFlag.Scrolling, scrollID ); ( button as UIStylePropertyContainer ).AddUISelectorFlag( UISelectorFlag.Scrolling, scrollID );
( button as UIStylePropertyContainerNode ).SetDirty();
} }
}; };
@ -159,12 +159,25 @@ namespace Rokojori
bool _dragging = false; bool _dragging = false;
bool _updatingPosition = false; bool _updatingPosition = false;
UIDragging.UIDraggingCallbacks leftMouseCallback; UIDragging.UIDraggingCallbacks leftMouseCallbacks;
UIDragging.UIDraggingCallbacks middleMouseCallbacks;
public override void _Process( double delta )
{
if (
leftMouseCallbacks == null || leftMouseCallbacks.notValid ||
middleMouseCallbacks == null || middleMouseCallbacks.notValid
)
{
AddDraggingListener();
}
}
void AddDraggingListener() void AddDraggingListener()
{ {
leftMouseCallback = UIDragging.OnLeftMouseButton( button, leftMouseCallbacks = UIDragging.OnLeftMouseButton( button,
( ev )=> ( ev )=>
{ {
if ( ev.isStart ) if ( ev.isStart )
@ -189,7 +202,7 @@ namespace Rokojori
} }
); );
UIDragging.OnMiddleMouseButton( scrollContainer, middleMouseCallbacks = UIDragging.OnMiddleMouseButton( scrollContainer,
( ev )=> ( ev )=>
{ {
if ( ev.isStart ) if ( ev.isStart )
@ -223,10 +236,12 @@ namespace Rokojori
Vector2 cachedOffset = Vector2.Zero; Vector2 cachedOffset = Vector2.Zero;
void UpdatePosition( float delta ) void UpdatePosition( float delta )
{ {
// this.LogInfo( "UpdatePosition" );
var value = Smoothing.Apply( smoothing, nextValue, delta ); var value = Smoothing.Apply( smoothing, nextValue, delta );
var uiStyleContainer = ( UIStylePropertyContainer ) button; var uiStyleContainer = ( UIStylePropertyContainerNode ) button;
uiStyleContainer.SetLayoutDirtyFlag();
if ( ! _dragging && ( value - nextValue ).Length() < 1 ) if ( ! _dragging && ( value - nextValue ).Length() < 1 )
{ {
@ -249,14 +264,15 @@ namespace Rokojori
{ {
var left = new UINumber(); var left = new UINumber();
left.value = value.X; left.value = value.X;
uiStyleContainer.SetUIStyleNumberProperty( UIStyleNumberProperty.Left, left ); uiStyleContainer.SetUIStyleNumberProperty( UIStyleNumberProperty.Left, left );
} }
if ( Direction.Both == direction || Direction.Vertical == direction ) if ( Direction.Both == direction || Direction.Vertical == direction )
{ {
var top = new UINumber(); var top = new UINumber();
top.value = value.Y; top.value = value.Y;
uiStyleContainer.SetUIStyleNumberProperty( UIStyleNumberProperty.Top, top ); uiStyleContainer.SetUIStyleNumberProperty( UIStyleNumberProperty.Top, top );
} }
var range = background.Size - button.Size; var range = background.Size - button.Size;
@ -268,18 +284,21 @@ namespace Rokojori
var scrollOffset = scrollRange * sliderValue; var scrollOffset = scrollRange * sliderValue;
var scrollTargetNode = scrollTarget as UIStylePropertyContainerNode;
if ( Direction.Both == direction || Direction.Horizontal == direction ) if ( Direction.Both == direction || Direction.Horizontal == direction )
{ {
var left = new UINumber(); var left = new UINumber();
left.value = -scrollOffset.X; left.value = -scrollOffset.X;
( scrollTarget as UIStylePropertyContainer ).SetUIStyleNumberProperty( UIStyleNumberProperty.Left, left ); scrollTargetNode.SetUIStyleNumberProperty( UIStyleNumberProperty.Left, left );
} }
if ( Direction.Both == direction || Direction.Vertical == direction ) if ( Direction.Both == direction || Direction.Vertical == direction )
{ {
var top = new UINumber(); var top = new UINumber();
top.value = -scrollOffset.Y; top.value = -scrollOffset.Y;
( scrollTarget as UIStylePropertyContainer ).SetUIStyleNumberProperty( UIStyleNumberProperty.Top, top ); scrollTargetNode.SetUIStyleNumberProperty( UIStyleNumberProperty.Top, top );
} }
} }
@ -299,6 +318,7 @@ namespace Rokojori
void SyncScroll() void SyncScroll()
{ {
if ( _dragging || _updatingPosition ) if ( _dragging || _updatingPosition )
{ {
// this.LogInfo( "SyncScroll blocked" ); // this.LogInfo( "SyncScroll blocked" );
@ -307,9 +327,11 @@ namespace Rokojori
// this.LogInfo( "SyncScroll" ); // this.LogInfo( "SyncScroll" );
var uiStyleContainer = ( UIStylePropertyContainer ) button; var uiStyleContainer = ( UIStylePropertyContainerNode ) button;
var value = GetButtonScrollRange() * sliderValue; var value = GetButtonScrollRange() * sliderValue;
uiStyleContainer.SetDirty();
if ( Direction.Both == direction || Direction.Horizontal == direction ) if ( Direction.Both == direction || Direction.Horizontal == direction )
{ {
var left = new UINumber(); var left = new UINumber();

View File

@ -135,6 +135,8 @@ namespace Rokojori
UILayouting.SetPositionInParentAnchor( region ); UILayouting.SetPositionInParentAnchor( region );
} }
region.CommitUpdateInfo();
Nodes.ForEachDirectChild<Control>( region, Nodes.ForEachDirectChild<Control>( region,
child => child =>
{ {
@ -151,6 +153,8 @@ namespace Rokojori
} }
); );
region.CommitUpdateInfo();
} }
static List<Line> CreateLines( UIRegion region ) static List<Line> CreateLines( UIRegion region )

View File

@ -34,164 +34,28 @@ namespace Rokojori
return; return;
} }
if ( control is UIRegion ) if ( control is UIRegion region )
{ {
var childUIRegion = (UIRegion) control; region.Layout();
childUIRegion.Layout();
} }
else if ( control is UIImage ) else if ( control is UIImage uiImage )
{ {
var tw = 0; uiImage.Update();
var th = 0; uiImage.CommitUpdateInfo();
if ( control is UIImage )
{
var uiImage = (UIImage) control;
if ( uiImage.Texture == null )
{
uiImage.Size = new Vector2( 0, 0 );
return;
}
tw = uiImage.Texture.GetWidth();
th = uiImage.Texture.GetHeight();
}
var container = (UIStylePropertyContainer) control;
var w = UINumber.Compute( control, UIStyleNumberProperty.Width, tw, tw / 100f );
var h = UINumber.Compute( control, UIStyleNumberProperty.Height, th, th / 100f );
// RJLog.Log( "Set Image Size", w, h );
control.Size = new Vector2( w, h );
if ( control is UIImage )
{
var uiImage = (UIImage) control;
if ( uiImage.Material != null )
{
var ui = uiImage.GetUI();
if ( ui == null )
{
RJLog.Log( "No UI Found", HierarchyName.Of( uiImage ) );
return;
}
if ( ui.settings == null )
{
RJLog.Log( "No UI settings Found", HierarchyName.Of( uiImage ) );
return;
}
if ( ui.settings.sizePropertyName == null )
{
// RJLog.Log( "No UI.settings.sizePropertyName Found" );
return;
}
//RJLog.Log( "Setting Size", ui.settings.sizePropertyName.propertyName, HierarchyName.Of( uiImage ) );
ui.settings.sizePropertyName.Set( uiImage.Material, uiImage.Size );
// UIShaderProperties.UpdatePropertiesInHierarchy( uiImage, uiImage.Material );
var colorProperties = uiImage.imageType != null ? uiImage.imageType.GetColorShaderProperties() : [];
var colorPropertyName = new ColorPropertyName();
foreach ( var c in colorProperties )
{
// uiImage.LogInfo( c );
var color = UIColor.Compute( control, UIStyleColorProperty.ColorShaderProperty, c, Colors.White );
colorPropertyName.propertyName = c;
colorPropertyName.Set( uiImage.Material, color );
}
var numberProperties = uiImage.imageType != null ? uiImage.imageType.GetNumberShaderProperties() : [];
var numberPropertyName = new FloatPropertyName();
foreach ( var n in numberProperties )
{
// uiImage.LogInfo( c );
var value = UINumber.Compute( control, UIStyleNumberProperty.FloatShaderProperty, n );
numberPropertyName.propertyName = n;
numberPropertyName.Set( uiImage.Material, value );
}
return;
}
}
} }
else if ( control is UIText ) else if ( control is UIText uiText )
{ {
var text = (UIText) control; uiText.Update();
uiText.CommitUpdateInfo();
var container = (UIStylePropertyContainer) control;
text.uiTextLabelSettings.FontSize = Mathf.Max( 1,
UINumber.ComputeInt( control, UIStyleNumberProperty.FontSize, UINumber.em( control ), UINumber.em( control ) / 100f ) );
text.uiTextLabelSettings.FontColor =
UIColor.Compute( control, UIStyleColorProperty.FontColor, "", Colors.White );
text.uiTextLabelSettings.OutlineSize =
UINumber.ComputeInt( control, UIStyleNumberProperty.FontOutlineSize, 0 );
text.uiTextLabelSettings.OutlineColor =
UIColor.Compute( control, UIStyleColorProperty.FontOutlineColor, "", Colors.Transparent );
text.uiTextLabelSettings.ShadowSize =
UINumber.ComputeInt( control, UIStyleNumberProperty.FontShadowSize, 0 );
text.uiTextLabelSettings.ShadowColor =
UIColor.Compute( control, UIStyleColorProperty.FontShadowColor, "", Colors.Black );
text.uiTextLabelSettings.ShadowOffset = new Vector2(
UINumber.Compute( control, UIStyleNumberProperty.FontShadowOffsetX, 0 ),
UINumber.Compute( control, UIStyleNumberProperty.FontShadowOffsetY, 0 )
);
control.UpdateMinimumSize();
if ( text.alwaysMinimumSize )
{
if ( text.AutowrapMode == TextServer.AutowrapMode.Word )
{
text.AutowrapMode = TextServer.AutowrapMode.Off;
var minSize = text.GetMinimumSize();
text.AutowrapMode = TextServer.AutowrapMode.Word;
var w = UINumber.Compute( control, UIStyleNumberProperty.Width, minSize.X, minSize.X / 100f );
var h = UINumber.Compute( control, UIStyleNumberProperty.Height, minSize.Y, minSize.Y / 100f );
control.CustomMinimumSize = new Vector2( Mathf.Min( minSize.X, w ), 0 );
}
control.Size = control.GetMinimumSize();
}
else
{
var minSize = control.GetMinimumSize();
var w = UINumber.Compute( control, UIStyleNumberProperty.Width, minSize.X, minSize.X / 100f );
var h = UINumber.Compute( control, UIStyleNumberProperty.Height, minSize.Y, minSize.Y / 100f );
// RJLog.Log( "Set Image Size", w, h );
control.Size = new Vector2( w, h );
}
} }
else else
{ {
// control.UpdateMinimumSize();
// control.Size = control.GetMinimumSize();
} }
UILayouting.UpdatePivot( control ); UpdatePivot( control );
} }
public static void SetPositionInParentAnchor( UIStylePropertyContainer container ) public static void SetPositionInParentAnchor( UIStylePropertyContainer container )
{ {
var control = (Control) container; var control = (Control) container;

View File

@ -7,8 +7,8 @@ namespace Rokojori
{ {
public interface UIHolderControl public interface UIHolderControl
{ {
public void SetUI( UI ui); public void SetUI( UI ui, bool computeDepth = true );
public UI GetUI(); public UI GetUI( bool computeDepth = true );
} }
public class UIHolder public class UIHolder

View File

@ -8,7 +8,7 @@ namespace Rokojori
{ {
[Tool] [Tool]
[GlobalClass,Icon("res://addons/rokojori_action_library/Icons/UIImage.svg")] [GlobalClass,Icon("res://addons/rokojori_action_library/Icons/UIImage.svg")]
public partial class UIImage:TextureRect, UIStylePropertyContainer, UIHolderControl, IAssemblyReload public partial class UIImage:TextureRect, UIStylePropertyContainerNode, UIHolderControl, IAssemblyReload
{ {
UIImageType _imageType; UIImageType _imageType;
[Export] [Export]
@ -33,28 +33,43 @@ namespace Rokojori
UI ui; UI ui;
public void SetUI( UI ui ) public void SetUI( UI ui, bool computeDepth = true )
{ {
this.ui = ui; this.ui = ui;
if ( computeDepth )
{
ComputeUIAncestorDepth();
}
} }
public UI GetUI() public UI GetUI( bool computeDepth = true )
{ {
var ui = this.ui != null ? this.ui : Unique<UI>.Get(); if ( this.ui != null )
{
return this.ui;
}
var ui = this.FindParentThatIs<UI>();
if ( ui == null ) if ( ui == null )
{ {
ui = this.FindParentThatIs<UI>();
this._uiAncestorDepth = -1;
this.LogInfo( "No UI in parents >", ui );
if ( ui == null ) return null;
{
this.LogInfo( "No UI in parents >", ui );
return null;
}
} }
if ( computeDepth )
{
ComputeUIAncestorDepth();
}
return ui; return ui;
} }
@ -64,7 +79,7 @@ namespace Rokojori
if ( _imageType != null ) if ( _imageType != null )
{ {
this.LogInfo( "Assigning Image Type:", _imageType ); // this.LogInfo( "Assigning Image Type:", _imageType );
_imageType.Assign( this ); _imageType.Assign( this );
} }
} }
@ -76,26 +91,52 @@ namespace Rokojori
MouseEntered += ()=> MouseEntered += ()=>
{ {
AddUISelectorFlag( UISelectorFlag.Hover, hoverID ); AddUISelectorFlag( UISelectorFlag.Hover, hoverID );
this.SetDirty();
}; };
MouseExited += ()=> MouseExited += ()=>
{ {
RemoveUISelectorFlag( UISelectorFlag.Hover, hoverID ); RemoveUISelectorFlag( UISelectorFlag.Hover, hoverID );
this.SetDirty();
}; };
UpdateImageType(); UpdateImageType();
ComputeUIAncestorDepth();
} }
public override void _EnterTree() public override void _EnterTree()
{ {
UpdateImageType(); UpdateImageType();
ComputeUIAncestorDepth();
}
public override void _ExitTree()
{
_uiAncestorDepth = -1;
} }
public void OnAssemblyReloaded() public void OnAssemblyReloaded()
{ {
UpdateImageType(); UpdateImageType();
} }
int _uiAncestorDepth;
public void ComputeUIAncestorDepth()
{
SetUIAncestorDepth( NodesWalker.Get().GetAncestorDistance( this, GetUI( false ) ) );
}
public void SetUIAncestorDepth( int depth )
{
_uiAncestorDepth = depth;
}
public int GetUIAncestorDepth()
{
return _uiAncestorDepth;
}
void ResetImageType() void ResetImageType()
{ {
@ -129,12 +170,23 @@ namespace Rokojori
} }
else else
{ {
_selectorFlagReferenceCounter.Remove( flag ); _selectorFlagReferenceCounter.Remove( flag, reference );
} }
var numFlagsBefore = _selectorFlags.Count;
_selectorFlags = _selectorFlagReferenceCounter.Keys.ToList(); _selectorFlags = _selectorFlagReferenceCounter.Keys.ToList();
var changed = numFlagsBefore != _selectorFlags.Count;
UISelector.UpdateParentUISelectorFlags( this ); UISelector.UpdateParentUISelectorFlags( this );
if ( changed )
{
// this.LogInfo( "Changed flag:", flag, reference );
this.SetDirty();
}
} }
List<UISelectorFlag> _selectorFlags = []; List<UISelectorFlag> _selectorFlags = [];
@ -444,6 +496,90 @@ namespace Rokojori
case UIStyleNumberProperty.ScaleY: { scaleY = number; } break; case UIStyleNumberProperty.ScaleY: { scaleY = number; } break;
} }
this.SetLayoutDirtyFlag();
}
bool _isAnimated = false;
int _isLayoutDirty = 3;
public void ResetDirtyFlags()
{
_isAnimated = false;
_isLayoutDirty = Mathf.Max( 0, _isLayoutDirty - 1 );
}
public void SetAnimatedFlag()
{
_isAnimated = true;
this.SetDirty();
}
public void SetLayoutDirtyFlag()
{
_isLayoutDirty = 3;
this.SetDirty();
}
public bool IsDirty()
{
return _isAnimated || _isLayoutDirty != 0 || this.HasActiveTransitions();
}
public void Update()
{
if ( Texture == null )
{
Size = new Vector2( 0, 0 );
return;
}
var tw = Texture.GetWidth();
var th = Texture.GetHeight();
var w = UINumber.Compute( this, UIStyleNumberProperty.Width, tw, tw / 100f );
var h = UINumber.Compute( this, UIStyleNumberProperty.Height, th, th / 100f );
Size = new Vector2( w, h );
if ( Material == null )
{
return;
}
var ui = GetUI();
if ( ui == null || ui.settings == null || ui.settings.sizePropertyName == null )
{
return;
}
ui.settings.sizePropertyName.Set( Material, Size );
var colorProperties = imageType != null ? imageType.GetColorShaderProperties() : [];
var colorPropertyName = new ColorPropertyName();
foreach ( var c in colorProperties )
{
var color = UIColor.Compute( this, UIStyleColorProperty.ColorShaderProperty, c, Colors.White );
colorPropertyName.propertyName = c;
colorPropertyName.Set( Material, color );
}
var numberProperties = imageType != null ? imageType.GetNumberShaderProperties() : [];
var numberPropertyName = new FloatPropertyName();
foreach ( var n in numberProperties )
{
var value = UINumber.Compute( this, UIStyleNumberProperty.FloatShaderProperty, n );
numberPropertyName.propertyName = n;
numberPropertyName.Set( Material, value );
}
} }
public UIColor GetUIStyleColorProperty( UIStyleColorProperty property, string shaderPropertyName, UIStylePropertyContainer source ) public UIColor GetUIStyleColorProperty( UIStyleColorProperty property, string shaderPropertyName, UIStylePropertyContainer source )

View File

@ -7,7 +7,7 @@ namespace Rokojori
{ {
[Tool] [Tool]
[GlobalClass,Icon("res://addons/rokojori_action_library/Icons/UIRegion.svg")] [GlobalClass,Icon("res://addons/rokojori_action_library/Icons/UIRegion.svg")]
public partial class UIRegion : Control, UIStylePropertyContainer, UIHolderControl public partial class UIRegion : Control, UIStylePropertyContainerNode, UIHolderControl
{ {
[Export] [Export]
public UIStyle parentStyle; public UIStyle parentStyle;
@ -256,8 +256,37 @@ namespace Rokojori
} }
this.SetLayoutDirtyFlag();
} }
bool _isAnimated = false;
int _isLayoutDirty = 3;
public void ResetDirtyFlags()
{
_isAnimated = false;
_isLayoutDirty = Mathf.Max( 0, _isLayoutDirty - 1 );
}
public void SetAnimatedFlag()
{
_isAnimated = true;
this.SetDirty();
}
public void SetLayoutDirtyFlag()
{
_isLayoutDirty = 3;
this.SetDirty();
}
public bool IsDirty()
{
return _isAnimated || _isLayoutDirty != 0 || this.HasActiveTransitions();
}
public UIColor GetUIStyleColorProperty( UIStyleColorProperty property, string shaderPropertyName, UIStylePropertyContainer source ) public UIColor GetUIStyleColorProperty( UIStyleColorProperty property, string shaderPropertyName, UIStylePropertyContainer source )
{ {
switch ( property ) switch ( property )
@ -277,15 +306,44 @@ namespace Rokojori
MouseEntered += ()=> MouseEntered += ()=>
{ {
AddUISelectorFlag( UISelectorFlag.Hover, hoverID ); AddUISelectorFlag( UISelectorFlag.Hover, hoverID );
this.SetDirty();
}; };
MouseExited += ()=> MouseExited += ()=>
{ {
RemoveUISelectorFlag( UISelectorFlag.Hover, hoverID ); RemoveUISelectorFlag( UISelectorFlag.Hover, hoverID );
this.SetDirty();
}; };
} }
int _uiAncestorDepth;
public void ComputeUIAncestorDepth()
{
SetUIAncestorDepth( NodesWalker.Get().GetAncestorDistance( this, GetUI( false ) ) );
}
public void SetUIAncestorDepth( int depth )
{
_uiAncestorDepth = depth;
}
public int GetUIAncestorDepth()
{
return _uiAncestorDepth;
}
public override void _EnterTree()
{
ComputeUIAncestorDepth();
}
public override void _ExitTree()
{
_uiAncestorDepth = -1;
}
MapList<UISelectorFlag,string> _selectorFlagReferenceCounter = new MapList<UISelectorFlag, string>(); MapList<UISelectorFlag,string> _selectorFlagReferenceCounter = new MapList<UISelectorFlag, string>();
public void AddUISelectorFlag( UISelectorFlag flag, string reference = "" ) public void AddUISelectorFlag( UISelectorFlag flag, string reference = "" )
@ -311,12 +369,20 @@ namespace Rokojori
} }
else else
{ {
_selectorFlagReferenceCounter.Remove( flag ); _selectorFlagReferenceCounter.Remove( flag, reference );
} }
var numFlagsBefore = _selectorFlags.Count;
_selectorFlags = _selectorFlagReferenceCounter.Keys.ToList(); _selectorFlags = _selectorFlagReferenceCounter.Keys.ToList();
var changed = numFlagsBefore != _selectorFlags.Count;
UISelector.UpdateParentUISelectorFlags( this ); UISelector.UpdateParentUISelectorFlags( this );
if ( changed )
{
this.SetDirty();
}
} }
List<UISelectorFlag> _selectorFlags = []; List<UISelectorFlag> _selectorFlags = [];
@ -352,25 +418,37 @@ namespace Rokojori
UI ui; UI ui;
public void SetUI( UI ui ) public void SetUI( UI ui, bool computeDepth = true )
{ {
this.ui = ui; this.ui = ui;
if ( computeDepth )
{
ComputeUIAncestorDepth();
}
} }
public UI GetUI() public UI GetUI( bool computeDepth = true )
{ {
var ui = this.ui != null ? this.ui : Unique<UI>.Get(); if ( this.ui != null )
{
return this.ui;
}
var ui = this.FindParentThatIs<UI>();
if ( ui == null ) if ( ui == null )
{ {
ui = this.FindParentThatIs<UI>();
_uiAncestorDepth =-1;
this.LogInfo( "No UI in parents >", ui );
if ( ui == null ) return null;
{ }
this.LogInfo( "No UI in parents >", ui );
return null; if ( computeDepth )
} {
ComputeUIAncestorDepth();
} }
return ui; return ui;

View File

@ -8,7 +8,7 @@ namespace Rokojori
{ {
[Tool] [Tool]
[GlobalClass,Icon("res://addons/rokojori_action_library/Icons/UIText.svg")] [GlobalClass,Icon("res://addons/rokojori_action_library/Icons/UIText.svg")]
public partial class UIText:Label,UIStylePropertyContainer, iLocalizable, UIHolderControl, IAssemblyReload public partial class UIText:Label,UIStylePropertyContainerNode, iLocalizable, UIHolderControl, IAssemblyReload
{ {
LocalizedString _locale; LocalizedString _locale;
@ -40,6 +40,8 @@ namespace Rokojori
Text = LocalizedString.Get( _locale ); Text = LocalizedString.Get( _locale );
_textDirty = true;
} }
public void OnAssemblyReloaded() public void OnAssemblyReloaded()
@ -69,6 +71,7 @@ namespace Rokojori
set { _font = value; UpdateFont(); } set { _font = value; UpdateFont(); }
} }
[Export] [Export]
public UINumber fontSize; public UINumber fontSize;
[Export] [Export]
@ -155,6 +158,8 @@ namespace Rokojori
{ {
RemoveThemeFontOverride( "font" ); RemoveThemeFontOverride( "font" );
AddThemeFontOverride( "font", resolvedFont ); AddThemeFontOverride( "font", resolvedFont );
_textDirty = true;
} }
} }
@ -168,15 +173,44 @@ namespace Rokojori
MouseEntered += ()=> MouseEntered += ()=>
{ {
AddUISelectorFlag( UISelectorFlag.Hover, hoverID ); AddUISelectorFlag( UISelectorFlag.Hover, hoverID );
this.SetDirty();
}; };
MouseExited += ()=> MouseExited += ()=>
{ {
RemoveUISelectorFlag( UISelectorFlag.Hover, hoverID ); RemoveUISelectorFlag( UISelectorFlag.Hover, hoverID );
this.SetDirty();
}; };
} }
int _uiAncestorDepth;
public void ComputeUIAncestorDepth()
{
SetUIAncestorDepth( NodesWalker.Get().GetAncestorDistance( this, GetUI( false ) ) );
}
public void SetUIAncestorDepth( int depth )
{
_uiAncestorDepth = depth;
}
public int GetUIAncestorDepth()
{
return _uiAncestorDepth;
}
public override void _EnterTree()
{
ComputeUIAncestorDepth();
}
public override void _ExitTree()
{
_uiAncestorDepth = -1;
}
protected override void Dispose( bool disposing) protected override void Dispose( bool disposing)
{ {
_selectorFlagReferenceCounter.Clear(); _selectorFlagReferenceCounter.Clear();
@ -196,18 +230,28 @@ namespace Rokojori
void SetSelectorFlagReference( UISelectorFlag flag, string reference, bool enable ) void SetSelectorFlagReference( UISelectorFlag flag, string reference, bool enable )
{ {
if ( enable ) if ( enable )
{ {
_selectorFlagReferenceCounter.AddIfNotPresent( flag, reference ); _selectorFlagReferenceCounter.AddIfNotPresent( flag, reference );
} }
else else
{ {
_selectorFlagReferenceCounter.Remove( flag ); _selectorFlagReferenceCounter.Remove( flag, reference );;
} }
var numFlagsBefore = _selectorFlags.Count;
_selectorFlags = _selectorFlagReferenceCounter.Keys.ToList(); _selectorFlags = _selectorFlagReferenceCounter.Keys.ToList();
var changed = numFlagsBefore != _selectorFlags.Count;
UISelector.UpdateParentUISelectorFlags( this ); UISelector.UpdateParentUISelectorFlags( this );
if ( changed )
{
this.SetDirty();
}
} }
List<UISelectorFlag> _selectorFlags = []; List<UISelectorFlag> _selectorFlags = [];
@ -254,16 +298,6 @@ namespace Rokojori
} }
// public List<ActiveStyleTransition<UIColor,ColorPropertyName>> GetActiveShaderUIColorTransitions()
// {
// return null;
// }
// public List<ActiveStyleTransition<UINumber,FloatPropertyName>> GetActiveShaderUINumberTransitions()
// {
// return null;
// }
[ExportGroup("Transitions")] [ExportGroup("Transitions")]
[Export] [Export]
public TransitionSettingsAll transitionSettings; public TransitionSettingsAll transitionSettings;
@ -427,11 +461,11 @@ namespace Rokojori
case UIStyleNumberProperty.MarginTop: { marginTop = number; } break; case UIStyleNumberProperty.MarginTop: { marginTop = number; } break;
case UIStyleNumberProperty.MarginBottom: { marginBottom = number; } break; case UIStyleNumberProperty.MarginBottom: { marginBottom = number; } break;
case UIStyleNumberProperty.FontSize: { fontSize = number; } break; case UIStyleNumberProperty.FontSize: { fontSize = number; _textDirty = true; } break;
case UIStyleNumberProperty.FontOutlineSize: { outlineSize = number; } break; case UIStyleNumberProperty.FontOutlineSize: { outlineSize = number; _styleDirty = true; } break;
case UIStyleNumberProperty.FontShadowSize: { shadowSize = number; } break; case UIStyleNumberProperty.FontShadowSize: { shadowSize = number; _styleDirty = true; } break;
case UIStyleNumberProperty.FontShadowOffsetX: { shadowOffsetX = number; } break; case UIStyleNumberProperty.FontShadowOffsetX: { shadowOffsetX = number; _styleDirty = true; } break;
case UIStyleNumberProperty.FontShadowOffsetY: { shadowOffsetY = number; } break; case UIStyleNumberProperty.FontShadowOffsetY: { shadowOffsetY = number; _styleDirty = true; } break;
case UIStyleNumberProperty.PivotX: { pivotX = number; } break; case UIStyleNumberProperty.PivotX: { pivotX = number; } break;
case UIStyleNumberProperty.PivotY: { pivotY = number; } break; case UIStyleNumberProperty.PivotY: { pivotY = number; } break;
@ -441,6 +475,9 @@ namespace Rokojori
case UIStyleNumberProperty.ScaleX: { scaleX = number; } break; case UIStyleNumberProperty.ScaleX: { scaleX = number; } break;
case UIStyleNumberProperty.ScaleY: { scaleY = number; } break; case UIStyleNumberProperty.ScaleY: { scaleY = number; } break;
} }
this.SetLayoutDirtyFlag();
} }
public Vector2 GetUISize() public Vector2 GetUISize()
@ -448,6 +485,207 @@ namespace Rokojori
return GetSize(); return GetSize();
} }
bool _isAnimated = false;
int _isLayoutDirty = 3;
public void ResetDirtyFlags()
{
_isAnimated = false;
_isLayoutDirty = Mathf.Max( 0, _isLayoutDirty - 1 );
}
public void SetAnimatedFlag()
{
_isAnimated = true;
this.SetDirty();
}
public void SetLayoutDirtyFlag()
{
_isLayoutDirty = 3;
this.SetDirty();
}
public bool IsDirty()
{
return _isAnimated || _isLayoutDirty != 0 || this.HasActiveTransitions();
}
bool _styleDirty = false;
bool _textDirty = false;
public class CachedLabelSettings
{
public CachedUINumber fontSize = CachedUINumber.AsInt( UIStyleNumberProperty.FontSize ).SetMin( 1 );
public CachedUINumber outlineSize = CachedUINumber.AsInt( UIStyleNumberProperty.FontOutlineSize );
public CachedUINumber shadowSize = CachedUINumber.AsInt( UIStyleNumberProperty.FontShadowSize );
public CachedUINumber shadowOffsetX = CachedUINumber.AsFloat( UIStyleNumberProperty.FontShadowOffsetX );
public CachedUINumber shadowOffsetY = CachedUINumber.AsFloat( UIStyleNumberProperty.FontShadowOffsetY );
public CachedUIColor fontColor = CachedUIColor.Create( UIStyleColorProperty.FontColor );
public CachedUIColor outlineColor = CachedUIColor.Create( UIStyleColorProperty.FontOutlineColor );
public CachedUIColor shadowColor = CachedUIColor.Create( UIStyleColorProperty.FontShadowColor );
public bool HasChanged()
{
if ( fontSize.changed || outlineSize.changed || shadowSize.changed || fontColor.changed )
{
return true;
}
if ( outlineSize.valueInt > 0 && outlineColor.changed )
{
return true;
}
if ( shadowSize.valueInt > 0 && ( shadowOffsetX.changed || shadowOffsetY.changed || shadowColor.changed ) )
{
return true;
}
return false;
}
bool _wasCreated = false;
public bool wasCreated => _wasCreated;
public LabelSettings CreateLabelSettings()
{
_wasCreated = true;
var l = new LabelSettings();
l.FontSize = fontSize.valueInt;
l.OutlineSize = outlineSize.valueInt;
l.ShadowSize = shadowSize.valueInt;
l.FontColor = fontColor.color;
if ( outlineSize.valueInt > 0 )
{
l.OutlineColor = outlineColor.color;
}
if ( shadowSize.valueInt > 0 )
{
l.ShadowColor = shadowColor.color;
l.ShadowOffset = new Vector2( shadowOffsetX.value, shadowOffsetY.value );
}
return l;
}
}
CachedLabelSettings cachedLabelSettings = new CachedLabelSettings();
public void Update()
{
// FONT SIZE
// VIEW WIDTH/HEIGHT
// PARENT WIDTH/HEIGHT
// PARENT STYLE
// PROP
var ui = GetUI();
var updateTextField = _textDirty || ui.fontSizeChanged || ui.sizeChanged;
if ( ui.fontSizeChanged || ! cachedLabelSettings.wasCreated )
{
cachedLabelSettings.fontSize.alternative = UINumber.em( this );
cachedLabelSettings.fontSize.relative = UINumber.em( this ) / 100f ;
}
cachedLabelSettings.fontSize.Compute( this );
cachedLabelSettings.outlineSize.Compute( this );
cachedLabelSettings.shadowSize.Compute( this );
cachedLabelSettings.fontColor.Compute( this );
if ( cachedLabelSettings.outlineSize.valueInt > 0 )
{
cachedLabelSettings.outlineColor.Compute( this );
}
if ( cachedLabelSettings.shadowSize.valueInt > 0 )
{
cachedLabelSettings.shadowOffsetX.Compute( this );
cachedLabelSettings.shadowOffsetY.Compute( this );
cachedLabelSettings.shadowColor.Compute( this );
}
updateTextField = updateTextField || cachedLabelSettings.fontSize.changed;
if ( cachedLabelSettings.HasChanged() || ! cachedLabelSettings.wasCreated )
{
uiTextLabelSettings = cachedLabelSettings.CreateLabelSettings();
}
// uiTextLabelSettings.FontSize = Mathf.Max( 1,
// UINumber.ComputeInt( this, UIStyleNumberProperty.FontSize, UINumber.em( this ), UINumber.em( this ) / 100f ) );
// uiTextLabelSettings.OutlineSize =
// UINumber.ComputeInt( this, UIStyleNumberProperty.FontOutlineSize, 0 );
// uiTextLabelSettings.ShadowSize =
// UINumber.ComputeInt( this, UIStyleNumberProperty.FontShadowSize, 0 );
// uiTextLabelSettings.ShadowOffset = new Vector2(
// UINumber.Compute( this, UIStyleNumberProperty.FontShadowOffsetX, 0 ),
// UINumber.Compute( this, UIStyleNumberProperty.FontShadowOffsetY, 0 )
// );
// uiTextLabelSettings.FontColor =
// UIColor.Compute( this, UIStyleColorProperty.FontColor, "", Colors.White );
// uiTextLabelSettings.OutlineColor =
// UIColor.Compute( this, UIStyleColorProperty.FontOutlineColor, "", Colors.Transparent );
// uiTextLabelSettings.ShadowColor =
// UIColor.Compute( this, UIStyleColorProperty.FontShadowColor, "", Colors.Black );
if ( ! updateTextField )
{
return;
}
UpdateMinimumSize();
if ( alwaysMinimumSize )
{
if ( AutowrapMode == TextServer.AutowrapMode.Word )
{
AutowrapMode = TextServer.AutowrapMode.Off;
var minSize = GetMinimumSize();
AutowrapMode = TextServer.AutowrapMode.Word;
var w = UINumber.Compute( this, UIStyleNumberProperty.Width, minSize.X, minSize.X / 100f );
var h = UINumber.Compute( this, UIStyleNumberProperty.Height, minSize.Y, minSize.Y / 100f );
CustomMinimumSize = new Vector2( Mathf.Min( minSize.X, w ), 0 );
}
Size = GetMinimumSize();
}
else
{
var minSize = GetMinimumSize();
var w = UINumber.Compute( this, UIStyleNumberProperty.Width, minSize.X, minSize.X / 100f );
var h = UINumber.Compute( this, UIStyleNumberProperty.Height, minSize.Y, minSize.Y / 100f );
// RJLog.Log( "Set Image Size", w, h );
Size = new Vector2( w, h );
}
}
public UIColor GetUIStyleColorProperty( UIStyleColorProperty property, string shaderPropertyName, UIStylePropertyContainer source ) public UIColor GetUIStyleColorProperty( UIStyleColorProperty property, string shaderPropertyName, UIStylePropertyContainer source )
{ {
switch ( property ) switch ( property )
@ -462,25 +700,36 @@ namespace Rokojori
UI ui; UI ui;
public void SetUI( UI ui ) public void SetUI( UI ui,bool computeDepth = true )
{ {
this.ui = ui; this.ui = ui;
if ( computeDepth )
{
ComputeUIAncestorDepth();
}
} }
public UI GetUI() public UI GetUI( bool computeDepth = true )
{ {
var ui = this.ui != null ? this.ui : Unique<UI>.Get(); if ( this.ui != null )
{
return this.ui;
}
var ui = this.FindParentThatIs<UI>();
if ( ui == null ) if ( ui == null )
{ {
ui = this.FindParentThatIs<UI>(); _uiAncestorDepth = -1;
// this.LogInfo( "No UI in parents >", HierarchyName.Of( this ) );
if ( ui == null ) return null;
{ }
// this.LogInfo( "No UI in parents >", HierarchyName.Of( this ) );
return null; if ( computeDepth )
} {
ComputeUIAncestorDepth();
} }
return ui; return ui;

View File

@ -0,0 +1,38 @@
using Godot;
using System;
namespace Rokojori
{
public class CachedUIColor
{
public UIStyleColorProperty property;
public string shaderPropertyName;
public bool changed;
public Color defaultColor = Colors.White;
public Color color;
public static CachedUIColor Create( UIStyleColorProperty colorProperty, string shaderPropertyName = "" )
{
var c = new CachedUIColor();
c.property = colorProperty;
c.shaderPropertyName = shaderPropertyName;
c.defaultColor = Colors.White;
return c;
}
public void Compute( Control control )
{
var nextValue = UIColor.Compute( control, property, shaderPropertyName, defaultColor );
changed = color != nextValue;
if ( changed )
{
color = nextValue;
}
}
}
}

View File

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

View File

@ -0,0 +1,85 @@
using Godot;
using System;
namespace Rokojori
{
public class CachedUINumber
{
public UIStyleNumberProperty property;
public string shaderPropertyName;
public bool isInt = false;
public float value = 0;
public int valueInt = 0;
public bool changed = false;
public int minInt = -1000000;
public int maxInt = 1000000;
public CachedUINumber SetMin( int min )
{
minInt = min;
return this;
}
public float alternative;
public float relative;
public static CachedUINumber AsFloat( UIStyleNumberProperty numberProperty, string shaderPropertyName = "" )
{
var n = new CachedUINumber();
n.property = numberProperty;
n.shaderPropertyName = shaderPropertyName;
n.alternative = 0;
return n;
}
public static CachedUINumber AsInt( UIStyleNumberProperty numberProperty, string shaderPropertyName = "" )
{
var n = new CachedUINumber();
n.property = numberProperty;
n.shaderPropertyName = shaderPropertyName;
n.alternative = 0;
n.isInt = true;
return n;
}
public static CachedUINumber AsInt( string shaderPropertyName )
{
return AsInt( UIStyleNumberProperty.FloatShaderProperty, shaderPropertyName );
}
public void Compute( Control control )
{
var nextValue = UINumber.Compute( control, property, shaderPropertyName, alternative, relative );
if ( isInt )
{
var nextInt = Mathf.Max( minInt, Mathf.RoundToInt( nextValue ) );
changed = nextInt != valueInt;
if ( changed )
{
valueInt = nextInt;
}
}
else
{
changed = value != nextValue;
if ( changed )
{
value = nextValue;
}
}
}
}
}

View File

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

View File

@ -39,10 +39,16 @@ namespace Rokojori
public static Color Compute( Control control, UIStyleColorProperty property, string shaderPropertyName, Color defaultColor ) public static Color Compute( Control control, UIStyleColorProperty property, string shaderPropertyName, Color defaultColor )
{ {
var container = control as UIStylePropertyContainer; var container = control as UIStylePropertyContainerNode;
// Get selected ui color // Get selected ui color
var uiColor = UIStyle.GetUIColorProperty( container, property, shaderPropertyName, container ); var uiColor = UIStyle.GetUIColorProperty( container, property, shaderPropertyName, container );
if ( uiColor != null && uiColor.isAnimated )
{
container.SetAnimatedFlag();
}
var computedColor = Compute( control, uiColor, defaultColor ); var computedColor = Compute( control, uiColor, defaultColor );
var transition = UIStyle.GetTransition( container, property, shaderPropertyName ); var transition = UIStyle.GetTransition( container, property, shaderPropertyName );

View File

@ -1,7 +1,9 @@
using Godot; using Godot;
using Rokojori; using Rokojori;
using System.Collections.Generic;
using System.Linq;
namespace Rokojori namespace Rokojori
{ {
@ -179,12 +181,17 @@ namespace Rokojori
public static float Compute( Control control, UIStyleNumberProperty property, string shaderPropertyName = "", float alternative = 0, float relative = 100 ) public static float Compute( Control control, UIStyleNumberProperty property, string shaderPropertyName = "", float alternative = 0, float relative = 100 )
{ {
var container = control as UIStylePropertyContainer; var container = control as UIStylePropertyContainerNode;
// Get selected ui number // Get selected ui number
var uiNumber = UIStyle.GetUINumberProperty( control as UIStylePropertyContainer, property, shaderPropertyName, container ); var uiNumber = UIStyle.GetUINumberProperty( container, property, shaderPropertyName, container );
var computedNumber = Compute( control, uiNumber, alternative, relative ); var computedNumber = Compute( control, uiNumber, alternative, relative );
if ( uiNumber != null && uiNumber.isAnimated )
{
container.SetAnimatedFlag();
}
var transition = UIStyle.GetTransition( container, property, shaderPropertyName ); var transition = UIStyle.GetTransition( container, property, shaderPropertyName );
var transitionAll = UIStyle.GetTransitionSettingsAll( container ); var transitionAll = UIStyle.GetTransitionSettingsAll( container );
@ -345,7 +352,7 @@ namespace Rokojori
public static float Compute( Control control, UINumber number, float width, float height, float relative ) public static float Compute( Control control, UINumber number, float width, float height, float relative )
{ {
var value = ComputeWithoutAnimation( control, number, width, height, relative ); var value = ComputeFormulaValue( control, number, width, height, relative );
if ( ! number.isAnimated || number.animationCurve == null ) if ( ! number.isAnimated || number.animationCurve == null )
{ {
@ -375,7 +382,42 @@ namespace Rokojori
"value" "value"
}; };
static float ComputeWithoutAnimation( Control control, UINumber number, float width, float height, float relative ) static MapList<string,float[]> cached = new MapList<string, float[]>();
class CachedExpressionData
{
public string formula;
public Godot.Collections.Array inputs;
public float result;
public bool Matches( UINumber number, Godot.Collections.Array inputs )
{
if ( number.unit != formula )
{
return false;
}
for ( int i = 0; i < inputs.Count; i++ )
{
if ( (float)inputs.ElementAt( i ) != (float)this.inputs.ElementAt( i ) )
{
return false;
}
}
return true;
}
}
static List<CachedExpressionData> cachedExpressions = new List<CachedExpressionData>();
static int maxCachedExpressions = 50;
static int GetCacheIndex( UINumber number, Godot.Collections.Array inputs )
{
return cachedExpressions.FindIndex( c => c.Matches( number, inputs ) );
}
static float ComputeFormulaValue( Control control, UINumber number, float width, float height, float relative )
{ {
if ( number == null ) if ( number == null )
{ {
@ -387,9 +429,7 @@ namespace Rokojori
case "em": case "em":
{ {
return number.value * em( control ); return number.value * em( control );
} }
case "vw": case "vw":
{ {
@ -407,6 +447,12 @@ namespace Rokojori
return number.value / 100f * ( parent == null ? width : parent.Size.X ); return number.value / 100f * ( parent == null ? width : parent.Size.X );
} }
case "ph":
{
var parent = control.GetParent() as Control;
return number.value / 100f * ( parent == null ? height : parent.Size.Y );
}
case "cw": case "cw":
{ {
var parent = control.GetParent() as Control; var parent = control.GetParent() as Control;
@ -442,11 +488,7 @@ namespace Rokojori
} }
case "ph":
{
var parent = control.GetParent() as Control;
return number.value / 100f * ( parent == null ? height : parent.Size.Y );
}
case "": case "":
{ {
@ -459,10 +501,29 @@ namespace Rokojori
} }
} }
var parentControl = control.GetParent() as Control;;
var inputs = GetInputs( control, number, parentControl, width, height, relative );
var cacheIndex = GetCacheIndex( number, inputs );
if ( cacheIndex != -1 )
{
var cachedResult = cachedExpressions[ cacheIndex ].result;
cachedExpressions.SwapTowardsBegin( cacheIndex );
// control.LogInfo( "Using cached value", cachedExpressions[ cacheIndex ].formula, ">", cachedResult );
return cachedResult;
}
var expression = new Expression(); var expression = new Expression();
var expressionText = number.unit == null ? "" : RegexUtility.Replace( number.unit, "%", " * relative " ); var expressionText = number.unit == null ? "" : RegexUtility.Replace( number.unit, "%", " * relative " );
expressionText = RegexUtility.Replace( expressionText, @"\b(\d+)\s*(em|v[wh]|p[wh]|c[wh]|c[xy]|ui[wh])\b", "$1*$2" );
if ( ! IsValid( expressionText ) ) if ( ! IsValid( expressionText ) )
{ {
return 0; return 0;
@ -475,9 +536,41 @@ namespace Rokojori
return 0; return 0;
} }
var parentControl = control.GetParent() as Control;;
var scale = number.unit.IndexOf( "value" ) == -1 ? number.value : 1;
var inputs = new Godot.Collections.Array(); var result = (float) ( scale * expression.Execute( inputs ).AsDouble() );
Cache( number.unit, inputs, result );
return result;
}
static void Cache( string formula, Godot.Collections.Array inputs, float result )
{
CachedExpressionData data = null;
if ( cachedExpressions.Count < maxCachedExpressions )
{
data = new CachedExpressionData();
cachedExpressions.Add( data );
}
else
{
data = GodotRandom.Get().From( cachedExpressions, 4 * maxCachedExpressions / 5, maxCachedExpressions - 1 );
}
data.formula = formula;
data.inputs = inputs;
data.result = result;
}
static Godot.Collections.Array GetInputs( Control control, UINumber number, Control parentControl, float width, float height, float relative )
{
var inputs = new Godot.Collections.Array();
// em // em
inputs.Add( em( control ) ); inputs.Add( em( control ) );
@ -491,7 +584,7 @@ namespace Rokojori
// cw, ch // cw, ch
inputs.Add( ( parentControl == null ? width : UILayouting.GetContentSize( parentControl ).X ) / 100f ); inputs.Add( ( parentControl == null ? width : UILayouting.GetContentSize( parentControl ).X ) / 100f );
inputs.Add( ( parentControl == null ? width : UILayouting.GetContentSize( parentControl ).Y ) / 100f ); inputs.Add( ( parentControl == null ? height : UILayouting.GetContentSize( parentControl ).Y ) / 100f );
// cx, cy // cx, cy
inputs.Add( ( parentControl == null ? 0 : UILayouting.GetContentOffset( parentControl ).X ) / 100f ); inputs.Add( ( parentControl == null ? 0 : UILayouting.GetContentOffset( parentControl ).X ) / 100f );
@ -504,16 +597,10 @@ namespace Rokojori
// "relative" // "relative"
inputs.Add( relative / 100f ); inputs.Add( relative / 100f );
// value // value
if ( number.unit.IndexOf( "value" ) == -1 )
{
inputs.Add( 0 );
return number.value * (float) expression.Execute( inputs ).AsDouble() ;
}
inputs.Add( number.value ); inputs.Add( number.value );
return (float) expression.Execute( inputs ).AsDouble() ; return inputs;
} }
static bool IsValid( string expressionText ) static bool IsValid( string expressionText )

View File

@ -15,9 +15,9 @@ namespace Rokojori
{ {
___, ___,
True, True,
False, False
True_For_Any_Parent, // True_For_Any_Parent,
False_For_All_Parents // False_For_All_Parents
} }
[Export] [Export]
@ -51,10 +51,10 @@ namespace Rokojori
return container.GetUISelectorFlags().Contains( flag ) == ( Value.True == value ); return container.GetUISelectorFlags().Contains( flag ) == ( Value.True == value );
} }
if ( Value.True_For_Any_Parent == value || Value.False_For_All_Parents == value ) // if ( Value.True_For_Any_Parent == value || Value.False_For_All_Parents == value )
{ // {
return container.GetParentUISelectorFlags().Contains( flag ) == ( Value.True_For_Any_Parent == value ); // return container.GetParentUISelectorFlags().Contains( flag ) == ( Value.True_For_Any_Parent == value );
} // }
return true; return true;
@ -101,8 +101,13 @@ namespace Rokojori
} }
public static void UpdateParentUISelectorFlags( UIStylePropertyContainer target ) public static void UpdateParentUISelectorFlags( UIStylePropertyContainerNode target )
{ {
if ( target != null )
{
return;
}
var node = target as Node; var node = target as Node;
var walker = NodesWalker.Get(); var walker = NodesWalker.Get();
@ -111,7 +116,7 @@ namespace Rokojori
walker.PruneChildTraversal( node, walker.PruneChildTraversal( node,
( Node n ) => ( Node n ) =>
{ {
if ( n != node && n is UIStylePropertyContainer c ) if ( n != node && n is UIStylePropertyContainerNode c )
{ {
UpdateParentUISelectorFlags( c ); UpdateParentUISelectorFlags( c );
return false; return false;
@ -125,7 +130,7 @@ namespace Rokojori
} }
static void CombineParentFlags( UIStylePropertyContainer target ) static void CombineParentFlags( UIStylePropertyContainerNode target )
{ {
var parentFlags = target.GetParentUISelectorFlags(); var parentFlags = target.GetParentUISelectorFlags();
parentFlags.Clear(); parentFlags.Clear();
@ -137,6 +142,9 @@ namespace Rokojori
{ {
parentFlags.Union( parent.GetParentUISelectorFlags() ); parentFlags.Union( parent.GetParentUISelectorFlags() );
} }
target.SetDirty();
} }

View File

@ -40,6 +40,76 @@ namespace Rokojori
void AddUISelectorFlag( UISelectorFlag flag, string reference = "" ); void AddUISelectorFlag( UISelectorFlag flag, string reference = "" );
void RemoveUISelectorFlag( UISelectorFlag flag, string reference = "" ); void RemoveUISelectorFlag( UISelectorFlag flag, string reference = "" );
} }
public interface UIStylePropertyContainerNode:UIStylePropertyContainer
{
public int GetUIAncestorDepth();
public void ResetDirtyFlags();
public void SetAnimatedFlag();
public void SetLayoutDirtyFlag();
public bool IsDirty();
}
public static class UIStylePropertyContainers
{
public static void SetDirty( this UIStylePropertyContainerNode container )
{
if ( ! ( container is UIHolderControl ) )
{
return;
}
var control = container as UIHolderControl;
var ui = control.GetUI();
if ( ui == null )
{
return;
}
ui.SetDirty( container );
}
public static void CommitUpdateInfo( this UIStylePropertyContainerNode container )
{
if ( ! ( container is UIHolderControl ) )
{
return;
}
var control = container as UIHolderControl;
var ui = control.GetUI();
if ( ui == null )
{
return;
}
ui.SetUpdated( container );
}
public static bool HasActiveTransitions( this UIStylePropertyContainer container )
{
var animatedNumber = container.GetActiveUINumberTransitions().Find( n => n != null && n.transitioning );
if ( animatedNumber != null )
{
return true;
}
var animatedColor = container.GetActiveUIColorTransitions().Find( n => n != null && n.transitioning );
if ( animatedColor != null )
{
return true;
}
return false;
}
}
} }

View File

@ -20,6 +20,7 @@ namespace Rokojori
public enum UpdateMode public enum UpdateMode
{ {
Always, Always,
Optimized,
Only_Manual_Updates Only_Manual_Updates
} }
[Export] [Export]
@ -38,9 +39,7 @@ namespace Rokojori
[ExportGroup("Read Only")] [ExportGroup("Read Only")]
[Export] [Export]
public float X_computedFontSizePixels = 1; public float X_computedFontSizePixels = 1;
List<ICustomDisposer> _customDisposers = []; List<ICustomDisposer> _customDisposers = [];
@ -57,6 +56,7 @@ namespace Rokojori
[Export] [Export]
public string[] customDisposerIDs = []; public string[] customDisposerIDs = [];
public void MakeStopToPass() public void MakeStopToPass()
{ {
@ -96,6 +96,8 @@ namespace Rokojori
return UIHolder.GetUI( c ); return UIHolder.GetUI( c );
} }
public static UIStylePropertyContainer GetStylePropertyContainerParent( Control c ) public static UIStylePropertyContainer GetStylePropertyContainerParent( Control c )
{ {
var it = c as Node; var it = c as Node;
@ -144,12 +146,30 @@ namespace Rokojori
return ui.settings.defaultTimeline; return ui.settings.defaultTimeline;
} }
Vector2 windowSize = new Vector2();
bool _resizeFlag = false;
bool _fontSizeFlag = false;
public bool sizeChanged => _resizeFlag;
public bool fontSizeChanged => _fontSizeFlag;
public override void _Process( double delta ) public override void _Process( double delta )
{ {
if ( settings == null ) if ( settings == null )
{ {
return; return;
} }
_resizeFlag = false;
_fontSizeFlag = false;
var newWindowSize = GetWindowSize();
if ( windowSize != newWindowSize )
{
_resizeFlag = true;
}
if ( useParentSize ) if ( useParentSize )
{ {
@ -158,12 +178,9 @@ namespace Rokojori
if ( parentSize != cachedSize ) if ( parentSize != cachedSize )
{ {
Size = parentSize; Size = parentSize;
cachedSize = parentSize; cachedSize = parentSize;
_resizeFlag = true;
// this.LogInfo( "Size Changed" );
} }
} }
@ -187,14 +204,7 @@ namespace Rokojori
public override void _Input( InputEvent ie ) public override void _Input( InputEvent ie )
{ {
onInputEvent.DispatchEvent( ie ); onInputEvent.DispatchEvent( ie );
} }
List<UIHoverable> hoveredControls = new List<UIHoverable>();
public void SetHovered( UIHoverable control )
{
hoveredControls.Add( control );
}
public void BindOwnChildren() public void BindOwnChildren()
{ {
@ -244,14 +254,113 @@ namespace Rokojori
} }
} }
HashSet<UIStylePropertyContainerNode> _dirty = new HashSet<UIStylePropertyContainerNode>();
HashSet<UIStylePropertyContainerNode> _updated = new HashSet<UIStylePropertyContainerNode>();
public void SetDirty( UIStylePropertyContainerNode control )
{
_dirty.Add( control );
}
public void SetUpdated( UIStylePropertyContainerNode control )
{
_updated.Add( control );
}
void UpdateUIElements() void UpdateUIElements()
{ {
if ( UpdateMode.Always != updateMode ) if ( UpdateMode.Always == updateMode )
{ {
return; UpdateAllUIRegions();
}
else if ( UpdateMode.Optimized == updateMode )
{
if ( _fontSizeFlag || _resizeFlag )
{
_dirty.Clear();
UpdateAllUIRegions();
}
else
{
UpdateUIElementsOptimized();
}
}
}
float time = 0;
void UpdateUIElementsOptimized()
{
var timeNow = TimeLine.osTime;
var elapsed = timeNow - time;
time = timeNow;
// this.LogInfo( Mathf.RoundToInt( elapsed * 1000f ) );
var parent = GetParent();
var sorted = new List<UIStylePropertyContainerNode>( [ .. _dirty ]);
if ( sorted.Count > 0 )
{
// this.LogInfo( "Updating:", sorted.Count );
} }
UpdateAllUIRegions(); _updated.Clear();
sorted.Sort(
( a, b ) =>
{
return Mathf.RoundToInt( Mathf.Sign( a.GetUIAncestorDepth() - b.GetUIAncestorDepth() ) );
}
);
sorted.ForEach(
( s )=>
{
if ( _updated.Contains( s ) )
{
return;
}
// ( s as Control).LogInfo( "Updating:", s );
UpdateElement( s );
}
);
_updated.Clear();
_dirty.RemoveWhere( d => ! d.IsDirty() );
foreach ( var d in _dirty )
{
d.ResetDirtyFlags();
}
}
void UpdateElement( UIStylePropertyContainerNode control )
{
if ( control is UIRegion region )
{
region.Layout();
}
else
{
UILayouting.UpdateChild( control as Control );
if ( UIStyle.Position( control ) == UIPosition.From_Layout )
{
UILayouting.SetPositionInParentAnchor( control );
}
}
} }
public void UpdateAllUIRegions() public void UpdateAllUIRegions()
@ -282,6 +391,21 @@ namespace Rokojori
return control.GetWindow().Size.Y; return control.GetWindow().Size.Y;
} }
} }
public Vector2 GetWindowSize()
{
if ( Engine.IsEditorHint() )
{
var width = ProjectSettings.GetSetting( "display/window/size/viewport_width" ).AsInt32();
var height = ProjectSettings.GetSetting( "display/window/size/viewport_height" ).AsInt32();
return new Vector2( width, height );
}
else
{
return GetWindow().Size;
}
}
} }

61
Tools/Git/Git.cs Normal file
View File

@ -0,0 +1,61 @@
#if TOOLS
using Godot;
using Rokojori;
using System.Diagnostics;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Rokojori.Tools
{
public class GitResponse
{
public string rawResponse;
public int exitCode;
}
public class Git
{
public static async Task<GitResponse> GetStatus( string path )
{
var process = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = "git",
Arguments = "status",
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
CreateNoWindow = true,
WorkingDirectory = path
}
};
process.Start();
var outputTask = process.StandardOutput.ReadToEndAsync();
var errorTask = process.StandardError.ReadToEndAsync();
await Task.WhenAll( outputTask, errorTask );
await process.WaitForExitAsync();
var response = new GitResponse();
response.exitCode = process.ExitCode;
if ( process.ExitCode == 0 )
{
response.rawResponse = outputTask.Result;
}
else
{
response.rawResponse = errorTask.Result;
}
return response;
}
}
}
#endif

1
Tools/Git/Git.cs.uid Normal file
View File

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

30
Tools/Git/GitTest.cs Normal file
View File

@ -0,0 +1,30 @@
#if TOOLS
using Godot;
using Rokojori;
using System.Diagnostics;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Rokojori.Tools
{
[Tool]
[GlobalClass]
public partial class GitTest:Node
{
[ExportToolButton("Status")]
public Callable StatusButton => Callable.From(
()=>
{
GetStatus();
}
);
async void GetStatus()
{
var response = await Git.GetStatus( ProjectSettings.GlobalizePath( "res://") );
this.LogInfo( response.exitCode, ">>", response.rawResponse );
}
}
}
#endif

1
Tools/Git/GitTest.cs.uid Normal file
View File

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

View File

@ -83,7 +83,7 @@ metadata/_custom_type_script = "uid://cnkyynboxg1qg"
[sub_resource type="ShaderMaterial" id="ShaderMaterial_btdid"] [sub_resource type="ShaderMaterial" id="ShaderMaterial_btdid"]
shader = ExtResource("7_aeebn") shader = ExtResource("7_aeebn")
shader_parameter/size = Vector2(1156.56, 137.56) shader_parameter/size = Vector2(1134.72, 137.56)
shader_parameter/sharpness = 5.0 shader_parameter/sharpness = 5.0
shader_parameter/borderRadius = 6.048 shader_parameter/borderRadius = 6.048
shader_parameter/strokeSize = 0.0 shader_parameter/strokeSize = 0.0
@ -111,7 +111,7 @@ fill_to = Vector2(0.0811966, 0.0811966)
[sub_resource type="Resource" id="Resource_pyi7r"] [sub_resource type="Resource" id="Resource_pyi7r"]
script = ExtResource("5_1tota") script = ExtResource("5_1tota")
value = 1.0 value = 1.0
unit = "100 * pw - 2*1.5em" unit = "100 pw - 2*1.5em"
isAnimated = false isAnimated = false
animationDuration = 0.0 animationDuration = 0.0
animationOffset = 0.0 animationOffset = 0.0
@ -566,10 +566,7 @@ number = SubResource("Resource_fcuvy")
[sub_resource type="LabelSettings" id="LabelSettings_x3h2c"] [sub_resource type="LabelSettings" id="LabelSettings_x3h2c"]
font_size = 9 font_size = 9
font_color = Color(1, 0.467117, 0.467117, 1) font_color = Color(1, 0.467117, 0.467117, 1)
outline_color = Color(1, 1, 1, 0)
shadow_size = 0 shadow_size = 0
shadow_color = Color(0, 0, 0, 1)
shadow_offset = Vector2(0, 0)
[sub_resource type="Resource" id="Resource_uulg6"] [sub_resource type="Resource" id="Resource_uulg6"]
script = ExtResource("17_illef") script = ExtResource("17_illef")
@ -607,7 +604,7 @@ fill = 1
fill_from = Vector2(0.5, 0.5) fill_from = Vector2(0.5, 0.5)
fill_to = Vector2(0.5, 0) fill_to = Vector2(0.5, 0)
[sub_resource type="LabelSettings" id="LabelSettings_qjby8"] [sub_resource type="LabelSettings" id="LabelSettings_1jemv"]
[sub_resource type="Resource" id="Resource_jm3cb"] [sub_resource type="Resource" id="Resource_jm3cb"]
script = ExtResource("17_illef") script = ExtResource("17_illef")
@ -616,21 +613,15 @@ entries = []
context = "" context = ""
metadata/_custom_type_script = "uid://bvj322mokkq63" metadata/_custom_type_script = "uid://bvj322mokkq63"
[sub_resource type="LabelSettings" id="LabelSettings_1jemv"] [sub_resource type="LabelSettings" id="LabelSettings_1hp7s"]
font_size = 9 font_size = 9
font_color = Color(0.75201, 0.831706, 0.90732, 1) font_color = Color(0.75201, 0.831706, 0.90732, 1)
outline_color = Color(1, 1, 1, 0)
shadow_size = 0 shadow_size = 0
shadow_color = Color(0, 0, 0, 1)
shadow_offset = Vector2(0, 0)
[sub_resource type="LabelSettings" id="LabelSettings_1hp7s"] [sub_resource type="LabelSettings" id="LabelSettings_nro64"]
font_size = 17 font_size = 17
font_color = Color(1, 1, 1, 0.843137) font_color = Color(1, 1, 1, 0.843137)
outline_color = Color(1, 1, 1, 0)
shadow_size = 0 shadow_size = 0
shadow_color = Color(0, 0, 0, 1)
shadow_offset = Vector2(0, 0)
[sub_resource type="Resource" id="Resource_jn787"] [sub_resource type="Resource" id="Resource_jn787"]
script = ExtResource("17_illef") script = ExtResource("17_illef")
@ -639,13 +630,10 @@ entries = []
context = "" context = ""
metadata/_custom_type_script = "uid://bvj322mokkq63" metadata/_custom_type_script = "uid://bvj322mokkq63"
[sub_resource type="LabelSettings" id="LabelSettings_nro64"] [sub_resource type="LabelSettings" id="LabelSettings_0e03u"]
font_size = 14 font_size = 14
font_color = Color(0.2226, 0.710943, 0.914108, 1) font_color = Color(0.2226, 0.710943, 0.914108, 1)
outline_color = Color(1, 1, 1, 0)
shadow_size = 0 shadow_size = 0
shadow_color = Color(0, 0, 0, 1)
shadow_offset = Vector2(0, 0)
[sub_resource type="Resource" id="Resource_7rt2a"] [sub_resource type="Resource" id="Resource_7rt2a"]
script = ExtResource("17_illef") script = ExtResource("17_illef")
@ -654,21 +642,15 @@ entries = []
context = "" context = ""
metadata/_custom_type_script = "uid://bvj322mokkq63" metadata/_custom_type_script = "uid://bvj322mokkq63"
[sub_resource type="LabelSettings" id="LabelSettings_0e03u"]
font_size = 14
font_color = Color(0.289366, 0.771546, 0.496309, 1)
outline_color = Color(1, 1, 1, 0)
shadow_size = 0
shadow_color = Color(0, 0, 0, 1)
shadow_offset = Vector2(0, 0)
[sub_resource type="LabelSettings" id="LabelSettings_illef"] [sub_resource type="LabelSettings" id="LabelSettings_illef"]
font_size = 14 font_size = 14
font_color = Color(0.914108, 0.8403, 0.2226, 1) font_color = Color(0.289366, 0.771546, 0.496309, 1)
outline_color = Color(1, 1, 1, 0) shadow_size = 0
[sub_resource type="LabelSettings" id="LabelSettings_qjby8"]
font_size = 14
font_color = Color(0.914108, 0.8403, 0.2226, 1)
shadow_size = 0 shadow_size = 0
shadow_color = Color(0, 0, 0, 1)
shadow_offset = Vector2(0, 0)
[sub_resource type="Resource" id="Resource_qjby8"] [sub_resource type="Resource" id="Resource_qjby8"]
script = ExtResource("5_1tota") script = ExtResource("5_1tota")
@ -706,18 +688,18 @@ animationDuration = 0.0
animationOffset = 0.0 animationOffset = 0.0
metadata/_custom_type_script = "uid://cnkyynboxg1qg" metadata/_custom_type_script = "uid://cnkyynboxg1qg"
[sub_resource type="ShaderMaterial" id="ShaderMaterial_qjby8"] [sub_resource type="ShaderMaterial" id="ShaderMaterial_ul0js"]
shader = ExtResource("7_aeebn") shader = ExtResource("7_aeebn")
shader_parameter/size = Vector2(34.5601, 34.56) shader_parameter/size = Vector2(0, 0)
shader_parameter/sharpness = 5.0 shader_parameter/sharpness = 5.0
shader_parameter/borderRadius = 3.46464 shader_parameter/borderRadius = 5.0
shader_parameter/strokeSize = 8.44128 shader_parameter/strokeSize = 5.0
shader_parameter/offset = 3.51648 shader_parameter/offset = 0.0
shader_parameter/fillColor = Color(1, 1, 1, 1) shader_parameter/fillColor = Color(0, 0, 0, 1)
shader_parameter/fillUVTransform = Vector4(0, 0, 0, 0) shader_parameter/fillUVTransform = Vector4(0, 0, 0, 0)
shader_parameter/screenfillMultiplyUVTransform = Vector4(0, 0, 0, 0) shader_parameter/screenfillMultiplyUVTransform = Vector4(0, 0, 0, 0)
shader_parameter/screenfillMultiplyUVMovement = Vector2(0, 0) shader_parameter/screenfillMultiplyUVMovement = Vector2(0, 0)
shader_parameter/strokeColor = Color(1, 1, 1, 1) shader_parameter/strokeColor = Color(0, 0, 0, 1)
shader_parameter/strokeUVTransform = Vector4(0, 0, 0, 0) shader_parameter/strokeUVTransform = Vector4(0, 0, 0, 0)
shader_parameter/screenStrokeMultiplyUVTransform = Vector4(0, 0, 0, 0) shader_parameter/screenStrokeMultiplyUVTransform = Vector4(0, 0, 0, 0)
shader_parameter/screenStrokeMultiplyUVMovment = Vector2(0, 0) shader_parameter/screenStrokeMultiplyUVMovment = Vector2(0, 0)
@ -794,12 +776,7 @@ animationDuration = 0.0
animationOffset = 0.0 animationOffset = 0.0
metadata/_custom_type_script = "uid://cnkyynboxg1qg" metadata/_custom_type_script = "uid://cnkyynboxg1qg"
[sub_resource type="LabelSettings" id="LabelSettings_ul0js"] [sub_resource type="LabelSettings" id="LabelSettings_hj653"]
font_size = 26
outline_color = Color(1, 1, 1, 0)
shadow_size = 0
shadow_color = Color(0, 0, 0, 1)
shadow_offset = Vector2(0, 0)
[sub_resource type="Resource" id="Resource_btdid"] [sub_resource type="Resource" id="Resource_btdid"]
script = ExtResource("5_1tota") script = ExtResource("5_1tota")
@ -882,9 +859,9 @@ nodeLink = NodePath("../Node Link")
[node name="Background" type="TextureRect" parent="."] [node name="Background" type="TextureRect" parent="."]
material = SubResource("ShaderMaterial_btdid") material = SubResource("ShaderMaterial_btdid")
layout_mode = 0 layout_mode = 0
offset_right = 1156.56 offset_right = 1134.72
offset_bottom = 137.56 offset_bottom = 137.56
pivot_offset = Vector2(593.28, 68.78) pivot_offset = Vector2(567.36, 68.78)
texture = SubResource("GradientTexture2D_dmcan") texture = SubResource("GradientTexture2D_dmcan")
expand_mode = 1 expand_mode = 1
script = ExtResource("8_gyhi8") script = ExtResource("8_gyhi8")
@ -994,7 +971,7 @@ pivot_offset = Vector2(11, 7)
mouse_filter = 1 mouse_filter = 1
theme_override_fonts/font = ExtResource("15_nro64") theme_override_fonts/font = ExtResource("15_nro64")
text = "INFO" text = "INFO"
label_settings = SubResource("LabelSettings_qjby8") label_settings = SubResource("LabelSettings_1jemv")
autowrap_mode = 2 autowrap_mode = 2
script = ExtResource("16_0e03u") script = ExtResource("16_0e03u")
locale = SubResource("Resource_jm3cb") locale = SubResource("Resource_jm3cb")
@ -1002,16 +979,17 @@ parentStyle = ExtResource("22_aeebn")
metadata/_custom_type_script = "uid://rqs2m0u6yvvf" metadata/_custom_type_script = "uid://rqs2m0u6yvvf"
[node name="Time Stamp" type="Label" parent="."] [node name="Time Stamp" type="Label" parent="."]
custom_minimum_size = Vector2(1, 0) custom_minimum_size = Vector2(24, 0)
layout_mode = 0 layout_mode = 0
offset_left = 69.0896 offset_left = 69.0896
offset_top = 17.28 offset_top = 17.28
offset_right = 70.0896 offset_right = 93.0896
offset_bottom = 31.28 offset_bottom = 31.28
pivot_offset = Vector2(0.5, 7) pivot_offset = Vector2(12, 7)
mouse_filter = 1 mouse_filter = 1
theme_override_fonts/font = ExtResource("15_nro64") theme_override_fonts/font = ExtResource("15_nro64")
label_settings = SubResource("LabelSettings_1jemv") text = "19:00"
label_settings = SubResource("LabelSettings_1hp7s")
autowrap_mode = 2 autowrap_mode = 2
script = ExtResource("16_0e03u") script = ExtResource("16_0e03u")
disableLocalization = true disableLocalization = true
@ -1029,7 +1007,7 @@ pivot_offset = Vector2(220.5, 13)
mouse_filter = 1 mouse_filter = 1
theme_override_fonts/font = ExtResource("15_nro64") theme_override_fonts/font = ExtResource("15_nro64")
text = "Ein etwas anderer Text! Hello das ist eine Nachricht! Huhe!" text = "Ein etwas anderer Text! Hello das ist eine Nachricht! Huhe!"
label_settings = SubResource("LabelSettings_1hp7s") label_settings = SubResource("LabelSettings_nro64")
autowrap_mode = 2 autowrap_mode = 2
script = ExtResource("16_0e03u") script = ExtResource("16_0e03u")
locale = SubResource("Resource_jn787") locale = SubResource("Resource_jn787")
@ -1048,7 +1026,7 @@ mouse_filter = 1
mouse_default_cursor_shape = 2 mouse_default_cursor_shape = 2
theme_override_fonts/font = ExtResource("15_nro64") theme_override_fonts/font = ExtResource("15_nro64")
text = "Node3D > Static Environment > SomeThing > MyNodes > SomeNode" text = "Node3D > Static Environment > SomeThing > MyNodes > SomeNode"
label_settings = SubResource("LabelSettings_nro64") label_settings = SubResource("LabelSettings_0e03u")
autowrap_mode = 2 autowrap_mode = 2
script = ExtResource("16_0e03u") script = ExtResource("16_0e03u")
locale = SubResource("Resource_7rt2a") locale = SubResource("Resource_7rt2a")
@ -1074,7 +1052,7 @@ mouse_filter = 1
mouse_default_cursor_shape = 2 mouse_default_cursor_shape = 2
theme_override_fonts/font = ExtResource("15_nro64") theme_override_fonts/font = ExtResource("15_nro64")
text = "Node3D > Static Environment > SomeThing > MyNodes > SomeNode" text = "Node3D > Static Environment > SomeThing > MyNodes > SomeNode"
label_settings = SubResource("LabelSettings_0e03u") label_settings = SubResource("LabelSettings_illef")
autowrap_mode = 2 autowrap_mode = 2
script = ExtResource("16_0e03u") script = ExtResource("16_0e03u")
locale = SubResource("Resource_7rt2a") locale = SubResource("Resource_7rt2a")
@ -1100,7 +1078,7 @@ mouse_filter = 1
mouse_default_cursor_shape = 2 mouse_default_cursor_shape = 2
theme_override_fonts/font = ExtResource("15_nro64") theme_override_fonts/font = ExtResource("15_nro64")
text = "Node3D > Static Environment > SomeThing > MyNodes > SomeNode" text = "Node3D > Static Environment > SomeThing > MyNodes > SomeNode"
label_settings = SubResource("LabelSettings_illef") label_settings = SubResource("LabelSettings_qjby8")
autowrap_mode = 2 autowrap_mode = 2
script = ExtResource("16_0e03u") script = ExtResource("16_0e03u")
locale = SubResource("Resource_7rt2a") locale = SubResource("Resource_7rt2a")
@ -1131,7 +1109,7 @@ right = SubResource("Resource_v6jx4")
metadata/_custom_type_script = "uid://c2hicupu28nbi" metadata/_custom_type_script = "uid://c2hicupu28nbi"
[node name="Info Icon2" type="TextureRect" parent="Close Button"] [node name="Info Icon2" type="TextureRect" parent="Close Button"]
material = SubResource("ShaderMaterial_qjby8") material = SubResource("ShaderMaterial_ul0js")
layout_mode = 0 layout_mode = 0
offset_right = 34.5601 offset_right = 34.5601
offset_bottom = 34.56 offset_bottom = 34.56
@ -1157,8 +1135,7 @@ offset_right = 34.5601
offset_bottom = 32.721 offset_bottom = 32.721
mouse_filter = 1 mouse_filter = 1
theme_override_fonts/font = ExtResource("15_nro64") theme_override_fonts/font = ExtResource("15_nro64")
text = "x" label_settings = SubResource("LabelSettings_hj653")
label_settings = SubResource("LabelSettings_ul0js")
horizontal_alignment = 1 horizontal_alignment = 1
vertical_alignment = 1 vertical_alignment = 1
autowrap_mode = 2 autowrap_mode = 2

View File

@ -320,6 +320,7 @@ offset_bottom = 584.0
mouse_filter = 1 mouse_filter = 1
script = ExtResource("1_op0b4") script = ExtResource("1_op0b4")
settings = ExtResource("2_iufyf") settings = ExtResource("2_iufyf")
updateMode = 1
useParentSize = true useParentSize = true
X_computedFontSizePixels = 17.28 X_computedFontSizePixels = 17.28
customDisposerIDs = PackedStringArray("ciOsgmckohhN3Ejw:Messages ▸ UI ▸ Scroller ▸ Vertical Scroller ▸ Button", "9ak1UYtRMpBsDldi:Messages ▸ UI ▸ Scroller") customDisposerIDs = PackedStringArray("ciOsgmckohhN3Ejw:Messages ▸ UI ▸ Scroller ▸ Vertical Scroller ▸ Button", "9ak1UYtRMpBsDldi:Messages ▸ UI ▸ Scroller")