diff --git a/Icons/Help.svg b/Icons/Help.svg new file mode 100644 index 0000000..0d4f6e8 --- /dev/null +++ b/Icons/Help.svg @@ -0,0 +1,52 @@ + + + + + + + + + diff --git a/Icons/Help.svg.import b/Icons/Help.svg.import new file mode 100644 index 0000000..641850e --- /dev/null +++ b/Icons/Help.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://ku3wjdsmv1lh" +path="res://.godot/imported/Help.svg-73996934a1ef8b9c260e47a975f69d9d.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/rokojori_action_library/Icons/Help.svg" +dest_files=["res://.godot/imported/Help.svg-73996934a1ef8b9c260e47a975f69d9d.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/Runtime/Actions/Action.cs b/Runtime/Actions/Action.cs index 55acd15..f36b75f 100644 --- a/Runtime/Actions/Action.cs +++ b/Runtime/Actions/Action.cs @@ -9,6 +9,16 @@ namespace Rokojori [GlobalClass, Icon("res://addons/rokojori_action_library/Icons/Action.svg")] public partial class Action : NetworkNode { + + [ExportToolButton( "(?) Help", Icon = "Help") ] + public Callable openHelpButton => Callable.From( ()=> + { + #if TOOLS + Rokojori.Tools.OnlineDocs.Open( GetType() ); + #endif + } + ); + [ExportToolButton( "Trigger Action in Editor")] public Callable TriggerActionButton => Callable.From( ()=> Trigger() ); diff --git a/Runtime/Files/FilesSync.cs b/Runtime/Files/FilesSync.cs index d58ed1c..db37ede 100644 --- a/Runtime/Files/FilesSync.cs +++ b/Runtime/Files/FilesSync.cs @@ -1,4 +1,5 @@ +using System; using System.Collections; using System.Collections.Generic; @@ -125,6 +126,16 @@ namespace Rokojori return SaveUTF8( path, JSON.StringifyObject( obj ) ); } + public static DateTimeOffset GetModificationTime( string path ) + { + return File.GetLastWriteTimeUtc( path ); + } + + public static ISOTimeStamp GetModificationTimeStamp( string path ) + { + return ISOTimeStamp.FromDate( GetModificationTime( path ) ); + } + public static string LoadUTF8( string path ) { try diff --git a/Runtime/Godot/Nodes.cs b/Runtime/Godot/Nodes.cs index d16e273..26bb136 100644 --- a/Runtime/Godot/Nodes.cs +++ b/Runtime/Godot/Nodes.cs @@ -209,6 +209,30 @@ namespace Rokojori ,false ); } + public static async Task ForEachAsync( this Node root, Func callback ) where T:class + { + var walker = nodesWalker; + + await walker.IterateAsync( root, + async ( n )=> + { + var t = n as T; + + if ( t == null ) + { + return; + } + + await callback( t ); + + return; + + } + ,false ); + + return; + } + public static T GetSibling( Node node ) where T:Node { if ( node == null ) @@ -233,10 +257,13 @@ namespace Rokojori t.Owner = parent.Owner; - if ( name != null ) + if ( name == null ) { - t.Name = name; + name = t.GetType().Name; } + + t.Name = name; + return t; } diff --git a/Runtime/Graphs/Trees/TreeWalker.cs b/Runtime/Graphs/Trees/TreeWalker.cs index b81bc9a..1d641bc 100644 --- a/Runtime/Graphs/Trees/TreeWalker.cs +++ b/Runtime/Graphs/Trees/TreeWalker.cs @@ -1,6 +1,7 @@ using System.Collections; using System.Collections.Generic; using System; +using System.Threading.Tasks; namespace Rokojori { @@ -585,6 +586,25 @@ namespace Rokojori } } + public async Task IterateAsync( N node, Func callback, bool childrenOnly = false ) + { + var end = IterationEndOf( node ); + var it = node; + + if ( childrenOnly ) + { + it = NextNode( it ); + } + + while ( it != end ) + { + await callback( it ); + it = NextNode( it ); + } + + return; + } + public N Find( N node, Predicate predicate, bool childrenOnly ) { var end = IterationEndOf( node ); diff --git a/Runtime/Math/Biquad.cs.uid b/Runtime/Math/Biquad.cs.uid new file mode 100644 index 0000000..ffb087a --- /dev/null +++ b/Runtime/Math/Biquad.cs.uid @@ -0,0 +1 @@ +uid://c1upyoky3f0we diff --git a/Runtime/Networking/Nodes/NetworkNode.cs b/Runtime/Networking/Nodes/NetworkNode.cs index aafadd1..b098e08 100644 --- a/Runtime/Networking/Nodes/NetworkNode.cs +++ b/Runtime/Networking/Nodes/NetworkNode.cs @@ -21,19 +21,6 @@ namespace Rokojori protected List _networkNodeMembers = null; protected NetworkNodeSlot _networkNodeSlot = new NetworkNodeSlot(); - #if TOOLS - - [ExportGroup("Help")] - [ExportToolButton( "Open Online Docs")] - public Callable openOnlineDocsButton => Callable.From( - ()=> - { - OnlineDocs.Open( GetType() ); - } - ); - - #endif - public virtual List GetNetworkNodeMembers() { if ( _networkNodeMembers != null ) diff --git a/Runtime/Procedural/Assets/Grass/GrassPatch.cs b/Runtime/Procedural/Assets/Grass/GrassPatch.cs index e2034a9..2a12ce3 100644 --- a/Runtime/Procedural/Assets/Grass/GrassPatch.cs +++ b/Runtime/Procedural/Assets/Grass/GrassPatch.cs @@ -8,13 +8,42 @@ using System.Threading.Tasks; namespace Rokojori { + /** + + + Creates a grass patch 3D model asset. + + + + The GrassPatch has various settings to create a different styles of grass. + It allows to change the shapes of the blades, their number and distribution, their triangle count, + rotation and scale, LOD levels and much more. + + + + + + */ + [Tool] [GlobalClass, Icon("res://addons/rokojori_action_library/Icons/Scatterer.svg") ] public partial class GrassPatch:Node3D { + + [ExportToolButton( "(?) Help", Icon = "Help") ] + public Callable openHelpButton => Callable.From( ()=> + { + #if TOOLS + Rokojori.Tools.OnlineDocs.Open( GetType() ); + #endif + } + ); + + /** The output where the mesh is stored, gets generated automatically.*/ [Export] public MeshInstance3D output; - + + /** The seed for the randomizers*/ [Export] public int seed = 1984; @@ -25,94 +54,194 @@ namespace Rokojori CreatePatch(); } ); + + /** The material the grass will be assigned*/ [Export] public Material material; + + /** Patch size for x and z*/ [ExportGroup( "Patch")] [Export] public float patchSize = 2; + /** Additional patch size for x*/ [Export] public float patchSizeX = 0; + /** Additional patch size for z*/ [Export] public float patchSizeZ = 0; - + + /** Patch offset in x/z*/ [Export] public Vector2 patchOffsetPosition = new Vector2( 0.5f, 0.5f ); + /** If centerPatch is on, the patch will be centered automatically*/ [Export] public bool centerPatch = false; + /** + If on, this determines which vertices should be counted to compute the center of the patch. + +

+ All vertices in y that are below, will not count to compute the center. + This can be usefull to align more to the upper more visible parts, it usually has only a small impact. +

+
*/ [Export] public float centerPatchComputationHeightTreshold = 0.1f; [ExportGroup( "Blades")] + /** The number of blades it will generate in x and z*/ [Export( PropertyHint.Range, "0,100")] public int blades = 20; + /** Additional number of blades it will generate in x*/ [Export( PropertyHint.Range, "0,100")] public int bladesX = 0; + /** Additional number of blades it will generate in z*/ [Export( PropertyHint.Range, "0,100")] public int bladesZ = 0; + /** This is an output/debug property, and will show how many blades were created*/ [Export] public int X_numBlades; - + /** This defines the number of segments (vertical divisions) for each blade.*/ [ExportGroup( "Triangles")] [Export( PropertyHint.Range, "1,256")] public int bladeSegments = 3; + /** This generates back faces, if it is disabled the material should not use backface culling*/ [Export] public bool createBackFaces = true; + /** + If on, this allows the ends of the blades to be merged as triangles instead of quads. +

+ This is usefull for creating very low poly grass blades with only one triangle. + The width of the blade needs to be very close to zero at the start or end to be applied. +

+
*/ [Export] public bool allowTrianglesOnEnds = true; + /** This is an output/debug property, and will show how many triangels were created*/ [Export] public int X_numTriangles; + /** + Allows to use a non-linear distortion for the segmentation. +

+ Normally, the blade shapes are segmented by taking an equal distance of divisions throughout the + height of the blade. + But since this low poly shapes won't be represented well with this approach, + zhis setting allows to distort the segmentation, some shapes are better represented with it. +

+
*/ [Export] public Curve bladeSegmentMapping = MathX.Curve( 0, 1 ); + /** + The number of splits in U for the blades, when generating the uv coordinates. + +

+ This allows to use multiple regions for the blades, so that blades can have different material settings. +

+
*/ [ExportGroup( "Segmentation")] [Export] public int uvSegmentColumns = 1; + /** + The number of splits in V for the blades, when generating the uv coordinates. + +

+ This allows to use multiple regions for the blades, so that blades can have different material settings. +

+
*/ [Export] public int uvSegmentRows = 1; + /** + The distribution for the UV region selection. + +

+ This will change the propability of the uv regions, so that some regions can + be used more often than other regions. +

+
*/ [Export] public Curve uvSegmentWeightsClose = MathX.Curve( 1f ); + + /** + The distribution for the UV region selection for blades outside the center. + +

+ This will change the propability of the uv regions outside the center. + This allows to have different distribution dependening on the position. +

+
*/ [Export] public Curve uvSegmentWeightsFar = null; + /** + Blending factor between undistorted and distorted U mapping. + +

+ This warps/pulls the strength of the close or far distribution. +

+
*/ + [Export( PropertyHint.Range, "0,1" )] public float uvSegmentDistortion = 0.5f; + /** + Defines how far the U mapping can distort. + */ [Export( PropertyHint.Range, "0,0.5" )] public float uvSegmentMaxRange = 0.3f; - [ExportGroup( "Shape")] + /** + Defines the height of the blades, the curve defines the random distribution. +

+ The total y size is sum of the blade height and baldInGround. +

+
*/ + [ExportGroup( "Shape")] [Export] public Curve bladeHeight = MathX.Curve( 0.4f ); + /** + The amount the blade is continued below 0 in y. See also bladeHeight. + */ [Export] public Curve bladeInGround = MathX.Curve( 0.05f ); + /** + The width of the blade defined over its height. + */ [Export] public Curve bladeWidth = MathX.Curve( 0.05f ); + /** + Optional: A second width (as randomizer) of the blade defined over its height. + +

+ The randomizer chooses a blend value before the creation and will use the resulting curve as width. + This means it will not randomly jump between the first and second width, but uses an interpolated curve. +

+
*/ [Export] public Curve bladeWidth2 = null; diff --git a/Runtime/Procedural/Mesh/MeshCombiner.cs b/Runtime/Procedural/Mesh/MeshCombiner.cs index 99d7def..7123907 100644 --- a/Runtime/Procedural/Mesh/MeshCombiner.cs +++ b/Runtime/Procedural/Mesh/MeshCombiner.cs @@ -8,6 +8,20 @@ using System.Threading.Tasks; namespace Rokojori { + /** + + + Combines multiples meshes and/or materials into one mesh or material. + + + + + + + + + */ + [Tool] [GlobalClass] public partial class MeshCombiner:Node3D @@ -29,7 +43,7 @@ namespace Rokojori } [Export] - public UVCombineMode uVCombineMode = UVCombineMode.Adjust_To_Combined_Material; + public UVCombineMode uvCombineMode = UVCombineMode.Adjust_To_Combined_Material; [Export] public Node3D pivot; @@ -50,6 +64,9 @@ namespace Rokojori [Export] public int randomSortSeed = 1234; + [Export] + public X_MeshGeometryModifierResource[] meshModifiers; + [ExportGroup( "Material")] [Export] public bool combineMaterials = true; @@ -466,7 +483,7 @@ namespace Rokojori if ( isCombinedMaterial && ! combineMeshes ) { - meshGeometry.GenerateMesh( Mesh.PrimitiveType.Triangles, arrayMesh ); + meshGeometry.Apply( meshModifiers ).GenerateMesh( Mesh.PrimitiveType.Triangles, arrayMesh ); arrayMesh.SurfaceSetMaterial( index, usedMaterial ); var meshInstance = outputContainer.CreateChild(); @@ -494,7 +511,7 @@ namespace Rokojori if ( combineMeshes ) { - meshGeometry.GenerateMesh( Mesh.PrimitiveType.Triangles, arrayMesh ); + meshGeometry.Apply( meshModifiers ).GenerateMesh( Mesh.PrimitiveType.Triangles, arrayMesh ); arrayMesh.SurfaceSetMaterial( index, usedMaterial ); index ++; @@ -513,7 +530,7 @@ namespace Rokojori var combinedMG = MeshGeometry.Combine( meshes ); this.LogInfo( "Combed meshes, num tris:", combinedMG.numTriangles ); - combinedMG.GenerateMesh( Mesh.PrimitiveType.Triangles, arrayMesh ); + combinedMG.Apply( meshModifiers ).GenerateMesh( Mesh.PrimitiveType.Triangles, arrayMesh ); this.LogInfo( "Add surface", index); arrayMesh.SurfaceSetMaterial( index, material ); diff --git a/Runtime/Procedural/Mesh/MeshGeometry.cs b/Runtime/Procedural/Mesh/MeshGeometry.cs index 933347e..1036f89 100644 --- a/Runtime/Procedural/Mesh/MeshGeometry.cs +++ b/Runtime/Procedural/Mesh/MeshGeometry.cs @@ -1496,6 +1496,23 @@ namespace Rokojori return GenerateLODMesh( mgs, Mesh.PrimitiveType.Triangles, null, generateTangents, lerpingData ); } + public MeshGeometry Apply( X_MeshGeometryModifierResource[] modifiers ) + { + if ( modifiers == null || modifiers.Length == 0 ) + { + return this; + } + var mg = this; + + modifiers.ForEach( + ( m )=> + { + mg = m.Modify( mg ); + } + ); + + return mg; + } public ArrayMesh GenerateMesh( diff --git a/Runtime/Procedural/Mesh/Modifiers/MeshGeometryModifier.cs b/Runtime/Procedural/Mesh/Modifiers/MeshGeometryModifier.cs index e898f7a..f99fe02 100644 --- a/Runtime/Procedural/Mesh/Modifiers/MeshGeometryModifier.cs +++ b/Runtime/Procedural/Mesh/Modifiers/MeshGeometryModifier.cs @@ -9,7 +9,8 @@ namespace Rokojori { public class MeshGeometryModifier { - public MeshGeometry Modify( MeshGeometry mg ){ return mg; } + public virtual MeshGeometry Modify( MeshGeometry mg ){ return mg; } + } } \ No newline at end of file diff --git a/Runtime/Procedural/Mesh/Modifiers/NormalBlender/NormalBlender.cs b/Runtime/Procedural/Mesh/Modifiers/NormalBlender/NormalBlender.cs new file mode 100644 index 0000000..265af45 --- /dev/null +++ b/Runtime/Procedural/Mesh/Modifiers/NormalBlender/NormalBlender.cs @@ -0,0 +1,21 @@ +using System.Collections; +using System.Collections.Generic; +using Godot; +using System; + + + +namespace Rokojori +{ + [Tool] + [GlobalClass] + public partial class NormalBlender:X_MeshGeometryModifierResource + { + public NormalBlenderSettings settings; + public override MeshGeometry Modify( MeshGeometry mg ) + { + return settings.Blend( mg ); + } + + } +} \ No newline at end of file diff --git a/Runtime/Procedural/Mesh/Modifiers/NormalBlender/NormalBlender.cs.uid b/Runtime/Procedural/Mesh/Modifiers/NormalBlender/NormalBlender.cs.uid new file mode 100644 index 0000000..47ab4df --- /dev/null +++ b/Runtime/Procedural/Mesh/Modifiers/NormalBlender/NormalBlender.cs.uid @@ -0,0 +1 @@ +uid://do0gp7573fyp1 diff --git a/Runtime/Procedural/Mesh/Modifiers/NormalBlender/NormalBlenderModifier.cs b/Runtime/Procedural/Mesh/Modifiers/NormalBlender/NormalBlenderModifier.cs new file mode 100644 index 0000000..54b332f --- /dev/null +++ b/Runtime/Procedural/Mesh/Modifiers/NormalBlender/NormalBlenderModifier.cs @@ -0,0 +1,19 @@ +using System.Collections; +using System.Collections.Generic; +using Godot; +using System; + + + +namespace Rokojori +{ + public class NormalBlenderModifier:MeshGeometryModifier + { + public NormalBlenderSettings settings; + public override MeshGeometry Modify( MeshGeometry mg ) + { + return settings.Blend( mg ); + } + + } +} \ No newline at end of file diff --git a/Runtime/Procedural/Mesh/Modifiers/NormalBlender/NormalBlenderModifier.cs.uid b/Runtime/Procedural/Mesh/Modifiers/NormalBlender/NormalBlenderModifier.cs.uid new file mode 100644 index 0000000..a83dab4 --- /dev/null +++ b/Runtime/Procedural/Mesh/Modifiers/NormalBlender/NormalBlenderModifier.cs.uid @@ -0,0 +1 @@ +uid://dei88uuxuyt3x diff --git a/Runtime/Procedural/Mesh/Modifiers/NormalBlender/NormalBlenderSettings.cs b/Runtime/Procedural/Mesh/Modifiers/NormalBlender/NormalBlenderSettings.cs new file mode 100644 index 0000000..56b7b24 --- /dev/null +++ b/Runtime/Procedural/Mesh/Modifiers/NormalBlender/NormalBlenderSettings.cs @@ -0,0 +1,55 @@ +using System.Collections; +using System.Collections.Generic; +using Godot; +using System; + + + +namespace Rokojori +{ + [Tool] + [GlobalClass] + public partial class NormalBlenderSettings:Resource + { + public enum Mode + { + Over_Y + } + [Export] + public Mode mode; + + [Export(PropertyHint.Range,"0,1")] + public float normalBlendAmount = 0.5f; + + [ExportGroup("Over Y")] + [Export] + public Vector3 overY_blendDirection = Vector3.Up; + + [Export] + public float overY_blendStartY = 0; + + [Export] + public float overY_blendEndY = 0.25f; + + [Export] + public Curve overY_blendCurve; + + + public MeshGeometry Blend( MeshGeometry mg ) + { + if ( Mode.Over_Y == mode ) + { + return BlendOverY( mg ); + } + + return mg; + } + + MeshGeometry BlendOverY( MeshGeometry mg ) + { + mg.BlendNormalsOverY( overY_blendDirection, normalBlendAmount, overY_blendStartY, overY_blendEndY, overY_blendCurve ); + return mg; + } + + } +} \ No newline at end of file diff --git a/Runtime/Procedural/Mesh/Modifiers/NormalBlender/NormalBlenderSettings.cs.uid b/Runtime/Procedural/Mesh/Modifiers/NormalBlender/NormalBlenderSettings.cs.uid new file mode 100644 index 0000000..f8224da --- /dev/null +++ b/Runtime/Procedural/Mesh/Modifiers/NormalBlender/NormalBlenderSettings.cs.uid @@ -0,0 +1 @@ +uid://dbaxttonr78f5 diff --git a/Runtime/Procedural/Mesh/Modifiers/SplinesDeformer/SplinesDeformerModifier.cs b/Runtime/Procedural/Mesh/Modifiers/SplinesDeformer/SplinesDeformerModifier.cs index f3e3c99..ce59d07 100644 --- a/Runtime/Procedural/Mesh/Modifiers/SplinesDeformer/SplinesDeformerModifier.cs +++ b/Runtime/Procedural/Mesh/Modifiers/SplinesDeformer/SplinesDeformerModifier.cs @@ -15,16 +15,14 @@ namespace Rokojori public float weight; } - public class SplinesDeformModifier + public class SplinesDeformModifier:MeshGeometryModifier { public SplineCurve[] sourceSplines = new SplineCurve[ 0 ]; public SplineCurve[] targetSplines = new SplineCurve[ 0 ]; - public SplinesDeformerSettings settings; + public SplinesDeformerSettings settings; - - - public MeshGeometry Modify( MeshGeometry mg ) + public override MeshGeometry Modify( MeshGeometry mg ) { var mappings = CreateSourceMappings( mg ); return CreateDeformed( mg, mappings ); diff --git a/Runtime/Procedural/Mesh/Modifiers/X_MeshGeometryModifierResource.cs b/Runtime/Procedural/Mesh/Modifiers/X_MeshGeometryModifierResource.cs new file mode 100644 index 0000000..4db14ea --- /dev/null +++ b/Runtime/Procedural/Mesh/Modifiers/X_MeshGeometryModifierResource.cs @@ -0,0 +1,20 @@ +using System.Collections; +using System.Collections.Generic; +using Godot; +using System; + + + +namespace Rokojori +{ + [Tool] + [GlobalClass] + public partial class X_MeshGeometryModifierResource:Resource + { + public virtual MeshGeometry Modify( MeshGeometry mg ) + { + return mg; + } + + } +} \ No newline at end of file diff --git a/Runtime/Procedural/Mesh/Modifiers/X_MeshGeometryModifierResource.cs.uid b/Runtime/Procedural/Mesh/Modifiers/X_MeshGeometryModifierResource.cs.uid new file mode 100644 index 0000000..9b4df27 --- /dev/null +++ b/Runtime/Procedural/Mesh/Modifiers/X_MeshGeometryModifierResource.cs.uid @@ -0,0 +1 @@ +uid://bbs2ht7j11aoq diff --git a/Runtime/Text/Lexing/LexerEvent.cs b/Runtime/Text/Lexing/LexerEvent.cs index 3604468..ff9c773 100644 --- a/Runtime/Text/Lexing/LexerEvent.cs +++ b/Runtime/Text/Lexing/LexerEvent.cs @@ -501,7 +501,7 @@ namespace Rokojori if ( index == 0 ) { - RJLog.Log( tokens.Map( t => t.type + ": '" + t.match + "'" ).Join( "\n" ) ); + // RJLog.Log( tokens.Map( t => t.type + ": '" + t.match + "'" ).Join( "\n" ) ); } return blocks; } diff --git a/Runtime/Text/Lexing/LexerList.cs.uid b/Runtime/Text/Lexing/LexerList.cs.uid new file mode 100644 index 0000000..0ea2690 --- /dev/null +++ b/Runtime/Text/Lexing/LexerList.cs.uid @@ -0,0 +1 @@ +uid://dqh0ll5kxudrb diff --git a/Runtime/Time/DateTime/Date.cs b/Runtime/Time/DateTime/Date.cs deleted file mode 100644 index 0da8bf6..0000000 --- a/Runtime/Time/DateTime/Date.cs +++ /dev/null @@ -1,29 +0,0 @@ - -using System.Diagnostics; -using System.Collections; -using System.Collections.Generic; -using System; -using Godot; - - -namespace Rokojori -{ - [GlobalClass] - [Tool] - public partial class Date:Resource - { - public int year = 1; - public int month = 1; - public int day = 1; - - public int hours = 0; - public int minutes = 0; - public int second = 0; - public float milliseconds = 0; - - public int utcHoursOffset = 0; - public int utcMinutesOffset = 0; - public float utcMillisecondsOffset = 0; - - } -} \ No newline at end of file diff --git a/Runtime/Time/DateTime/Date.cs.uid b/Runtime/Time/DateTime/Date.cs.uid deleted file mode 100644 index eaba169..0000000 --- a/Runtime/Time/DateTime/Date.cs.uid +++ /dev/null @@ -1 +0,0 @@ -uid://cvl5k8x7rrybt diff --git a/Runtime/Time/DateTime/DateMath.cs b/Runtime/Time/DateTime/DateMath.cs index fbebb85..0249dc9 100644 --- a/Runtime/Time/DateTime/DateMath.cs +++ b/Runtime/Time/DateTime/DateMath.cs @@ -10,6 +10,10 @@ namespace Rokojori { public static class DateMath { + public static DateTimeOffset InThePast( int hours ) + { + return DateTimeOffset.UtcNow.AddHours( - hours ); + } public static bool IsNewerThan( this DateTimeOffset a, DateTimeOffset b ) { diff --git a/Runtime/Time/DateTime/ISOTimeStamp.cs b/Runtime/Time/DateTime/ISOTimeStamp.cs new file mode 100644 index 0000000..2ce106e --- /dev/null +++ b/Runtime/Time/DateTime/ISOTimeStamp.cs @@ -0,0 +1,37 @@ + +using System.Diagnostics; +using System.Collections; +using System.Collections.Generic; +using System; +using Godot; + + +namespace Rokojori +{ + public class ISOTimeStamp + { + public string value; + + public static ISOTimeStamp Create( string value ) + { + var t = new ISOTimeStamp(); + t.value = value; + return t; + } + + public static DateTimeOffset ToDate( ISOTimeStamp stamp ) + { + return DateTimeOffset.Parse( stamp.value ); + } + + public static ISOTimeStamp FromDate( DateTimeOffset date ) + { + return Create( date.ToString("o") ); + } + + public static ISOTimeStamp Now() + { + return ISOTimeStamp.FromDate( DateTimeOffset.Now ); + } + } +} \ No newline at end of file diff --git a/Runtime/Time/DateTime/ISOTimeStamp.cs.uid b/Runtime/Time/DateTime/ISOTimeStamp.cs.uid new file mode 100644 index 0000000..086483e --- /dev/null +++ b/Runtime/Time/DateTime/ISOTimeStamp.cs.uid @@ -0,0 +1 @@ +uid://cj240k4nm1fyq diff --git a/Runtime/Tools/ReflectionHelper.cs b/Runtime/Tools/ReflectionHelper.cs index a925095..26fd282 100644 --- a/Runtime/Tools/ReflectionHelper.cs +++ b/Runtime/Tools/ReflectionHelper.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System; using System.Reflection; using System.Text.RegularExpressions; +using Godot; namespace Rokojori { @@ -416,8 +417,28 @@ namespace Rokojori dataMembers.ForEach( dm => { - var value = GetDataMemberValue( source, dm ); - SetDataMemberValue( target, dm, value ); + try + { + var value = GetDataMemberValue( source, dm ); + SetDataMemberValue( target, dm, value ); + } + catch( System.Exception e ) + { + if ( source is Node n && target is Node n2 ) + { + n.LogInfo( "Could not copy to ", dm, HierarchyName.Of( n2 ) ); + } + else if ( source is Resource r && target is Resource r2 ) + { + r.LogInfo( "Could not copy to ", dm, HierarchyName.Of( r2 ) ); + } + else + { + RJLog.Log( "Could not copy from ", source, "to ", dm, ">>", target ); + } + + } + } ); } diff --git a/Tools/docs/ClassDocGenerator.cs b/Tools/docs/ClassDocGenerator.cs index d0fe29e..fb6db77 100644 --- a/Tools/docs/ClassDocGenerator.cs +++ b/Tools/docs/ClassDocGenerator.cs @@ -41,6 +41,41 @@ namespace Rokojori.DocGenerator return "CSharp.svg"; } + public static List GetExports( FieldInfo fieldInfo ) + { + var result = new List(); + + var exportAttributes = fieldInfo.GetCustomAttributes( typeof(ExportAttribute), false); + + foreach ( ExportAttribute export in exportAttributes ) + { + if ( export.Hint == PropertyHint.None) + { + result.Add( "Export" ); + } + else if ( ! string.IsNullOrEmpty( export.HintString ) ) + { + result.Add( $"Export( PropertyHint.{export.Hint}, \"{export.HintString}\" )" ); + } + else + { + result.Add( $"Export( PropertyHint.{export.Hint} )" ); + } + } + + return result; + } + + + public static string GetOutputFilePath( string outputPath, Type classType ) + { + var typeName = GetDocsType.Of( classType ); + var outputPathName = typeName.Replace( "`", "-" ).Replace( "<", "-" ).Replace( ">", "-" ); + + return FilePath.Join( outputPath, outputPathName + ".json" ); + } + + public ClassDocInfo Create( string filePath, Type classType, string definitionType, List icons ) { var data = filePath == null ? "" : FilesSync.LoadUTF8( filePath ); @@ -51,9 +86,9 @@ namespace Rokojori.DocGenerator var baseTypeName = classType.BaseType; var typeNameSpace = classType.Namespace; - RJLog.Log( typeName, "Comments:", comments.entries.Count ); + // RJLog.Log( typeName, "Comments:", comments.entries.Count ); - + info.modificationTime = FilesSync.GetModificationTimeStamp( filePath ); info.name = typeName; info.csNameSpace = typeNameSpace; info.definitionType = definitionType; @@ -160,6 +195,7 @@ namespace Rokojori.DocGenerator memberInfo.dataType = GetDocsType.Of( f.FieldType ); memberInfo.generics = Lists.Map( f.FieldType.GetGenericArguments(), t => t + "" ); memberInfo.doc = comments.FindDoc( "field", f.Name ); + memberInfo.attributes = GetExports( f ); if ( f.IsStatic ) { diff --git a/Tools/docs/ClassDocInfo.cs b/Tools/docs/ClassDocInfo.cs index f5fcb04..788de05 100644 --- a/Tools/docs/ClassDocInfo.cs +++ b/Tools/docs/ClassDocInfo.cs @@ -77,6 +77,7 @@ namespace Rokojori.DocGenerator public string icon; public string sourcePath; public string definitionType; + public ISOTimeStamp modificationTime; public List generics = new List(); public List interfaces = new List(); diff --git a/Tools/docs/CreateDoc.cs b/Tools/docs/CreateDoc.cs index d8f82f4..d36340e 100644 --- a/Tools/docs/CreateDoc.cs +++ b/Tools/docs/CreateDoc.cs @@ -40,10 +40,10 @@ namespace Rokojori.DocGenerator public bool shaders = true; [Export] - public bool processOnlyNewerThanCheckTime = true; + public bool processOnlyNewer = true; [Export] - public float hoursCheckTime; + public int hoursCheckTime = 12; [ExportToolButton( "Create")] public Callable createButton => Callable.From( ()=>{ Generate(); } ); @@ -77,6 +77,7 @@ namespace Rokojori.DocGenerator var generator = new DocGenerator(); generator.shaders = shaders; generator.cSharp = c_sharp; + generator.checkChangeTime = processOnlyNewer; var icons = Lists.Map( FilesSync.GetFiles( absoluteIconPath, ( fp => fp.fileExtension == ".svg" ) ), fp => fp.fullFileName ); generator.Generate( absoluteLibraryPath, absoluteOutputPath, icons ); diff --git a/Tools/docs/DocComments.cs b/Tools/docs/DocComments.cs index 3dc69e7..5362e08 100644 --- a/Tools/docs/DocComments.cs +++ b/Tools/docs/DocComments.cs @@ -70,7 +70,7 @@ namespace Rokojori.DocGenerator entries.Add( entry ); - RJLog.Log( "Doc Comment:", entry.type, entry.name, ">>\n", entry.doc ); + // RJLog.Log( "Doc Comment:", entry.type, entry.name, ">>\n", entry.doc ); } ); diff --git a/Tools/docs/DocGenerator.cs b/Tools/docs/DocGenerator.cs index 0be333b..faf5feb 100644 --- a/Tools/docs/DocGenerator.cs +++ b/Tools/docs/DocGenerator.cs @@ -30,7 +30,6 @@ namespace Rokojori.DocGenerator List icons = new List(); public bool checkChangeTime = false; - public DateTimeOffset changeTime; public List classFiles = new List(); public List classTypes = new List(); @@ -62,7 +61,7 @@ namespace Rokojori.DocGenerator if ( isShader ) { - RJLog.Log( "SHADER: FILE", f.absolutePath ); + // RJLog.Log( "SHADER: FILE", f.absolutePath ); } return ( cSharp && isCS ) || ( shaders && isShader ); @@ -70,15 +69,16 @@ namespace Rokojori.DocGenerator true ); - if ( checkChangeTime ) - { - classFiles = await classFiles.FilterAsync( - async ( f ) => - { - return await Git.IsFileNewerThan( f.absolutePath, changeTime ); - } - ); - } + // if ( checkChangeTime ) + // { + // classFiles = await classFiles.FilterAsync( + // async ( f ) => + // { + // let generated = + // return await Git.IsFileNewerThan( f.absolutePath, changeTime ); + // } + // ); + // } } void IncludeDefaultTypes() @@ -121,7 +121,7 @@ namespace Rokojori.DocGenerator var fileContent = FilesSync.LoadUTF8( cf.fullPath ); var definitions = CSharpLexer.GetAllObjectDefinitions( fileContent ); - RJLog.Log( cf.fileName, ">>", definitions.Join( "," ) ); + // RJLog.Log( cf.fileName, ">>", definitions.Join( "," ) ); for ( int i = 0; i < definitions.Count; i++ ) { @@ -129,7 +129,7 @@ namespace Rokojori.DocGenerator var definitionType = sequence[ 0 ]; var definitionName = sequence[ 1 ]; - RJLog.Log( "Adding definition:", definitionName.match ); + // RJLog.Log( "Adding definition:", definitionName.match ); AddCSharpsClassType( cf, definitionName.match, definitionType.match, namespaceLabel, assembly ); } @@ -140,7 +140,7 @@ namespace Rokojori.DocGenerator shaderType.path = cf.absolutePath; shaderTypes.Add( shaderType ); - RJLog.Log( "SHADER: Adding definition:", cf.absolutePath ); + // RJLog.Log( "SHADER: Adding definition:", cf.absolutePath ); } @@ -162,12 +162,39 @@ namespace Rokojori.DocGenerator { return; } - + + if ( checkChangeTime ) + { + + var outputPath = ClassDocGenerator.GetOutputFilePath( this.outputPath, type ); + + // RJLog.Log( "Checking change times:", outputPath, cf.fullPath ); + + if ( FilesSync.FileExists( outputPath ) ) + { + var outputModificationTime = FilesSync.GetModificationTime( outputPath ); + var classModificationTime = FilesSync.GetModificationTime( cf.fullPath ); + + // RJLog.Log( "Change times are:", outputModificationTime, classModificationTime ); + + if ( outputModificationTime.IsNewerThan( classModificationTime ) ) + { + // RJLog.Log( "File not changed:", type, cf.fullPath ); + return; + } + } + else + { + + } + } + var entry = new ClassTypeEntry(); entry.type = type; entry.path = cf.fullPath; entry.definitionType = definitionType; + classTypes.Add( entry); } @@ -181,28 +208,30 @@ namespace Rokojori.DocGenerator { var cdg = new ClassDocGenerator(); var cinfo = cdg.Create( c.path, c.type, c.definitionType, icons ); - var outputPathName = cinfo.name.Replace( "`", "-" ).Replace( "<", "-" ).Replace( ">", "-" ); + var outputPath = ClassDocGenerator.GetOutputFilePath( this.outputPath, c.type ); + // var outputPathName = cinfo.name.Replace( "`", "-" ).Replace( "<", "-" ).Replace( ">", "-" ); - var outputPath = FilePath.Join( this.outputPath, outputPathName + ".json" ); + // var outputPath = FilePath.Join( this.outputPath, outputPathName + ".json" ); FilesSync.SaveJSON( outputPath, cinfo ); + RJLog.Log( "Updated", c.type.Name, c.path ); } ); - RJLog.Log( "SHADER: shaderTypes", shaderTypes.Count ); + // RJLog.Log( "SHADER: shaderTypes", shaderTypes.Count ); shaderTypes.ForEach( ( s ) => { try { - RJLog.Log( "SHADER: DOC", s.path ); + // RJLog.Log( "SHADER: DOC", s.path, path ); var sdg = new ShaderDocGenerator(); - var cinfo = sdg.Create( s.path ); + var cinfo = sdg.Create( s.path, path ); var prefix = cinfo.definitionType + "." ; var outputPathName = prefix + cinfo.name; var outputPath = FilePath.Join( this.outputPath, outputPathName + ".json" ); - RJLog.Log( "SHADER: SAVING", s.path, ">>", outputPathName ); + // RJLog.Log( "SHADER: SAVING", s.path, ">>", outputPathName ); FilesSync.SaveJSON( outputPath, cinfo ); } catch ( System.Exception e ) diff --git a/Tools/docs/OnlineDocs.cs b/Tools/docs/OnlineDocs.cs index 5177616..0c5ef6a 100644 --- a/Tools/docs/OnlineDocs.cs +++ b/Tools/docs/OnlineDocs.cs @@ -5,11 +5,12 @@ using System.Diagnostics; using System.Collections.Generic; using System.Threading.Tasks; + namespace Rokojori.Tools { public class OnlineDocs { - static string docsPath = "https://rokojori.com/en/labs/godot/docs/4.3/"; + static string docsPath = "https://rokojori.com/en/labs/godot/docs/4.4/"; public static void Open( System.Type type ) { var name = type.Name + "-class"; diff --git a/Tools/docs/ShaderDocGenerator.cs b/Tools/docs/ShaderDocGenerator.cs index 74ec78c..894591b 100644 --- a/Tools/docs/ShaderDocGenerator.cs +++ b/Tools/docs/ShaderDocGenerator.cs @@ -20,7 +20,8 @@ namespace Rokojori.DocGenerator List _lexerEvents; LexerList tokens; - public ClassDocInfo Create( string filePath ) + + public ClassDocInfo Create( string filePath, string rootPath ) { var fileContent = FilesSync.LoadUTF8( filePath ); _lexerEvents = GDShaderLexer.Lex( fileContent ); @@ -36,6 +37,7 @@ namespace Rokojori.DocGenerator } info.name = RegexUtility.TrimToLastPathFragment( filePath ).ReplaceEnd( GDShaderIncludeExtension, "" ).ReplaceEnd( GDShaderExtension, "" ); + info.sourcePath = FilePath.Join( "Runtime", filePath.ReplaceStart( rootPath ) ); GetIncludes(); GetUniforms(); @@ -49,7 +51,7 @@ namespace Rokojori.DocGenerator { var includePrexix = "#include "; - RJLog.Log( "Processing includes:", tokens.GetAll( LexerMatcherLibrary.CInstructionMatcher ).events.Count ); + // RJLog.Log( "Processing includes:", tokens.GetAll( LexerMatcherLibrary.CInstructionMatcher ).events.Count ); tokens.ForEach( LexerMatcherLibrary.CInstructionMatcher, ( t )=> @@ -57,11 +59,11 @@ namespace Rokojori.DocGenerator var match = t.match; - RJLog.Log( "Processing include:", match ); + // RJLog.Log( "Processing include:", match ); if ( ! match.StartsWith( includePrexix ) ) { - RJLog.Log( "Processing include:", match ); + // RJLog.Log( "Processing include:", match ); return; } diff --git a/Tools/gltf-export/ExportGLTF.cs b/Tools/gltf-export/ExportGLTF.cs new file mode 100644 index 0000000..b2b8fe4 --- /dev/null +++ b/Tools/gltf-export/ExportGLTF.cs @@ -0,0 +1,29 @@ +using System.Collections; +using System.Collections.Generic; +using Godot; +using System; +using System.Threading.Tasks; + + + + +namespace Rokojori.Tools +{ + [Tool] + [GlobalClass] + public partial class ExportGLTF:Action + { + [Export] + public Node3D root; + + [Export] + public string path; + + protected override void _OnTrigger() + { + #if TOOLS + GLTFExport.Save( root, path ); + #endif + } + } +} diff --git a/Tools/gltf-export/ExportGLTF.cs.uid b/Tools/gltf-export/ExportGLTF.cs.uid new file mode 100644 index 0000000..546a772 --- /dev/null +++ b/Tools/gltf-export/ExportGLTF.cs.uid @@ -0,0 +1 @@ +uid://cbwdx0p5m7qoe