diff --git a/Icons/AppSetting.svg b/Icons/AppSetting.svg new file mode 100644 index 0000000..7d1236f --- /dev/null +++ b/Icons/AppSetting.svg @@ -0,0 +1,256 @@ + + diff --git a/Icons/AppSetting.svg.import b/Icons/AppSetting.svg.import new file mode 100644 index 0000000..90019e4 --- /dev/null +++ b/Icons/AppSetting.svg.import @@ -0,0 +1,43 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bmwow4y720y33" +path="res://.godot/imported/AppSetting.svg-8d628f4fbcffee62d24cc3be49835a1b.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/rokojori_action_library/Icons/AppSetting.svg" +dest_files=["res://.godot/imported/AppSetting.svg-8d628f4fbcffee62d24cc3be49835a1b.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +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/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +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/Icons/AppSettingsCategory.svg b/Icons/AppSettingsCategory.svg new file mode 100644 index 0000000..a2deff2 --- /dev/null +++ b/Icons/AppSettingsCategory.svg @@ -0,0 +1,288 @@ + + diff --git a/Icons/AppSettingsCategory.svg.import b/Icons/AppSettingsCategory.svg.import new file mode 100644 index 0000000..13dd68a --- /dev/null +++ b/Icons/AppSettingsCategory.svg.import @@ -0,0 +1,43 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cxn0doccbmdkk" +path="res://.godot/imported/AppSettingsCategory.svg-fc090dc93be0f63fc2716bd8b27285c6.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/rokojori_action_library/Icons/AppSettingsCategory.svg" +dest_files=["res://.godot/imported/AppSettingsCategory.svg-fc090dc93be0f63fc2716bd8b27285c6.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +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/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +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/Icons/UIStyle.svg b/Icons/UIStyle.svg new file mode 100644 index 0000000..2336448 --- /dev/null +++ b/Icons/UIStyle.svg @@ -0,0 +1,176 @@ + + diff --git a/Icons/UIStyle.svg.import b/Icons/UIStyle.svg.import new file mode 100644 index 0000000..69356d9 --- /dev/null +++ b/Icons/UIStyle.svg.import @@ -0,0 +1,43 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bvypajorfxmwx" +path="res://.godot/imported/UIStyle.svg-a608110861b4c944c77405733f78e151.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/rokojori_action_library/Icons/UIStyle.svg" +dest_files=["res://.godot/imported/UIStyle.svg-a608110861b4c944c77405733f78e151.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +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/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +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/ActionSequence.cs b/Runtime/Actions/ActionSequence.cs index ede7a37..c244722 100644 --- a/Runtime/Actions/ActionSequence.cs +++ b/Runtime/Actions/ActionSequence.cs @@ -16,6 +16,7 @@ namespace Rokojori public int sequencablesIndex = 0; bool cancelled = false; bool cancelledSequence = false; + int _runID = -1; @@ -213,6 +214,7 @@ namespace Rokojori // this.LogInfo( "Running" ); + var run = new ActionSequenceRunner(); run.sequence = this; run.actions = new List( actions ); diff --git a/Runtime/Actions/Conditional/CoolDown.cs b/Runtime/Actions/Conditional/CoolDown.cs index 3e92159..a8577e2 100644 --- a/Runtime/Actions/Conditional/CoolDown.cs +++ b/Runtime/Actions/Conditional/CoolDown.cs @@ -12,12 +12,25 @@ namespace Rokojori [Export] public Action action; + [Export] + public Action onCoolingDownAction; + [Export] public Duration coolDownDuration; + [Export] + public bool retriggerCoolDown = false; + bool _isCoolingDown = false; int _coolDownID = -1; + bool _canRelease = false; + + public bool CanRelease() + { + return _canRelease; + } + public void RegisterCoolDown() { _isCoolingDown = coolDownDuration != null; @@ -54,13 +67,23 @@ namespace Rokojori { if ( _isCoolingDown ) { + onCoolingDownAction?.Trigger(); + _canRelease = false; + + if ( retriggerCoolDown ) + { + RegisterCoolDown(); + } return; } + _canRelease = true; Trigger( action ); RegisterCoolDown(); + + } } } \ No newline at end of file diff --git a/Runtime/Actions/Conditional/CoolDownRelease.cs b/Runtime/Actions/Conditional/CoolDownRelease.cs new file mode 100644 index 0000000..52e6a19 --- /dev/null +++ b/Runtime/Actions/Conditional/CoolDownRelease.cs @@ -0,0 +1,28 @@ + +using Godot; +using System.Collections.Generic; + + +namespace Rokojori; + +[Tool] +[GlobalClass, Icon("res://addons/rokojori_action_library/Icons/ConditionalAction.svg")] +public partial class CoolDownRelease : Action +{ + [Export] + public CoolDown coolDown; + + [Export] + public Action action; + + protected override void _OnTrigger() + { + if ( ! ( coolDown?.CanRelease() ?? true ) ) + { + return; + } + + action?.Trigger(); + + } +} diff --git a/Runtime/Actions/Conditional/CoolDownRelease.cs.uid b/Runtime/Actions/Conditional/CoolDownRelease.cs.uid new file mode 100644 index 0000000..7094f1a --- /dev/null +++ b/Runtime/Actions/Conditional/CoolDownRelease.cs.uid @@ -0,0 +1 @@ +uid://b4ld8egl1pum diff --git a/Runtime/Actions/LoadScene.cs b/Runtime/Actions/LoadScene.cs index b34dfcd..1d01cbf 100644 --- a/Runtime/Actions/LoadScene.cs +++ b/Runtime/Actions/LoadScene.cs @@ -7,15 +7,32 @@ namespace Rokojori [Tool][GlobalClass] public partial class LoadScene : SequenceAction { - [Export] + [Export( PropertyHint.File )] public string scenePath; [Export] public Node target; + [ExportGroup("Transforming")] + [Export] + public Node3D poseParent; + + [Export] + public Vector3 offsetTranslation = Vector3.Zero; + + [Export] + public Quaternion offsetRotation = Quaternion.Identity; + [Export] public Action onLoaded; + Node _loadedNode; + + public Node GetLoadedNode() + { + return _loadedNode; + } + bool _loading = false; int _id = -1; List _cached = new List(); @@ -40,6 +57,7 @@ namespace Rokojori } } + public override void _Process ( double delta ) { if ( ! _loading ) @@ -58,8 +76,24 @@ namespace Rokojori var packedScene = (PackedScene) ResourceLoader.LoadThreadedGet( scenePath ); var node = packedScene.Instantiate(); - target.AddChild( node ); + _loadedNode = node; + target.AddChild( node ); + node.Owner = target.Owner; + + if ( node is Node3D n3D ) + { + if ( poseParent != null ) + { + Pose.From( poseParent ).Set( n3D ); + } + + n3D.GlobalPosition = n3D.GlobalPosition + offsetTranslation; + n3D.SetGlobalQuaternion( n3D.GlobalQuaternion() * offsetRotation ); + } + Action.Trigger( onLoaded ); + + _loadedNode = null; DispatchEnd( _id ); _id = -1; diff --git a/Runtime/Actions/Node/SetNodeState.cs b/Runtime/Actions/Node/SetNodeState.cs index 6e09371..9bb46f9 100644 --- a/Runtime/Actions/Node/SetNodeState.cs +++ b/Runtime/Actions/Node/SetNodeState.cs @@ -7,21 +7,60 @@ namespace Rokojori [Tool][GlobalClass, Icon("res://addons/rokojori_action_library/Icons/SetNodeState.svg")] public partial class SetNodeState : Action { - [Export] - public Node[] enable = new Node[ 0 ]; + [Export] - public Node[] disable = new Node[ 0 ]; + public Node[] enable = []; + + [Export] + public Node[] disable = []; + + [ExportGroup( "Reference")] + [Export] + public SetNodeState reference; + + [Export] + public bool inverseReference = false; + protected override void _OnTrigger() { - CallDeferred( "SetStates" ); + this.CallDeferred( + ()=> + { + var map = new System.Collections.Generic.HashSet(); + SetStates( map, false, inverseReference ); + } + ); } - void SetStates() + public void SetStates( System.Collections.Generic.HashSet callMap, bool inverse, bool referenceInverse ) { - Arrays.ForEach( enable, n => NodeState.Enable( n ) ); - Arrays.ForEach( disable, n => NodeState.Disable( n ) ); + if ( callMap.Contains( this ) ) + { + return; + } + + callMap.Add( this ); + + if ( inverse ) + { + Arrays.ForEach( enable, n => NodeState.Disable( n ) ); + Arrays.ForEach( disable, n => NodeState.Enable( n ) ); + } + else + { + Arrays.ForEach( enable, n => NodeState.Enable( n ) ); + Arrays.ForEach( disable, n => NodeState.Disable( n ) ); + } + + if ( reference == null ) + { + return; + } + + reference.SetStates( callMap, referenceInverse, referenceInverse ); + } } diff --git a/Runtime/Actions/Node3D/PlayParticles.cs b/Runtime/Actions/Node3D/PlayParticles.cs index 8f7d85c..6104cb0 100644 --- a/Runtime/Actions/Node3D/PlayParticles.cs +++ b/Runtime/Actions/Node3D/PlayParticles.cs @@ -87,7 +87,7 @@ namespace Rokojori return particles3D; } - return _pool.Find( p => ! p.Emitting ); + return _pool.Find( p => ! IsEmitting( p ) ); } GpuParticles3D DuplicateParticles() diff --git a/Runtime/Actions/Sequence/CancelSequenceAction.cs b/Runtime/Actions/Sequence/CancelSequenceAction.cs new file mode 100644 index 0000000..fe0718f --- /dev/null +++ b/Runtime/Actions/Sequence/CancelSequenceAction.cs @@ -0,0 +1,18 @@ + +using Godot; +using System.Collections.Generic; + +namespace Rokojori +{ + [Tool][GlobalClass ] + public partial class CancelSequenceAction : Action + { + [Export] + public SequenceAction sequence; + + protected override void _OnTrigger() + { + sequence?.CancelAllRunning(); + } + } +} \ No newline at end of file diff --git a/Runtime/Actions/Sequence/CancelSequenceAction.cs.uid b/Runtime/Actions/Sequence/CancelSequenceAction.cs.uid new file mode 100644 index 0000000..da332b5 --- /dev/null +++ b/Runtime/Actions/Sequence/CancelSequenceAction.cs.uid @@ -0,0 +1 @@ +uid://cwbkharqngylr diff --git a/Runtime/Actions/SequenceAction.cs b/Runtime/Actions/SequenceAction.cs index 3427ae1..d594d08 100644 --- a/Runtime/Actions/SequenceAction.cs +++ b/Runtime/Actions/SequenceAction.cs @@ -1,6 +1,7 @@ using Godot; using System.Collections.Generic; +using System.Linq; namespace Rokojori { @@ -30,7 +31,8 @@ namespace Rokojori [Export] public int[] runningSequences = []; - + + HashSet _running = new HashSet(); int _dispatchCounter = 0; @@ -50,11 +52,15 @@ namespace Rokojori runningSequences = runningSequences.Add( _dispatchCounter ); } + _running.Add( _dispatchCounter ); + return _dispatchCounter; } public void DispatchEnd( int id ) { + _running.Remove( id ); + var ev = new SequenceActionFinishedEvent{ id = id, success = true }; onSequenceDone.DispatchEvent( ev ); @@ -62,10 +68,14 @@ namespace Rokojori { runningSequences = runningSequences.Remove( _dispatchCounter ); } + + } public void DispatchCancelled( int id ) { + _running.Remove( id ); + var ev = new SequenceActionFinishedEvent{ id = id, success = true }; onSequenceDone.DispatchEvent( ev ); @@ -73,6 +83,20 @@ namespace Rokojori { runningSequences = runningSequences.Remove( _dispatchCounter ); } + + + } + + public virtual void CancelAllRunning() + { + var runningList = _running.ToArray(); + + runningList.ForEach( + ( id )=> + { + CancelAction( id ); + } + ); } public virtual void CancelAction( int id ) diff --git a/Runtime/Actions/SetPauseState.cs b/Runtime/Actions/SetPauseState.cs index 8d71dc6..2b72d7c 100644 --- a/Runtime/Actions/SetPauseState.cs +++ b/Runtime/Actions/SetPauseState.cs @@ -29,22 +29,24 @@ namespace Rokojori protected override void _OnTrigger() { - var currentState = GetTree().Paused; + var isCurrentlyPaused = GetTree().Paused; - var nextState = Mode.Toggle == mode ? ! currentState : Mode.Pause == mode ? false : true; + var nextIsPaused = Mode.Toggle == mode ? ! isCurrentlyPaused : + Mode.Pause == mode ? true : false; - this.LogInfo( "SetPauseState", currentState, ">>", nextState ); + this.LogInfo( "SetPauseState: is paused", isCurrentlyPaused, ">> next is paused", nextIsPaused ); - if ( currentState == nextState && onlyTriggerOnChange ) + if ( isCurrentlyPaused == nextIsPaused && onlyTriggerOnChange ) { return; } - this.LogInfo( "Setting Pause State", nextState ); - GetTree().Paused = nextState; + this.LogInfo( "Setting Paused State", nextIsPaused ); + + GetTree().Paused = nextIsPaused; - if ( nextState ) + if ( nextIsPaused ) { Action.Trigger( onPausing ); } diff --git a/Runtime/Actions/Solo.cs b/Runtime/Actions/Solo.cs index c7b2acf..35b45ce 100644 --- a/Runtime/Actions/Solo.cs +++ b/Runtime/Actions/Solo.cs @@ -1,4 +1,5 @@ +using System.Linq; using Godot; @@ -16,15 +17,27 @@ namespace Rokojori [Export] public NodeStateConfiguration muteConifiguration; + [Export] + public Node[] ignore = []; + protected override void _OnTrigger() { var parent = soloNode.GetParent(); + var soloConfig = soloConfiguration ?? NodeStateConfiguration.AllOn(); + var muteConfig = muteConifiguration ?? NodeStateConfiguration.AllOff(); + + parent.ForEachDirectChild( n => { - var configuration = soloNode == n ? soloConfiguration : muteConifiguration; + if ( ignore != null && ignore.Contains( n ) ) + { + return; + } + + var configuration = soloNode == n ? soloConfig : muteConfig; NodeState.Configure( n, configuration ); } ); diff --git a/Runtime/Actions/Time/Delay.cs b/Runtime/Actions/Time/Delay.cs index 177a513..5f39401 100644 --- a/Runtime/Actions/Time/Delay.cs +++ b/Runtime/Actions/Time/Delay.cs @@ -28,7 +28,7 @@ namespace Rokojori if ( type == TimeLineSpanUpdateType.End ) { DispatchEnd( sequenceID ); - // this.LogInfo( "time:", Time.GetTicksMsec() / 1000f ); + this.LogInfo( "time:", Time.GetTicksMsec() / 1000f ); } }, this diff --git a/Runtime/Actions/Time/DelayFrames.cs b/Runtime/Actions/Time/DelayFrames.cs new file mode 100644 index 0000000..9b1ddbf --- /dev/null +++ b/Runtime/Actions/Time/DelayFrames.cs @@ -0,0 +1,55 @@ + +using Godot; +using System.Threading.Tasks; + +namespace Rokojori +{ + [Tool][GlobalClass, Icon("res://addons/rokojori_action_library/Icons/Delay.svg")] + public partial class DelayFrames : SequenceAction + { + [Export] + public int numFrames; + + protected override void _OnTrigger() + { + var sequenceID = DispatchStart(); + + // this.LogInfo( "time:", Time.GetTicksMsec() / 1000f ); + + if ( Engine.IsEditorHint() ) + { + var timeLine = TimeLineManager.Ensure( null ); + + TimeLineManager.ScheduleSpanIn( timeLine, 0, numFrames * 1f/60f , + ( span, type )=> + { + if ( type == TimeLineSpanUpdateType.End ) + { + DispatchEnd( sequenceID ); + this.LogInfo( "time:", Time.GetTicksMsec() / 1000f ); + } + }, + this + ); + } + else + { + runForFrames( numFrames, sequenceID ); + } + + } + + protected async Task runForFrames( int frames, int sequenceID ) + { + while ( frames > 0 ) + { + await this.RequestNextFrame(); + frames --; + } + + DispatchEnd( sequenceID ); + } + + + } +} \ No newline at end of file diff --git a/Runtime/Actions/Time/DelayFrames.cs.uid b/Runtime/Actions/Time/DelayFrames.cs.uid new file mode 100644 index 0000000..267a7fd --- /dev/null +++ b/Runtime/Actions/Time/DelayFrames.cs.uid @@ -0,0 +1 @@ +uid://cb4ji13qh1v3g diff --git a/Runtime/Actions/Visual/TweenFloatShaderProperty.cs b/Runtime/Actions/Visual/TweenFloatShaderProperty.cs index 667cb54..2b2f79b 100644 --- a/Runtime/Actions/Visual/TweenFloatShaderProperty.cs +++ b/Runtime/Actions/Visual/TweenFloatShaderProperty.cs @@ -24,6 +24,20 @@ namespace Rokojori [Export] public Curve curve; + [ExportGroup( "Stop")] + [Export] + public bool stopAnimation = false; + + [Export] + public bool setStopValue = false; + + [ExportGroup( "Animate")] + [Export] + public bool animateStartValue = false; + + [Export] + public float animationStartValue = 0f; + [ExportGroup( "Editor Testing")] [Export] public bool forceStartValue = false; @@ -55,15 +69,41 @@ namespace Rokojori CancelAction( _actionID ); } + if ( stopAnimation ) + { + + AnimationManager.StartAnimation( this, material, propertyName ); + + if ( setStopValue ) + { + propertyName.Set( material, endValue ); + } + + AnimationManager.EndAnimation( this, material, propertyName ); + + + return; + } + + _actionID = DispatchStart(); var startValue = propertyName.Get( material ); + + + if ( forceStartValue && Engine.IsEditorHint() ) { startValue = forcedStartValue; } + if ( animateStartValue ) + { + startValue = animationStartValue; + } + + AnimationManager.StartAnimation( this, material, propertyName ); diff --git a/Runtime/Actions/Visual/TweenMaterial.cs b/Runtime/Actions/Visual/TweenMaterial.cs index 932d89f..767a1bd 100644 --- a/Runtime/Actions/Visual/TweenMaterial.cs +++ b/Runtime/Actions/Visual/TweenMaterial.cs @@ -184,6 +184,18 @@ namespace Rokojori _assignedMaterial = null; var msc = MaterialSurfaceContainer.From( target, index ); msc.SetMaterialInSlot( slot, toMaterial ); + + var prop = new ColorPropertyName(); + prop.propertyName = "albedo_color"; + + var info = new Color(); + + if ( toMaterial is BaseMaterial3D bm ) + { + info = bm.AlbedoColor; + } + + this.LogInfo( "Setting:", slot, toMaterial, info, prop.Get( toMaterial ) ); } DispatchEnd( sequenceID ); diff --git a/Runtime/Actions/Visual/TweenScale.cs b/Runtime/Actions/Visual/TweenScale.cs index 8caef13..58d19a2 100644 --- a/Runtime/Actions/Visual/TweenScale.cs +++ b/Runtime/Actions/Visual/TweenScale.cs @@ -12,6 +12,9 @@ namespace Rokojori [Export] public Node3D target; + [Export] + public float endScaleAll = 1f; + [Export] public Vector3 endScale = Vector3.One; @@ -37,7 +40,7 @@ namespace Rokojori var start = tl.position; var fromScale = target.Scale; - var toScale = endScale; + var toScale = endScale * endScaleAll; var sequenceID = DispatchStart(); @@ -64,7 +67,7 @@ namespace Rokojori if ( ! cacheEndPositionOnStart ) { - var toScale = endScale; + var toScale = endScale * endScaleAll; } var lerpedScale = fromScale.Lerp( toScale, state ); diff --git a/Runtime/Animation/Highlight/HighlightEffect.cs b/Runtime/Animation/Highlight/HighlightEffect.cs index d26a4e6..45422f7 100644 --- a/Runtime/Animation/Highlight/HighlightEffect.cs +++ b/Runtime/Animation/Highlight/HighlightEffect.cs @@ -177,7 +177,7 @@ namespace Rokojori RJLog.Log( "Removed animations", numRemoved ); - Lists.RemoveRange( animations, removals ); + Lists.RemoveList( animations, removals ); } diff --git a/Runtime/App/App.cs b/Runtime/App/App.cs index 5816c31..0c59ad4 100644 --- a/Runtime/App/App.cs +++ b/Runtime/App/App.cs @@ -37,6 +37,31 @@ namespace Rokojori [Export] public AppLauncher launcher; + [Export] + public AppSettings settings; + + [Export] + public Action onAppStart; + + Dictionary _settingsData = new Dictionary(); + public Dictionary GetAppSettingsData() =>_settingsData; + + public string GetSetting( AppSetting appSetting ) + { + return _settingsData.ContainsKey( appSetting.id ) ? _settingsData[ appSetting.id ] : appSetting.GetDefaultValue(); + } + + public string GetSetting( string id ) + { + return _settingsData.ContainsKey( id ) ? _settingsData[ id ] : null; + } + + public void SetSetting( string id, string value ) + { + // this.LogInfo( "Set setting:", id, value ); + _settingsData[ id ] = value; + } + int _fps = 60; public int x = 0; @@ -48,7 +73,16 @@ namespace Rokojori set { _fps = value; Engine.MaxFps = _fps; } } - - + public override void _Ready() + { + if ( Engine.IsEditorHint() ) + { + return; + } + + onAppStart?.Trigger(); + } + + } } \ No newline at end of file diff --git a/Runtime/App/Settings/Actions/LoadAppSettings.cs b/Runtime/App/Settings/Actions/LoadAppSettings.cs new file mode 100644 index 0000000..63abe86 --- /dev/null +++ b/Runtime/App/Settings/Actions/LoadAppSettings.cs @@ -0,0 +1,68 @@ + +using Godot; +using System.Collections.Generic; + +namespace Rokojori +{ + [Tool] + [GlobalClass] + public partial class LoadAppSettings:Action + { + [Export] + public string savePath = ""; + + [Export] + public App app; + + [Export] + public bool writeDefaults = true; + + protected override void _OnTrigger() + { + this.LogInfo( "Loading App Settings" ); + + var data = GDFilesSync.LoadJSON>( savePath ); + + this.LogInfo( "App Settings", data ); + + foreach ( var vk in data ) + { + app.settings.ApplySetting( app, vk.Key, vk.Value ); + } + + // var settings = + // this.LogInfo( JSON.StringifyObject( data ) ); + + // var resolvedApp = app ?? Unique.Get(); + + // var data = resolvedApp.GetAppSettingsData(); + + // var saveMap = new Dictionary(); + + // foreach ( var kv in data ){ saveMap[ kv.Key ] = kv.Value; } + + // if ( writeDefaults ) + // { + // app.settings.categories.ForEach( + // ( c )=> + // { + // c.settings.ForEach( + // ( appSetting )=> + // { + // if ( saveMap.ContainsKey( appSetting.id ) ) + // { + // return; + // } + + // saveMap[ appSetting.id ] = appSetting.GetDefaultValue(); + // } + // ); + // } + // ); + // } + + + } + + } +} \ No newline at end of file diff --git a/Runtime/App/Settings/Actions/LoadAppSettings.cs.uid b/Runtime/App/Settings/Actions/LoadAppSettings.cs.uid new file mode 100644 index 0000000..9939ad5 --- /dev/null +++ b/Runtime/App/Settings/Actions/LoadAppSettings.cs.uid @@ -0,0 +1 @@ +uid://bbm2x6as7wvc8 diff --git a/Runtime/App/Settings/Actions/SaveAppSettings.cs b/Runtime/App/Settings/Actions/SaveAppSettings.cs new file mode 100644 index 0000000..ff123d8 --- /dev/null +++ b/Runtime/App/Settings/Actions/SaveAppSettings.cs @@ -0,0 +1,54 @@ + +using Godot; +using System.Collections.Generic; + +namespace Rokojori +{ + [Tool] + [GlobalClass] + public partial class SaveAppSettings:Action + { + [Export] + public string savePath = ""; + + [Export] + public App app; + + [Export] + public bool writeDefaults = true; + + protected override void _OnTrigger() + { + var resolvedApp = app ?? Unique.Get(); + + var data = resolvedApp.GetAppSettingsData(); + + var saveMap = new Dictionary(); + + foreach ( var kv in data ){ saveMap[ kv.Key ] = kv.Value; } + + if ( writeDefaults ) + { + app.settings.categories.ForEach( + ( c )=> + { + c.settings.ForEach( + ( appSetting )=> + { + if ( saveMap.ContainsKey( appSetting.id ) ) + { + return; + } + + saveMap[ appSetting.id ] = appSetting.GetDefaultValue(); + } + ); + } + ); + } + + GDFilesSync.SaveJSON( savePath, saveMap ); + } + + } +} \ No newline at end of file diff --git a/Runtime/App/Settings/Actions/SaveAppSettings.cs.uid b/Runtime/App/Settings/Actions/SaveAppSettings.cs.uid new file mode 100644 index 0000000..ae56f40 --- /dev/null +++ b/Runtime/App/Settings/Actions/SaveAppSettings.cs.uid @@ -0,0 +1 @@ +uid://ctuyiqlpdd4m4 diff --git a/Runtime/App/Settings/AppSetting.cs b/Runtime/App/Settings/AppSetting.cs index f550dec..3ea6cc1 100644 --- a/Runtime/App/Settings/AppSetting.cs +++ b/Runtime/App/Settings/AppSetting.cs @@ -5,13 +5,25 @@ using System.Collections.Generic; namespace Rokojori { [Tool] - [GlobalClass] - public partial class AppSetting:Resource + [GlobalClass,Icon("res://addons/rokojori_action_library/Icons/AppSetting.svg")] + public abstract partial class AppSetting:Resource { - public LocaleText GetName(){ return null; } - public LocaleText GetInfo(){ return null; } + [Export] + public LocalizedString title; + + [Export] + public LocalizedString info; + + [Export] + public string id = ""; + + public abstract string GetDefaultValue(); + public abstract void ApplyValue( App app ); + + public string GetValue( App app ) + { + return app.GetSetting( id ); + } - public string Serialize(){ return null; } - public void SetFromSerialized( string serializedValue ){} } } \ No newline at end of file diff --git a/Runtime/App/Settings/AppSettings.cs b/Runtime/App/Settings/AppSettings.cs new file mode 100644 index 0000000..16aa652 --- /dev/null +++ b/Runtime/App/Settings/AppSettings.cs @@ -0,0 +1,35 @@ + +using Godot; +using System.Collections.Generic; + +namespace Rokojori +{ + [Tool] + [GlobalClass] + public partial class AppSettings:Resource + { + [Export] + public AppSettingsCategory[] categories = []; + + public void ApplySetting( App app, string key, string value ) + { + app.SetSetting( key, value ); + categories.ForEach( + ( c )=> + { + c.settings.ForEach( + ( s)=> + { + if ( s.id != key ) + { + return; + } + + s.ApplyValue( app ); + } + ); + } + ); + } + } +} \ No newline at end of file diff --git a/Runtime/App/Settings/AppSettings.cs.uid b/Runtime/App/Settings/AppSettings.cs.uid new file mode 100644 index 0000000..7b35c9e --- /dev/null +++ b/Runtime/App/Settings/AppSettings.cs.uid @@ -0,0 +1 @@ +uid://c5iowli8mkuoy diff --git a/Runtime/App/Settings/AppSettingsCategory.cs b/Runtime/App/Settings/AppSettingsCategory.cs new file mode 100644 index 0000000..823fe10 --- /dev/null +++ b/Runtime/App/Settings/AppSettingsCategory.cs @@ -0,0 +1,26 @@ + +using Godot; +using System.Collections.Generic; + +namespace Rokojori +{ + [Tool] + [GlobalClass,Icon("res://addons/rokojori_action_library/Icons/AppSettingsCategory.svg")] + public partial class AppSettingsCategory:Resource + { + [Export] + public LocalizedString title; + + [Export] + public LocalizedString info; + + [Export] + public Texture2D icon; + + [Export] + public string id = ""; + + [Export] + public AppSetting[] settings; + } +} \ No newline at end of file diff --git a/Runtime/App/Settings/AppSettingsCategory.cs.uid b/Runtime/App/Settings/AppSettingsCategory.cs.uid new file mode 100644 index 0000000..f554b23 --- /dev/null +++ b/Runtime/App/Settings/AppSettingsCategory.cs.uid @@ -0,0 +1 @@ +uid://b3kfbhiwqt26o diff --git a/Runtime/App/Settings/ListSetting/ListAppSetting.cs b/Runtime/App/Settings/ListSetting/ListAppSetting.cs new file mode 100644 index 0000000..ade25d8 --- /dev/null +++ b/Runtime/App/Settings/ListSetting/ListAppSetting.cs @@ -0,0 +1,26 @@ + +using Godot; +using System.Collections.Generic; + +namespace Rokojori +{ + [Tool] + [GlobalClass] + public abstract partial class ListAppSetting:AppSetting + { + [Export] + public LocalizedString[] values = []; + + [Export] + public int defaultValueIndex = 0; + + + public override string GetDefaultValue() + { + return JSON.StringifyObject( values[ defaultValueIndex ] ); + } + + + + } +} \ No newline at end of file diff --git a/Runtime/App/Settings/ListSetting/ListAppSetting.cs.uid b/Runtime/App/Settings/ListSetting/ListAppSetting.cs.uid new file mode 100644 index 0000000..870fcf0 --- /dev/null +++ b/Runtime/App/Settings/ListSetting/ListAppSetting.cs.uid @@ -0,0 +1 @@ +uid://cgo3gvs8q2oon diff --git a/Runtime/App/Settings/ListSetting/TestingListAppSettings.cs b/Runtime/App/Settings/ListSetting/TestingListAppSettings.cs new file mode 100644 index 0000000..f5564b8 --- /dev/null +++ b/Runtime/App/Settings/ListSetting/TestingListAppSettings.cs @@ -0,0 +1,17 @@ + +using Godot; +using System.Collections.Generic; + +namespace Rokojori +{ + [Tool] + [GlobalClass] + public partial class TestingListAppSetting:NumberAppSetting + { + public override void ApplyValue( App app ) + { + var stringValue = app.GetSetting( id ); + RJLog.Log( "Test value is:", stringValue ); + } + } +} \ No newline at end of file diff --git a/Runtime/App/Settings/ListSetting/TestingListAppSettings.cs.uid b/Runtime/App/Settings/ListSetting/TestingListAppSettings.cs.uid new file mode 100644 index 0000000..a7e9b3b --- /dev/null +++ b/Runtime/App/Settings/ListSetting/TestingListAppSettings.cs.uid @@ -0,0 +1 @@ +uid://deyg247xjr2mu diff --git a/Runtime/App/Settings/NumberSetting/AudioBusSetting.cs b/Runtime/App/Settings/NumberSetting/AudioBusSetting.cs new file mode 100644 index 0000000..2f73a67 --- /dev/null +++ b/Runtime/App/Settings/NumberSetting/AudioBusSetting.cs @@ -0,0 +1,33 @@ + +using Godot; +using System.Collections.Generic; + +namespace Rokojori +{ + [Tool] + [GlobalClass] + public partial class AudioBusSetting:NumberAppSetting + { + [Export] + public string busName = ""; + + public override void ApplyValue( App app ) + { + var stringValue = app.GetSetting( id ); + var floatValue = RegexUtility.ParseFloat( stringValue ); + + var busIndex = AudioServer.GetBusIndex( busName ); + + if ( busIndex == -1 ) + { + this.LogError( "Audio bus not found:", busName ); + return; + } + + + AudioServer.SetBusVolumeLinear( busIndex, NormalizeValue( floatValue ) ); + } + + + } +} \ No newline at end of file diff --git a/Runtime/App/Settings/NumberSetting/AudioBusSetting.cs.uid b/Runtime/App/Settings/NumberSetting/AudioBusSetting.cs.uid new file mode 100644 index 0000000..63b9ef4 --- /dev/null +++ b/Runtime/App/Settings/NumberSetting/AudioBusSetting.cs.uid @@ -0,0 +1 @@ +uid://dji3qa0w7pbql diff --git a/Runtime/App/Settings/NumberSetting/NumberAppSetting.cs b/Runtime/App/Settings/NumberSetting/NumberAppSetting.cs new file mode 100644 index 0000000..202b2a7 --- /dev/null +++ b/Runtime/App/Settings/NumberSetting/NumberAppSetting.cs @@ -0,0 +1,48 @@ + +using Godot; +using System.Collections.Generic; + +namespace Rokojori +{ + [Tool] + [GlobalClass] + public abstract partial class NumberAppSetting:AppSetting + { + [Export] + public LocalizedString prefix; + + [Export] + public float min = 0; + + [Export] + public float max = 1; + + [Export] + public float defaultValue = 0.5f; + + [Export] + public int steps = -1; + + [Export] + public float stepSize = -1; + + [Export] + public UIFloatValueMode.DecimialPoints decimialPoints = UIFloatValueMode.DecimialPoints.Int; + + [Export] + public LocalizedString suffix; + + public float NormalizeValue( float v ) + { + return MathX.Normalize( v, min, max ); + } + + public override string GetDefaultValue() + { + return JSON.StringifyObject( defaultValue ); + } + + + + } +} \ No newline at end of file diff --git a/Runtime/App/Settings/NumberSetting/NumberAppSetting.cs.uid b/Runtime/App/Settings/NumberSetting/NumberAppSetting.cs.uid new file mode 100644 index 0000000..361fb3b --- /dev/null +++ b/Runtime/App/Settings/NumberSetting/NumberAppSetting.cs.uid @@ -0,0 +1 @@ +uid://bowpfiftk8xyq diff --git a/Runtime/App/Settings/NumberSetting/ResolutionScalingSetting.cs b/Runtime/App/Settings/NumberSetting/ResolutionScalingSetting.cs new file mode 100644 index 0000000..cb17349 --- /dev/null +++ b/Runtime/App/Settings/NumberSetting/ResolutionScalingSetting.cs @@ -0,0 +1,25 @@ + +using Godot; +using System.Collections.Generic; + +namespace Rokojori +{ + [Tool] + [GlobalClass] + public partial class ResolutionScalingSetting:NumberAppSetting + { + [Export] + public float userScaleToResolutionScale = 1f/100f; + + public override void ApplyValue( App app ) + { + var stringValue = app.GetSetting( id ); + var floatValue = RegexUtility.ParseFloat( stringValue ); + + var viewport = app.GetViewport(); + viewport.Scaling3DScale = floatValue * userScaleToResolutionScale; + } + + + } +} \ No newline at end of file diff --git a/Runtime/App/Settings/NumberSetting/ResolutionScalingSetting.cs.uid b/Runtime/App/Settings/NumberSetting/ResolutionScalingSetting.cs.uid new file mode 100644 index 0000000..afa5600 --- /dev/null +++ b/Runtime/App/Settings/NumberSetting/ResolutionScalingSetting.cs.uid @@ -0,0 +1 @@ +uid://ck1jjpy2gvkk4 diff --git a/Runtime/App/Settings/NumberSetting/TestingNumberAppSetting.cs b/Runtime/App/Settings/NumberSetting/TestingNumberAppSetting.cs new file mode 100644 index 0000000..d0d943f --- /dev/null +++ b/Runtime/App/Settings/NumberSetting/TestingNumberAppSetting.cs @@ -0,0 +1,17 @@ + +using Godot; +using System.Collections.Generic; + +namespace Rokojori +{ + [Tool] + [GlobalClass] + public partial class TestingNumberAppSetting:NumberAppSetting + { + public override void ApplyValue( App app ) + { + var stringValue = app.GetSetting( id ); + RJLog.Log( "Test value is:", stringValue ); + } + } +} \ No newline at end of file diff --git a/Runtime/App/Settings/NumberSetting/TestingNumberAppSetting.cs.uid b/Runtime/App/Settings/NumberSetting/TestingNumberAppSetting.cs.uid new file mode 100644 index 0000000..3ddf69f --- /dev/null +++ b/Runtime/App/Settings/NumberSetting/TestingNumberAppSetting.cs.uid @@ -0,0 +1 @@ +uid://en53sdt3fmlj diff --git a/Runtime/App/Settings/NumberSetting/UIFontScaleSetting.cs b/Runtime/App/Settings/NumberSetting/UIFontScaleSetting.cs new file mode 100644 index 0000000..c0561e1 --- /dev/null +++ b/Runtime/App/Settings/NumberSetting/UIFontScaleSetting.cs @@ -0,0 +1,30 @@ + +using Godot; +using System.Collections.Generic; + +namespace Rokojori +{ + [Tool] + [GlobalClass] + public partial class UIFontScaleSetting:NumberAppSetting + { + [Export] + public float userScaleToFontZoom = 1f/100f; + + public override void ApplyValue( App app ) + { + var stringValue = app.GetSetting( id ); + var floatValue = RegexUtility.ParseFloat( stringValue ); + + var uis = Nodes.AllInScene(); + uis.ForEach( + ( ui )=> + { + ui.fontZoom = userScaleToFontZoom * floatValue; + } + ); + } + + + } +} \ No newline at end of file diff --git a/Runtime/App/Settings/NumberSetting/UIFontScaleSetting.cs.uid b/Runtime/App/Settings/NumberSetting/UIFontScaleSetting.cs.uid new file mode 100644 index 0000000..4d945d0 --- /dev/null +++ b/Runtime/App/Settings/NumberSetting/UIFontScaleSetting.cs.uid @@ -0,0 +1 @@ +uid://bj27trgy8poyy diff --git a/Runtime/App/Settings/Presets/Audio/Audio Category.tres b/Runtime/App/Settings/Presets/Audio/Audio Category.tres new file mode 100644 index 0000000..adc0c21 --- /dev/null +++ b/Runtime/App/Settings/Presets/Audio/Audio Category.tres @@ -0,0 +1,15 @@ +[gd_resource type="Resource" script_class="AppSettingsCategory" load_steps=7 format=3 uid="uid://cewutd6leekw6"] + +[ext_resource type="Script" uid="uid://b3kfbhiwqt26o" path="res://addons/rokojori_action_library/Runtime/App/Settings/AppSettingsCategory.cs" id="1_p3j14"] +[ext_resource type="Resource" uid="uid://y3wia1vd1q68" path="res://addons/rokojori_action_library/Runtime/App/Settings/Presets/Audio/Master AudioBus Setting.tres" id="2_1g5c8"] +[ext_resource type="Resource" uid="uid://b24rm0ggveq8y" path="res://addons/rokojori_action_library/Runtime/App/Settings/Presets/Audio/Music AudioBus Setting.tres" id="3_25bee"] +[ext_resource type="Resource" uid="uid://da34tyk6d0l4b" path="res://addons/rokojori_action_library/Runtime/App/Settings/Presets/Audio/SFX AudioBus Setting.tres" id="4_bgbml"] +[ext_resource type="Resource" uid="uid://ckpuhu87npn2l" path="res://addons/rokojori_action_library/Runtime/App/Settings/Presets/Audio/VOX AudioBus Setting.tres" id="5_pt3u0"] +[ext_resource type="Resource" uid="uid://dn5qwc0t4llho" path="res://addons/rokojori_action_library/Runtime/App/Settings/Presets/Audio/Audio Label.tres" id="6_imd2x"] + +[resource] +script = ExtResource("1_p3j14") +title = ExtResource("6_imd2x") +id = "audio" +settings = [ExtResource("2_1g5c8"), ExtResource("3_25bee"), ExtResource("4_bgbml"), ExtResource("5_pt3u0")] +metadata/_custom_type_script = "uid://b3kfbhiwqt26o" diff --git a/Runtime/App/Settings/Presets/Audio/Audio Label.tres b/Runtime/App/Settings/Presets/Audio/Audio Label.tres new file mode 100644 index 0000000..8231638 --- /dev/null +++ b/Runtime/App/Settings/Presets/Audio/Audio Label.tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="LocaleText" load_steps=2 format=3 uid="uid://dn5qwc0t4llho"] + +[ext_resource type="Script" uid="uid://bvj322mokkq63" path="res://addons/rokojori_action_library/Runtime/Localization/LocaleText.cs" id="1_i1gki"] + +[resource] +script = ExtResource("1_i1gki") +en = "Audio" +metadata/_custom_type_script = "uid://bvj322mokkq63" diff --git a/Runtime/App/Settings/Presets/Audio/Main Volume Label.tres b/Runtime/App/Settings/Presets/Audio/Main Volume Label.tres new file mode 100644 index 0000000..0258f41 --- /dev/null +++ b/Runtime/App/Settings/Presets/Audio/Main Volume Label.tres @@ -0,0 +1,16 @@ +[gd_resource type="Resource" script_class="LocaleText" load_steps=4 format=3 uid="uid://ph4irn16ygj4"] + +[ext_resource type="Script" uid="uid://b584767duemqk" path="res://addons/rokojori_action_library/Runtime/Localization/LocaleTextEntry.cs" id="1_uqcpa"] +[ext_resource type="Script" uid="uid://bvj322mokkq63" path="res://addons/rokojori_action_library/Runtime/Localization/LocaleText.cs" id="2_is7nr"] + +[sub_resource type="Resource" id="Resource_sjqn2"] +script = ExtResource("1_uqcpa") +code = 12 +content = "Gesamt Lautstärke" +metadata/_custom_type_script = "uid://b584767duemqk" + +[resource] +script = ExtResource("2_is7nr") +en = "Main Volume" +entries = [SubResource("Resource_sjqn2")] +metadata/_custom_type_script = "uid://bvj322mokkq63" diff --git a/Runtime/App/Settings/Presets/Audio/Master AudioBus Setting.tres b/Runtime/App/Settings/Presets/Audio/Master AudioBus Setting.tres new file mode 100644 index 0000000..afc3b68 --- /dev/null +++ b/Runtime/App/Settings/Presets/Audio/Master AudioBus Setting.tres @@ -0,0 +1,15 @@ +[gd_resource type="Resource" script_class="AudioBusSetting" load_steps=4 format=3 uid="uid://y3wia1vd1q68"] + +[ext_resource type="Script" uid="uid://dji3qa0w7pbql" path="res://addons/rokojori_action_library/Runtime/App/Settings/NumberSetting/AudioBusSetting.cs" id="1_og01v"] +[ext_resource type="Resource" uid="uid://osfjg5u2jb4f" path="res://addons/rokojori_action_library/Runtime/Localization/DataBase/Numberic/Percantage-Suffix.tres" id="2_j708b"] +[ext_resource type="Resource" uid="uid://ph4irn16ygj4" path="res://addons/rokojori_action_library/Runtime/App/Settings/Presets/Audio/Main Volume Label.tres" id="3_fm56v"] + +[resource] +script = ExtResource("1_og01v") +busName = "Master" +max = 100.0 +defaultValue = 50.0 +suffix = ExtResource("2_j708b") +title = ExtResource("3_fm56v") +id = "mainVolume" +metadata/_custom_type_script = "uid://dji3qa0w7pbql" diff --git a/Runtime/App/Settings/Presets/Audio/Music AudioBus Setting.tres b/Runtime/App/Settings/Presets/Audio/Music AudioBus Setting.tres new file mode 100644 index 0000000..544229a --- /dev/null +++ b/Runtime/App/Settings/Presets/Audio/Music AudioBus Setting.tres @@ -0,0 +1,15 @@ +[gd_resource type="Resource" script_class="AudioBusSetting" load_steps=4 format=3 uid="uid://b24rm0ggveq8y"] + +[ext_resource type="Script" uid="uid://dji3qa0w7pbql" path="res://addons/rokojori_action_library/Runtime/App/Settings/NumberSetting/AudioBusSetting.cs" id="1_clrqb"] +[ext_resource type="Resource" uid="uid://osfjg5u2jb4f" path="res://addons/rokojori_action_library/Runtime/Localization/DataBase/Numberic/Percantage-Suffix.tres" id="2_bhjsn"] +[ext_resource type="Resource" uid="uid://dldn6o3wvxfdc" path="res://addons/rokojori_action_library/Runtime/App/Settings/Presets/Audio/Music Label.tres" id="3_vjtyo"] + +[resource] +script = ExtResource("1_clrqb") +busName = "Music" +max = 100.0 +defaultValue = 50.0 +suffix = ExtResource("2_bhjsn") +title = ExtResource("3_vjtyo") +id = "musicVolume" +metadata/_custom_type_script = "uid://dji3qa0w7pbql" diff --git a/Runtime/App/Settings/Presets/Audio/Music Label.tres b/Runtime/App/Settings/Presets/Audio/Music Label.tres new file mode 100644 index 0000000..8329ff1 --- /dev/null +++ b/Runtime/App/Settings/Presets/Audio/Music Label.tres @@ -0,0 +1,16 @@ +[gd_resource type="Resource" script_class="LocaleText" load_steps=4 format=3 uid="uid://dldn6o3wvxfdc"] + +[ext_resource type="Script" uid="uid://b584767duemqk" path="res://addons/rokojori_action_library/Runtime/Localization/LocaleTextEntry.cs" id="1_1ce4q"] +[ext_resource type="Script" uid="uid://bvj322mokkq63" path="res://addons/rokojori_action_library/Runtime/Localization/LocaleText.cs" id="2_dqscy"] + +[sub_resource type="Resource" id="Resource_sjqn2"] +script = ExtResource("1_1ce4q") +code = 12 +content = "Musik Lautstärke" +metadata/_custom_type_script = "uid://b584767duemqk" + +[resource] +script = ExtResource("2_dqscy") +en = "Music Volume" +entries = [SubResource("Resource_sjqn2")] +metadata/_custom_type_script = "uid://bvj322mokkq63" diff --git a/Runtime/App/Settings/Presets/Audio/SFX AudioBus Setting.tres b/Runtime/App/Settings/Presets/Audio/SFX AudioBus Setting.tres new file mode 100644 index 0000000..e42c2ac --- /dev/null +++ b/Runtime/App/Settings/Presets/Audio/SFX AudioBus Setting.tres @@ -0,0 +1,15 @@ +[gd_resource type="Resource" script_class="AudioBusSetting" load_steps=4 format=3 uid="uid://da34tyk6d0l4b"] + +[ext_resource type="Script" uid="uid://dji3qa0w7pbql" path="res://addons/rokojori_action_library/Runtime/App/Settings/NumberSetting/AudioBusSetting.cs" id="1_04sn2"] +[ext_resource type="Resource" uid="uid://osfjg5u2jb4f" path="res://addons/rokojori_action_library/Runtime/Localization/DataBase/Numberic/Percantage-Suffix.tres" id="2_37v0c"] +[ext_resource type="Resource" uid="uid://ccrwni0het7rl" path="res://addons/rokojori_action_library/Runtime/App/Settings/Presets/Audio/SFX Label.tres" id="3_6duf0"] + +[resource] +script = ExtResource("1_04sn2") +busName = "SFX" +max = 100.0 +defaultValue = 50.0 +suffix = ExtResource("2_37v0c") +title = ExtResource("3_6duf0") +id = "sfxVolume" +metadata/_custom_type_script = "uid://dji3qa0w7pbql" diff --git a/Runtime/App/Settings/Presets/Audio/SFX Label.tres b/Runtime/App/Settings/Presets/Audio/SFX Label.tres new file mode 100644 index 0000000..cd6a373 --- /dev/null +++ b/Runtime/App/Settings/Presets/Audio/SFX Label.tres @@ -0,0 +1,16 @@ +[gd_resource type="Resource" script_class="LocaleText" load_steps=4 format=3 uid="uid://ccrwni0het7rl"] + +[ext_resource type="Script" uid="uid://b584767duemqk" path="res://addons/rokojori_action_library/Runtime/Localization/LocaleTextEntry.cs" id="1_3r5aw"] +[ext_resource type="Script" uid="uid://bvj322mokkq63" path="res://addons/rokojori_action_library/Runtime/Localization/LocaleText.cs" id="2_voo1w"] + +[sub_resource type="Resource" id="Resource_sjqn2"] +script = ExtResource("1_3r5aw") +code = 12 +content = "SFX Lautstärke" +metadata/_custom_type_script = "uid://b584767duemqk" + +[resource] +script = ExtResource("2_voo1w") +en = "SFX Volume" +entries = [SubResource("Resource_sjqn2")] +metadata/_custom_type_script = "uid://bvj322mokkq63" diff --git a/Runtime/App/Settings/Presets/Audio/VOX AudioBus Setting.tres b/Runtime/App/Settings/Presets/Audio/VOX AudioBus Setting.tres new file mode 100644 index 0000000..8573416 --- /dev/null +++ b/Runtime/App/Settings/Presets/Audio/VOX AudioBus Setting.tres @@ -0,0 +1,15 @@ +[gd_resource type="Resource" script_class="AudioBusSetting" load_steps=4 format=3 uid="uid://ckpuhu87npn2l"] + +[ext_resource type="Script" uid="uid://dji3qa0w7pbql" path="res://addons/rokojori_action_library/Runtime/App/Settings/NumberSetting/AudioBusSetting.cs" id="1_paelx"] +[ext_resource type="Resource" uid="uid://osfjg5u2jb4f" path="res://addons/rokojori_action_library/Runtime/Localization/DataBase/Numberic/Percantage-Suffix.tres" id="2_s0edn"] +[ext_resource type="Resource" uid="uid://cg2e4yctcmhgy" path="res://addons/rokojori_action_library/Runtime/App/Settings/Presets/Audio/VOX Label.tres" id="3_e4vca"] + +[resource] +script = ExtResource("1_paelx") +busName = "Vox" +max = 100.0 +defaultValue = 50.0 +suffix = ExtResource("2_s0edn") +title = ExtResource("3_e4vca") +id = "voxVolume" +metadata/_custom_type_script = "uid://dji3qa0w7pbql" diff --git a/Runtime/App/Settings/Presets/Audio/VOX Label.tres b/Runtime/App/Settings/Presets/Audio/VOX Label.tres new file mode 100644 index 0000000..7c62a4a --- /dev/null +++ b/Runtime/App/Settings/Presets/Audio/VOX Label.tres @@ -0,0 +1,16 @@ +[gd_resource type="Resource" script_class="LocaleText" load_steps=4 format=3 uid="uid://cg2e4yctcmhgy"] + +[ext_resource type="Script" uid="uid://b584767duemqk" path="res://addons/rokojori_action_library/Runtime/Localization/LocaleTextEntry.cs" id="1_jpt7d"] +[ext_resource type="Script" uid="uid://bvj322mokkq63" path="res://addons/rokojori_action_library/Runtime/Localization/LocaleText.cs" id="2_xqj8d"] + +[sub_resource type="Resource" id="Resource_sjqn2"] +script = ExtResource("1_jpt7d") +code = 12 +content = "Sprach Lautstärke" +metadata/_custom_type_script = "uid://b584767duemqk" + +[resource] +script = ExtResource("2_xqj8d") +en = "Voice Volume" +entries = [SubResource("Resource_sjqn2")] +metadata/_custom_type_script = "uid://bvj322mokkq63" diff --git a/Runtime/App/Settings/Presets/Graphics/Graphics Category.tres b/Runtime/App/Settings/Presets/Graphics/Graphics Category.tres new file mode 100644 index 0000000..a79fd9b --- /dev/null +++ b/Runtime/App/Settings/Presets/Graphics/Graphics Category.tres @@ -0,0 +1,13 @@ +[gd_resource type="Resource" script_class="AppSettingsCategory" load_steps=5 format=3 uid="uid://4iqfk01k81nc"] + +[ext_resource type="Script" uid="uid://b3kfbhiwqt26o" path="res://addons/rokojori_action_library/Runtime/App/Settings/AppSettingsCategory.cs" id="1_g7ii0"] +[ext_resource type="Resource" uid="uid://0itt52s066qp" path="res://addons/rokojori_action_library/Runtime/App/Settings/Presets/Graphics/UI Scale Setting.tres" id="2_xi6qd"] +[ext_resource type="Resource" uid="uid://bpfrw7y8jx2wp" path="res://addons/rokojori_action_library/Runtime/App/Settings/Presets/Graphics/Graphics Label.tres" id="3_g7ii0"] +[ext_resource type="Resource" uid="uid://cec7500hcn1e0" path="res://addons/rokojori_action_library/Runtime/App/Settings/Presets/Graphics/Resolution Scale Setting.tres" id="3_xi6qd"] + +[resource] +script = ExtResource("1_g7ii0") +title = ExtResource("3_g7ii0") +id = "graphics" +settings = [ExtResource("3_xi6qd"), ExtResource("2_xi6qd")] +metadata/_custom_type_script = "uid://b3kfbhiwqt26o" diff --git a/Runtime/App/Settings/Presets/Graphics/Graphics Label.tres b/Runtime/App/Settings/Presets/Graphics/Graphics Label.tres new file mode 100644 index 0000000..9ad5bda --- /dev/null +++ b/Runtime/App/Settings/Presets/Graphics/Graphics Label.tres @@ -0,0 +1,15 @@ +[gd_resource type="Resource" script_class="LocaleText" load_steps=4 format=3 uid="uid://bpfrw7y8jx2wp"] + +[ext_resource type="Script" uid="uid://b584767duemqk" path="res://addons/rokojori_action_library/Runtime/Localization/LocaleTextEntry.cs" id="1_q1oe3"] +[ext_resource type="Script" uid="uid://bvj322mokkq63" path="res://addons/rokojori_action_library/Runtime/Localization/LocaleText.cs" id="2_s1eae"] + +[sub_resource type="Resource" id="Resource_133rj"] +script = ExtResource("1_q1oe3") +content = "Grafik" +metadata/_custom_type_script = "uid://b584767duemqk" + +[resource] +script = ExtResource("2_s1eae") +en = "Graphics" +entries = [SubResource("Resource_133rj")] +metadata/_custom_type_script = "uid://bvj322mokkq63" diff --git a/Runtime/App/Settings/Presets/Graphics/Resolution Scale Label.tres b/Runtime/App/Settings/Presets/Graphics/Resolution Scale Label.tres new file mode 100644 index 0000000..faa134c --- /dev/null +++ b/Runtime/App/Settings/Presets/Graphics/Resolution Scale Label.tres @@ -0,0 +1,16 @@ +[gd_resource type="Resource" script_class="LocaleText" load_steps=4 format=3 uid="uid://ckevpvf37gsu0"] + +[ext_resource type="Script" uid="uid://b584767duemqk" path="res://addons/rokojori_action_library/Runtime/Localization/LocaleTextEntry.cs" id="1_jucsw"] +[ext_resource type="Script" uid="uid://bvj322mokkq63" path="res://addons/rokojori_action_library/Runtime/Localization/LocaleText.cs" id="2_d7iky"] + +[sub_resource type="Resource" id="Resource_0xy14"] +script = ExtResource("1_jucsw") +code = 12 +content = "Auflösungs-Skalierung" +metadata/_custom_type_script = "uid://b584767duemqk" + +[resource] +script = ExtResource("2_d7iky") +en = "Resolution Scale" +entries = [SubResource("Resource_0xy14")] +metadata/_custom_type_script = "uid://bvj322mokkq63" diff --git a/Runtime/App/Settings/Presets/Graphics/Resolution Scale Setting.tres b/Runtime/App/Settings/Presets/Graphics/Resolution Scale Setting.tres new file mode 100644 index 0000000..65085d4 --- /dev/null +++ b/Runtime/App/Settings/Presets/Graphics/Resolution Scale Setting.tres @@ -0,0 +1,33 @@ +[gd_resource type="Resource" script_class="ResolutionScalingSetting" load_steps=7 format=3 uid="uid://cec7500hcn1e0"] + +[ext_resource type="Script" uid="uid://ck1jjpy2gvkk4" path="res://addons/rokojori_action_library/Runtime/App/Settings/NumberSetting/ResolutionScalingSetting.cs" id="1_1x5jf"] +[ext_resource type="Script" uid="uid://bvj322mokkq63" path="res://addons/rokojori_action_library/Runtime/Localization/LocaleText.cs" id="2_irwt0"] +[ext_resource type="Script" uid="uid://b584767duemqk" path="res://addons/rokojori_action_library/Runtime/Localization/LocaleTextEntry.cs" id="3_831il"] + +[sub_resource type="Resource" id="Resource_4ajq1"] +script = ExtResource("2_irwt0") +en = "%" +metadata/_custom_type_script = "uid://bvj322mokkq63" + +[sub_resource type="Resource" id="Resource_0xy14"] +script = ExtResource("3_831il") +code = 12 +content = "Auflösungs-Skalierung" +metadata/_custom_type_script = "uid://b584767duemqk" + +[sub_resource type="Resource" id="Resource_7auxo"] +script = ExtResource("2_irwt0") +en = "Resolution Scale" +entries = [SubResource("Resource_0xy14")] +metadata/_custom_type_script = "uid://bvj322mokkq63" + +[resource] +script = ExtResource("1_1x5jf") +min = 10.0 +max = 150.0 +defaultValue = 100.0 +stepSize = 5.0 +suffix = SubResource("Resource_4ajq1") +title = SubResource("Resource_7auxo") +id = "resolutionScale" +metadata/_custom_type_script = "uid://ck1jjpy2gvkk4" diff --git a/Runtime/App/Settings/Presets/Graphics/UI Scale Setting.tres b/Runtime/App/Settings/Presets/Graphics/UI Scale Setting.tres new file mode 100644 index 0000000..cce2c7b --- /dev/null +++ b/Runtime/App/Settings/Presets/Graphics/UI Scale Setting.tres @@ -0,0 +1,28 @@ +[gd_resource type="Resource" script_class="UIFontScaleSetting" load_steps=7 format=3 uid="uid://0itt52s066qp"] + +[ext_resource type="Script" uid="uid://bj27trgy8poyy" path="res://addons/rokojori_action_library/Runtime/App/Settings/NumberSetting/UIFontScaleSetting.cs" id="1_5l5ka"] +[ext_resource type="Resource" uid="uid://osfjg5u2jb4f" path="res://addons/rokojori_action_library/Runtime/Localization/DataBase/Numberic/Percantage-Suffix.tres" id="2_1r4kl"] +[ext_resource type="Script" uid="uid://b584767duemqk" path="res://addons/rokojori_action_library/Runtime/Localization/LocaleTextEntry.cs" id="3_ta5nt"] +[ext_resource type="Script" uid="uid://bvj322mokkq63" path="res://addons/rokojori_action_library/Runtime/Localization/LocaleText.cs" id="4_mrecg"] + +[sub_resource type="Resource" id="Resource_cviq7"] +script = ExtResource("3_ta5nt") +code = 12 +content = "UI Skalierung" +metadata/_custom_type_script = "uid://b584767duemqk" + +[sub_resource type="Resource" id="Resource_avygq"] +script = ExtResource("4_mrecg") +en = "UI Scale" +entries = [SubResource("Resource_cviq7")] +metadata/_custom_type_script = "uid://bvj322mokkq63" + +[resource] +script = ExtResource("1_5l5ka") +min = 75.0 +max = 150.0 +defaultValue = 100.0 +suffix = ExtResource("2_1r4kl") +title = SubResource("Resource_avygq") +id = "uiScale" +metadata/_custom_type_script = "uid://bj27trgy8poyy" diff --git a/Runtime/Audio/Presets/Default-Audio-Channel-Layout.tres b/Runtime/Audio/Presets/Default-Audio-Channel-Layout.tres new file mode 100644 index 0000000..174186e --- /dev/null +++ b/Runtime/Audio/Presets/Default-Audio-Channel-Layout.tres @@ -0,0 +1,21 @@ +[gd_resource type="AudioBusLayout" format=3 uid="uid://b588mdjuo56ut"] + +[resource] +bus/1/name = &"Music" +bus/1/solo = false +bus/1/mute = false +bus/1/bypass_fx = false +bus/1/volume_db = 0.0 +bus/1/send = &"Master" +bus/2/name = &"SFX" +bus/2/solo = false +bus/2/mute = false +bus/2/bypass_fx = false +bus/2/volume_db = 0.0 +bus/2/send = &"Master" +bus/3/name = &"Vox" +bus/3/solo = false +bus/3/mute = false +bus/3/bypass_fx = false +bus/3/volume_db = 0.0 +bus/3/send = &"Master" diff --git a/Runtime/Cameras/CameraTypes/FirstPersonCamera/FirstPersonCamera.cs b/Runtime/Cameras/CameraTypes/FirstPersonCamera/FirstPersonCamera.cs index 6208a76..0ddd7cd 100644 --- a/Runtime/Cameras/CameraTypes/FirstPersonCamera/FirstPersonCamera.cs +++ b/Runtime/Cameras/CameraTypes/FirstPersonCamera/FirstPersonCamera.cs @@ -12,6 +12,12 @@ namespace Rokojori [GlobalClass, Icon("res://addons/rokojori_action_library/Icons/1stPersonCamera.svg") ] public partial class FirstPersonCamera:VirtualCamera { + [Export] + public float fov = 60; + public override float GetCameraFOV() + { + return fov; + } } } \ No newline at end of file diff --git a/Runtime/Cameras/CameraTypes/FollowCamera/FollowCamera3D.cs b/Runtime/Cameras/CameraTypes/FollowCamera/FollowCamera3D.cs index 758f24e..033dc0c 100644 --- a/Runtime/Cameras/CameraTypes/FollowCamera/FollowCamera3D.cs +++ b/Runtime/Cameras/CameraTypes/FollowCamera/FollowCamera3D.cs @@ -21,6 +21,14 @@ namespace Rokojori [Export] public float rotationSmoothingCoefficient = 0.1f; + [Export] + public float fov = 60; + + public override float GetCameraFOV() + { + return fov; + } + Smoother smoother = new Smoother(); public override void _Process( double delta ) diff --git a/Runtime/Cameras/CameraTypes/LookAtCamera/LookAtCamera.cs b/Runtime/Cameras/CameraTypes/LookAtCamera/LookAtCamera.cs index 9ffda99..2128658 100644 --- a/Runtime/Cameras/CameraTypes/LookAtCamera/LookAtCamera.cs +++ b/Runtime/Cameras/CameraTypes/LookAtCamera/LookAtCamera.cs @@ -15,12 +15,21 @@ namespace Rokojori [Export] public Node3D target; + [Export] + public float fov = 60; + + public override float GetCameraFOV() + { + return fov; + } + [Export] public Smoothing smoothing; [Export] public TimeLine timeLine; + [ExportToolButton( "Copy Camera Pose With Target")] public Callable copyCameraPoseWithTargetButton => Callable.From( ()=> diff --git a/Runtime/Cameras/CameraTypes/StrategyTopDownCamera/StrategyTopDownCamera.cs b/Runtime/Cameras/CameraTypes/StrategyTopDownCamera/StrategyTopDownCamera.cs index 9446cf2..d034d68 100644 --- a/Runtime/Cameras/CameraTypes/StrategyTopDownCamera/StrategyTopDownCamera.cs +++ b/Runtime/Cameras/CameraTypes/StrategyTopDownCamera/StrategyTopDownCamera.cs @@ -122,7 +122,15 @@ namespace Rokojori [Export] public float zoomSmoothingCoefficient = 0.1f; - Smoother smoother = new Smoother(); + Smoother smoother = new Smoother(); + + [Export] + public float fov = 60; + + public override float GetCameraFOV() + { + return fov; + } public override void _Process( double delta ) { diff --git a/Runtime/Cameras/CameraTypes/ThirdPersonCamera/ThirdPersonCamera.cs b/Runtime/Cameras/CameraTypes/ThirdPersonCamera/ThirdPersonCamera.cs index a125aa1..15889d8 100644 --- a/Runtime/Cameras/CameraTypes/ThirdPersonCamera/ThirdPersonCamera.cs +++ b/Runtime/Cameras/CameraTypes/ThirdPersonCamera/ThirdPersonCamera.cs @@ -46,10 +46,10 @@ namespace Rokojori void _ProcessCamera( double gameDelta ) { - if ( Engine.IsEditorHint() ) - { - return; - } + // if ( Engine.IsEditorHint() ) + // { + // return; + // } if ( target == null ) { @@ -93,14 +93,53 @@ namespace Rokojori var smoothedPitch = Smoothing.Apply( settings.pitchSmoothing, pitch, delta ); - var distance = settings.distanceForPitch.Sample( MathX.NormalizeClamped( pitch, settings.minPitch, settings.maxPitch ) ) * settings.distanceScale; + var pitchState = MathX.NormalizeClamped( pitch, settings.minPitch, settings.maxPitch ); + var distance = settings.distanceForPitch.Sample( pitchState ) * settings.distanceScale; + FOV = settings.fovOffset + ( settings.fovForPitch?.Sample( pitchState ) ?? 0f ); - GlobalPosition = targetPosition + Math3D.YawPitchRotation( smoothedYaw, smoothedPitch ) * Vector3.Forward * distance; + cameraPosition = targetPosition + Math3D.YawPitchRotation( smoothedYaw, smoothedPitch ) * Vector3.Forward * distance; - LookAt( targetPosition, Vector3.Up, true ); + cameraForward = ( targetPosition - cameraPosition ).Normalized(); + // LookAt( targetPosition, Vector3.Up, true ); - GlobalPosition += this.GetOrientationBasedGlobalOffset( settings.offset ); + var pitchOffset = settings.offset; + + pitchOffset.X += settings.offsetXForPitch?.Sample( pitchState ) ?? 0f; + pitchOffset.Y += settings.offsetYForPitch?.Sample( pitchState ) ?? 0f; + pitchOffset.Z += settings.offsetZForPitch?.Sample( pitchState ) ?? 0f; + var basis = Basis.LookingAt( cameraForward, Vector3.Up, true ); + cameraPosition += basis.ToGlobalDirection( pitchOffset ); + + cameraRotation = new Quaternion( basis ); + } + + [Export,ReadOnly] + public Vector3 cameraPosition; + + public override Vector3 GetCameraPosition() + { + return cameraPosition; + } + + [Export,ReadOnly] + public Vector3 cameraForward; + + [Export,ReadOnly] + public Quaternion cameraRotation; + + public override Quaternion GetCameraRotation() + { + return cameraRotation; + } + + + [Export,ReadOnly] + public float FOV; + + public override float GetCameraFOV() + { + return FOV; } diff --git a/Runtime/Cameras/CameraTypes/ThirdPersonCamera/ThirdPersonCameraSettings.cs b/Runtime/Cameras/CameraTypes/ThirdPersonCamera/ThirdPersonCameraSettings.cs index b3fcfa2..b41b1c7 100644 --- a/Runtime/Cameras/CameraTypes/ThirdPersonCamera/ThirdPersonCameraSettings.cs +++ b/Runtime/Cameras/CameraTypes/ThirdPersonCamera/ThirdPersonCameraSettings.cs @@ -11,8 +11,7 @@ namespace Rokojori [Export] public Smoothing targetFollowSmoothing = new FrameSmoothing(); - [Export] - public Vector3 offset = Vector3.Zero; + [Export] public Smoothing yawSmoothing = new FrameSmoothing(); @@ -39,12 +38,37 @@ namespace Rokojori [ExportGroup("Distance")] - [Export] - public Curve distanceForPitch = MathX.Curve( 1, 1 ); [Export] public float distanceScale = 1; + [Export] + public Curve distanceForPitch = MathX.Curve( 1, 1 ); + + + + [ExportGroup("Offset")] + + [Export] + public Vector3 offset = Vector3.Zero; + + [Export] + public Curve offsetXForPitch = MathX.Curve( 0, 0 ).WithValueRange( -10, 10 ); + + [Export] + public Curve offsetYForPitch = MathX.Curve( 0, 0 ).WithValueRange( -10, 10 ); + + [Export] + public Curve offsetZForPitch = MathX.Curve( 0, 0 ).WithValueRange( -10, 10 ); + + [ExportGroup("FOV")] + + [Export] + public Curve fovForPitch = MathX.Curve( 0, 0 ).WithValueRange( -10, 10 ); + + [Export] + public float fovOffset = 60; + public float GetNormalizedPitch( float pitch ) { @@ -53,10 +77,27 @@ namespace Rokojori public ThirdPersonCameraData GetActiveDeviceData() { + if ( deviceData == null ) + { + return null; + } + var sm = Unique.Get(); + if ( sm == null ) + { + return deviceData[ 0 ]; + } + + var lastActive = sm.lastActiveDevice; + if ( lastActive == null ) + { + return deviceData[ 0 ]; + } + + var lastActiveData = deviceData.FindNonNull( d => d.deviceSelector.Selects( lastActive ) ); return lastActiveData != null ? lastActiveData : deviceData[ 0 ]; diff --git a/Runtime/Cameras/EditorCamera/EditorCamera.cs b/Runtime/Cameras/EditorCamera/EditorCamera.cs index 2ed23f7..b472a8e 100644 --- a/Runtime/Cameras/EditorCamera/EditorCamera.cs +++ b/Runtime/Cameras/EditorCamera/EditorCamera.cs @@ -38,6 +38,13 @@ namespace Rokojori [Export] public float maxDistance = 200f; + [Export] + public float fov = 60; + + public override float GetCameraFOV() + { + return fov; + } [Export( PropertyHint.Range, "0,600")] public Smoothing zoomSmoothing; diff --git a/Runtime/Cameras/VirtualCamera.cs b/Runtime/Cameras/VirtualCamera.cs index f9daf57..11406b9 100644 --- a/Runtime/Cameras/VirtualCamera.cs +++ b/Runtime/Cameras/VirtualCamera.cs @@ -10,10 +10,8 @@ namespace Rokojori { [Tool] [GlobalClass, Icon("res://addons/rokojori_action_library/Icons/VirtualCamera3D.svg") ] - public partial class VirtualCamera:Node3D + public abstract partial class VirtualCamera:Node3D { - [Export] - public float fov = 60; [Export] public bool inputEnabled = true; @@ -31,20 +29,18 @@ namespace Rokojori } ); - public Vector3 GetCameraPosition() + public virtual Vector3 GetCameraPosition() { return GlobalPosition; } - public Quaternion GetCameraRotation() + public virtual Quaternion GetCameraRotation() { return GlobalBasis.GetRotationQuaternion(); } - public float GetCameraFOV() - { - return fov; - } + public abstract float GetCameraFOV(); + } } \ No newline at end of file diff --git a/Runtime/Events/EventSlot.cs b/Runtime/Events/EventSlot.cs index c879ce0..71d8cda 100644 --- a/Runtime/Events/EventSlot.cs +++ b/Runtime/Events/EventSlot.cs @@ -96,7 +96,7 @@ namespace Rokojori if ( _removals.Count > 0 ) { - Lists.RemoveRange( _actions, _removals ); + Lists.RemoveList( _actions, _removals ); // _removals.ForEach( // r => diff --git a/Runtime/Files/GDFilesSync.cs b/Runtime/Files/GDFilesSync.cs new file mode 100644 index 0000000..c3b37e0 --- /dev/null +++ b/Runtime/Files/GDFilesSync.cs @@ -0,0 +1,44 @@ + +using System; +using Godot; + +namespace Rokojori; + +public class GDFilesSync +{ + public static void SaveJSON( string path, object data ) + { + SaveUTF8( path, JSON.StringifyObject( data ) ); + } + + public static T LoadJSON( string path ) where T:new() + { + return JSON.ParseObject( LoadUTF8( path ) ); + } + + public static void SaveUTF8( string path, string data ) + { + using var fileAccess = FileAccess.Open( path, FileAccess.ModeFlags.Write ); + fileAccess.StoreString( data ); + fileAccess.Close(); + } + + public static string LoadUTF8( string path ) + { + using var fileAccess = FileAccess.Open( path, FileAccess.ModeFlags.Read ); + return fileAccess.GetAsText( ); + } + + public static void SaveBytes( string path, byte[] data ) + { + using var fileAccess = FileAccess.Open( path, FileAccess.ModeFlags.Write ); + fileAccess.StoreBuffer( data ); + fileAccess.Close(); + } + + public static byte[] LoadBytes( string path ) + { + using var fileAccess = FileAccess.Open( path, FileAccess.ModeFlags.Read ); + return fileAccess.GetBuffer( (long) fileAccess.GetLength() ); + } +} diff --git a/Runtime/Files/GDFilesSync.cs.uid b/Runtime/Files/GDFilesSync.cs.uid new file mode 100644 index 0000000..088e6a1 --- /dev/null +++ b/Runtime/Files/GDFilesSync.cs.uid @@ -0,0 +1 @@ +uid://d08fev7gh8nfe diff --git a/Runtime/Godot/Extensions/BasisExtensions.cs b/Runtime/Godot/Extensions/BasisExtensions.cs index 5731967..f5779c9 100644 --- a/Runtime/Godot/Extensions/BasisExtensions.cs +++ b/Runtime/Godot/Extensions/BasisExtensions.cs @@ -7,6 +7,26 @@ namespace Rokojori { public static class BasisExtensions { + public static Vector3 Forward( this Basis self ) + { + return -self.Z; + } + + public static Vector3 Right( this Basis self ) + { + return self.X; + } + + public static Vector3 Up( this Basis self ) + { + return self.Y; + } + + public static Vector3 ToGlobalDirection( this Basis self, Vector3 direction ) + { + return self.Right() * direction.X + self.Up() * direction.Y + self.Forward() * direction; + } + public static bool IsValid( this Basis self ) { return self.Row0.IsValid() && self.Row1.IsValid() && self.Row2.IsValid(); diff --git a/Runtime/Godot/Extensions/NodeExtensions.cs b/Runtime/Godot/Extensions/NodeExtensions.cs index 470a79d..ed163db 100644 --- a/Runtime/Godot/Extensions/NodeExtensions.cs +++ b/Runtime/Godot/Extensions/NodeExtensions.cs @@ -4,12 +4,62 @@ using System.Collections.Generic; using System; using System.Threading.Tasks; using System.Reflection; -using Microsoft.VisualBasic; namespace Rokojori { public static class NodeExtensions { + public static void CallDeferred( this Node node, System.Action action ) + { + Callable.From( action ).CallDeferred(); + } + + + public static int GetChildCountOfType( this Node node ) + { + var count = 0; + + for ( int i = 0; i < node.GetChildCount(); i++ ) + { + if ( node.GetChild( i ) is N ) + { + count ++; + } + } + + return count; + } + + public static void EnsureChildCount( this Node node, int neededChildCount, Action callback = null ) where N:Node,new() + { + var segments = neededChildCount; + var ownCount = node.GetChildCount(); + + if ( ownCount == segments ) + { + return; + } + + + if ( ownCount > segments ) + { + node.DestroyChildrenRange( segments, ownCount - segments ); + + ownCount = segments; + } + + for ( int i = ownCount; i < segments; i++ ) + { + var n = node.CreateChild(); + + if ( callback != null ) + { + callback( n ); + } + } + + } + public static T GetNextSiblingOrChild( this Node node ) where T:Node { var index = node.GetIndex(); diff --git a/Runtime/Godot/Extensions/QuaternionExtensions.cs b/Runtime/Godot/Extensions/QuaternionExtensions.cs index 8c16b21..4c838c4 100644 --- a/Runtime/Godot/Extensions/QuaternionExtensions.cs +++ b/Runtime/Godot/Extensions/QuaternionExtensions.cs @@ -7,6 +7,9 @@ namespace Rokojori { public static class QuaternionExtensions { - + public static Quaternion From( Vector3 forward, Vector3 up ) + { + return Math3D.LookRotation( forward, up ); + } } } \ No newline at end of file diff --git a/Runtime/Godot/NodeStateConfiguration.cs b/Runtime/Godot/NodeStateConfiguration.cs index 65af486..0e42da1 100644 --- a/Runtime/Godot/NodeStateConfiguration.cs +++ b/Runtime/Godot/NodeStateConfiguration.cs @@ -29,6 +29,36 @@ namespace Rokojori [Export] public Node.ProcessModeEnum processMode; + + + public static NodeStateConfiguration All( Trillean value ) + { + var config = new NodeStateConfiguration(); + + config.processEnabled = value; + config.inputEnabled = value; + config.physicsEnabled = value; + config.signalsEnabled = value; + config.visible = value; + + config.setProcessMode = true; + + config.processMode = Trillean.True == value ? Node.ProcessModeEnum.Inherit : Node.ProcessModeEnum.Disabled; + + return config; + } + + public static NodeStateConfiguration AllOn() + { + return All( Trillean.True ); + } + + public static NodeStateConfiguration AllOff() + { + return All( Trillean.False ); + } + + } } \ No newline at end of file diff --git a/Runtime/Godot/Nodes.cs b/Runtime/Godot/Nodes.cs index 876c14b..b2cdd0e 100644 --- a/Runtime/Godot/Nodes.cs +++ b/Runtime/Godot/Nodes.cs @@ -371,7 +371,7 @@ namespace Rokojori } - public static T CreateChild( this Node parent, PackedScene scene, string name = null ) where T:Node,new() + public static T CreateChild( this Node parent, PackedScene scene, string name = null, bool editable = true ) where T:Node,new() { var instance = scene.Instantiate(); @@ -383,6 +383,11 @@ namespace Rokojori instance.Name = name; } + if ( editable ) + { + parent.SetEditableInstance( instance, true ); + } + return instance; } @@ -673,6 +678,31 @@ namespace Rokojori RemoveAndDeleteChildren( parent, includeInternal ); } + public static void DestroyChildAt( this Node parent, int index, bool includeInternal = false, bool queue = true ) + { + var node = parent.GetChild( index, includeInternal ); + parent.RemoveChild( node ); + + if ( ! queue ) + { + node.Free(); + } + else + { + node.QueueFree(); + } + } + + public static void DestroyChildrenRange( this Node parent, int startIndex, int range, bool includeInternal = false, bool queue = true ) + { + parent.LogInfo( startIndex, range, parent.GetChildCount() ); + for ( int i = 0; i < range; i++ ) + { + var index = ( range - 1 ) - i; + parent.DestroyChildAt( index, includeInternal, queue ); + } + } + public static void RemoveAndDeleteChildren( Node parent, bool includeInternal = false, bool queue = true ) { if ( parent == null ) diff --git a/Runtime/Localization/DataBase/Numberic/Percantage-Suffix.tres b/Runtime/Localization/DataBase/Numberic/Percantage-Suffix.tres new file mode 100644 index 0000000..2e46c70 --- /dev/null +++ b/Runtime/Localization/DataBase/Numberic/Percantage-Suffix.tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="LocaleText" load_steps=2 format=3 uid="uid://osfjg5u2jb4f"] + +[ext_resource type="Script" uid="uid://bvj322mokkq63" path="res://addons/rokojori_action_library/Runtime/Localization/LocaleText.cs" id="1_khv63"] + +[resource] +script = ExtResource("1_khv63") +en = "%" +metadata/_custom_type_script = "uid://bvj322mokkq63" diff --git a/Runtime/Math/Geometry/Box3.cs b/Runtime/Math/Geometry/Box3.cs index 08d3b67..8303b8b 100644 --- a/Runtime/Math/Geometry/Box3.cs +++ b/Runtime/Math/Geometry/Box3.cs @@ -31,6 +31,12 @@ namespace Rokojori max += translation; } + public void Extend( float size ) + { + min -= Vector3.One * size / 2f; + max += Vector3.One * size / 2f; + } + public static Box3 FromPositionAndScale( Vector3 position, Vector3 scale ) { var max = scale * 0.5f; diff --git a/Runtime/Math/Geometry/Pose.cs b/Runtime/Math/Geometry/Pose.cs index 31e4122..7252c67 100644 --- a/Runtime/Math/Geometry/Pose.cs +++ b/Runtime/Math/Geometry/Pose.cs @@ -177,6 +177,24 @@ namespace Rokojori return p; } + public static Pose From( Vector3 position, Vector3 forward ) + { + var p = new Pose(); + p.position = position; + p.LookAt( forward, Vector3.Up ); + + return p; + } + + public static Pose From( Vector3 position, Vector3 forward, Vector3 up ) + { + var p = new Pose(); + p.position = position; + p.LookAt( forward, up ); + + return p; + } + public static Pose InverseFrom( Node3D node3D ) { var p = new Pose(); diff --git a/Runtime/Math/Math2D.cs b/Runtime/Math/Math2D.cs index 1c7129a..9bcbed0 100644 --- a/Runtime/Math/Math2D.cs +++ b/Runtime/Math/Math2D.cs @@ -108,6 +108,11 @@ namespace Rokojori return new Vector2( x, y ); } + public static Vector2 CircleDegrees( float degrees, float size = 1 ) + { + return Circle( MathX.DegreesToRadians * degrees, size ); + } + public static Vector2 Fract( Vector2 a ) { return new Vector2( MathX.Fract( a.X ), MathX.Fract( a.Y ) ); diff --git a/Runtime/Math/Math3D.cs b/Runtime/Math/Math3D.cs index 77a5212..f68cf2c 100644 --- a/Runtime/Math/Math3D.cs +++ b/Runtime/Math/Math3D.cs @@ -595,14 +595,8 @@ namespace Rokojori { return Quaternion.Identity; } - - var t = new Transform3D(); - t.Basis = Basis.Identity; - t.Origin = Vector3.Zero; - t = t.LookingAt( direction, up, useModelFront ); - - return t.Basis.GetRotationQuaternion(); + return Basis.LookingAt( direction, up, useModelFront ).GetRotationQuaternion(); } public static Vector3 LerpComponents( Vector3 a, Vector3 b, Vector3 t ) diff --git a/Runtime/Math/MathX.cs b/Runtime/Math/MathX.cs index 2f51c30..f12c662 100644 --- a/Runtime/Math/MathX.cs +++ b/Runtime/Math/MathX.cs @@ -79,6 +79,11 @@ namespace Rokojori return Mathf.Lerp( bottom, top, uvw.Z ); } + public static float LerpClamped( float min, float max, float value ) + { + return Mathf.Clamp( Mathf.Lerp( min, max, value ), min, max ); + } + public static float Fract( float value ) { return value - Mathf.Floor( value ); diff --git a/Runtime/Procedural/Mesh/Generator/CylinderGenerator.cs b/Runtime/Procedural/Mesh/Generator/CylinderGenerator.cs new file mode 100644 index 0000000..0116e25 --- /dev/null +++ b/Runtime/Procedural/Mesh/Generator/CylinderGenerator.cs @@ -0,0 +1,30 @@ +using System.Collections; +using System.Collections.Generic; +using Godot; +using System; + + + +namespace Rokojori +{ + [Tool] + [GlobalClass] + public partial class CylinderGenerator:MeshGeneratorType + { + [Export] + public int vertices = 16; + + [Export] + public int subdivisions = 5; + + protected override string GetCachePath() + { + return "CylinderGenerator-" + vertices + "-x-"+ subdivisions; + } + + protected override MeshGeometry _GenerateMeshGeometry() + { + return MeshGeometry.Cylinder( vertices, subdivisions, 0f, 1f ); + } + } +} \ No newline at end of file diff --git a/Runtime/Procedural/Mesh/Generator/CylinderGenerator.cs.uid b/Runtime/Procedural/Mesh/Generator/CylinderGenerator.cs.uid new file mode 100644 index 0000000..884a401 --- /dev/null +++ b/Runtime/Procedural/Mesh/Generator/CylinderGenerator.cs.uid @@ -0,0 +1 @@ +uid://8bb4srk0y7bi diff --git a/Runtime/Procedural/Mesh/MeshGeometry.cs b/Runtime/Procedural/Mesh/MeshGeometry.cs index 07e6ebd..ebb23bf 100644 --- a/Runtime/Procedural/Mesh/MeshGeometry.cs +++ b/Runtime/Procedural/Mesh/MeshGeometry.cs @@ -873,6 +873,65 @@ namespace Rokojori return mg; } + public static MeshGeometry Cylinder( int vertices, int divisions, float zMin, float zMax ) + { + var mg = new MeshGeometry(); + var normalizeDivisions = 1f / divisions; + + for ( int d = 0; d < divisions; d++ ) + { + var v0 = d * normalizeDivisions; + var v1 = ( d + 1f ) * normalizeDivisions; + + var z0 = Mathf.Lerp( zMin, zMax, v0 ); + var z1 = Mathf.Lerp( zMin, zMax, v1 ); + + var normalizeVertices = 1f / vertices; + + for ( int i = 0; i < vertices; i++ ) + { + var u0 = i * normalizeVertices; + var u1 = ( i + 1 ) * normalizeVertices; + + var angle0 = u0 * 360f; + var angle1 = u1 * 360f; + + var pos0 = Math2D.CircleDegrees( angle0 ).To3DXY(); + var pos1 = Math2D.CircleDegrees( angle1 ).To3DXY(); + + var pos0z0 = pos0; pos0z0.Z = z0; + var pos0z1 = pos0; pos0z1.Z = z1; + + var pos1z0 = pos1; pos1z0.Z = z0; + var pos1z1 = pos1; pos1z1.Z = z1; + + // RJLog.Log( + // "\nPOSITIONS:", + // pos0z0, pos1z0, pos1z1, pos0z1, + + // "\nNORMALS:", + // pos0, pos1, pos1, pos0, + + // "\nUV:", + // new Vector2( u0, v0 ), new Vector2( u1, v0 ), + // new Vector2( u1, v1 ), new Vector2( u0, v1 ) + // ); + + mg.AddQuad( + pos0z1, pos1z1, pos1z0, pos0z0, + pos0, pos1, pos1, pos0, + new Vector2( u0, v1 ), new Vector2( u1, v1 ), new Vector2( u1, v0 ), new Vector2( u0, v0 ) + ); + + + } + } + + return mg; + + + } + public void Initialize( bool normals = true, bool uvs = true, bool colors = false, bool uvs2 = false ) { this.normals = normals ? new List() : null; diff --git a/Runtime/Rendering/Compositor/CompositorEffects/AntiAliasing/FXAA/FXAAEffect.cs b/Runtime/Rendering/Compositor/CompositorEffects/AntiAliasing/FXAA/FXAAEffect.cs index 1cd2146..95bb675 100644 --- a/Runtime/Rendering/Compositor/CompositorEffects/AntiAliasing/FXAA/FXAAEffect.cs +++ b/Runtime/Rendering/Compositor/CompositorEffects/AntiAliasing/FXAA/FXAAEffect.cs @@ -87,7 +87,7 @@ namespace Rokojori } - if ( lastIterations != numIterations ) + if ( lastIterations != numIterations || numIterations != graph.processOrderSize ) { lastIterations = numIterations; var list = new List(); diff --git a/Runtime/Rendering/RenderGraph/RDGraph.cs b/Runtime/Rendering/RenderGraph/RDGraph.cs index 6a9d097..d0ff836 100644 --- a/Runtime/Rendering/RenderGraph/RDGraph.cs +++ b/Runtime/Rendering/RenderGraph/RDGraph.cs @@ -51,6 +51,8 @@ namespace Rokojori _processOrder.AddRange( order ); } + public int processOrderSize => _processOrder.Count; + public void AddToProcessOrder( params RGGraphProcessor[] additional ) { _processOrder.AddRange( additional ); diff --git a/Runtime/Sensors/CombineSensor.cs b/Runtime/Sensors/CombineSensor.cs index 0dc3904..6c0a46a 100644 --- a/Runtime/Sensors/CombineSensor.cs +++ b/Runtime/Sensors/CombineSensor.cs @@ -18,6 +18,20 @@ namespace Rokojori [Export] public int numVisible = 0; + public override bool IsSensor( InputEvent ev ) + { + foreach ( var s in sensors ) + { + if ( s != null && s.IsSensor( ev ) ) + { + // this.LogInfo( "Is from combined:", s, Sensor.GetInputEventInfo( ev ) ); + return true; + } + } + + return false; + } + protected override void UpdateValue() { var value = 0f; diff --git a/Runtime/Sensors/Default-Sensors/UI/Sensors/UI Cancel.tres b/Runtime/Sensors/Default-Sensors/UI/Sensors/UI Cancel.tres new file mode 100644 index 0000000..426a2b3 --- /dev/null +++ b/Runtime/Sensors/Default-Sensors/UI/Sensors/UI Cancel.tres @@ -0,0 +1,15 @@ +[gd_resource type="Resource" script_class="CombineSensor" load_steps=5 format=3 uid="uid://dfvs7wbygwmhk"] + +[ext_resource type="Script" uid="uid://eid0qnlvq4n1" path="res://addons/rokojori_action_library/Runtime/Sensors/CombineSensor.cs" id="1_3pq7c"] +[ext_resource type="Script" uid="uid://e7fduwypgvwr" path="res://addons/rokojori_action_library/Runtime/Sensors/InputMapActionSensor.cs" id="2_87mft"] +[ext_resource type="Resource" uid="uid://cvjlv07g2nkfw" path="res://addons/rokojori_action_library/Runtime/Sensors/Default-Sensors/Gamepad/Buttons/Button B, PS Circle, Nin A.tres" id="3_e1dcp"] + +[sub_resource type="Resource" id="Resource_hydin"] +script = ExtResource("2_87mft") +inputActionName = "ui_cancel" +metadata/_custom_type_script = "uid://e7fduwypgvwr" + +[resource] +script = ExtResource("1_3pq7c") +sensors = [SubResource("Resource_hydin"), ExtResource("3_e1dcp")] +metadata/_custom_type_script = "uid://eid0qnlvq4n1" diff --git a/Runtime/Sensors/Default-Sensors/UI/Sensors/UI Confirm.tres b/Runtime/Sensors/Default-Sensors/UI/Sensors/UI Confirm.tres new file mode 100644 index 0000000..6737fa0 --- /dev/null +++ b/Runtime/Sensors/Default-Sensors/UI/Sensors/UI Confirm.tres @@ -0,0 +1,15 @@ +[gd_resource type="Resource" script_class="CombineSensor" load_steps=5 format=3 uid="uid://ciia3k58fa5w"] + +[ext_resource type="Script" uid="uid://eid0qnlvq4n1" path="res://addons/rokojori_action_library/Runtime/Sensors/CombineSensor.cs" id="1_5ww7h"] +[ext_resource type="Script" uid="uid://e7fduwypgvwr" path="res://addons/rokojori_action_library/Runtime/Sensors/InputMapActionSensor.cs" id="2_qe2fd"] +[ext_resource type="Resource" uid="uid://dffkdky8iowro" path="res://addons/rokojori_action_library/Runtime/Sensors/Default-Sensors/Gamepad/Buttons/Button A, PS Cross, Nin B.tres" id="3_wy52s"] + +[sub_resource type="Resource" id="Resource_1dc0j"] +script = ExtResource("2_qe2fd") +inputActionName = "ui_accept" +metadata/_custom_type_script = "uid://e7fduwypgvwr" + +[resource] +script = ExtResource("1_5ww7h") +sensors = [SubResource("Resource_1dc0j"), ExtResource("3_wy52s")] +metadata/_custom_type_script = "uid://eid0qnlvq4n1" diff --git a/Runtime/Sensors/Default-Sensors/UI/Sensors/UI Down.tres b/Runtime/Sensors/Default-Sensors/UI/Sensors/UI Down.tres new file mode 100644 index 0000000..e444282 --- /dev/null +++ b/Runtime/Sensors/Default-Sensors/UI/Sensors/UI Down.tres @@ -0,0 +1,14 @@ +[gd_resource type="Resource" script_class="CombineSensor" load_steps=4 format=3 uid="uid://ckyf78p517ga1"] + +[ext_resource type="Script" uid="uid://eid0qnlvq4n1" path="res://addons/rokojori_action_library/Runtime/Sensors/CombineSensor.cs" id="1_uc4e8"] +[ext_resource type="Script" uid="uid://e7fduwypgvwr" path="res://addons/rokojori_action_library/Runtime/Sensors/InputMapActionSensor.cs" id="2_l2qr3"] + +[sub_resource type="Resource" id="Resource_pb2so"] +script = ExtResource("2_l2qr3") +inputActionName = "ui_down" +metadata/_custom_type_script = "uid://e7fduwypgvwr" + +[resource] +script = ExtResource("1_uc4e8") +sensors = [SubResource("Resource_pb2so")] +metadata/_custom_type_script = "uid://eid0qnlvq4n1" diff --git a/Runtime/Sensors/Default-Sensors/UI/Sensors/UI Left.tres b/Runtime/Sensors/Default-Sensors/UI/Sensors/UI Left.tres new file mode 100644 index 0000000..50899c0 --- /dev/null +++ b/Runtime/Sensors/Default-Sensors/UI/Sensors/UI Left.tres @@ -0,0 +1,14 @@ +[gd_resource type="Resource" script_class="CombineSensor" load_steps=4 format=3 uid="uid://cqatyb80rpor0"] + +[ext_resource type="Script" uid="uid://eid0qnlvq4n1" path="res://addons/rokojori_action_library/Runtime/Sensors/CombineSensor.cs" id="1_u5wou"] +[ext_resource type="Script" uid="uid://e7fduwypgvwr" path="res://addons/rokojori_action_library/Runtime/Sensors/InputMapActionSensor.cs" id="2_ibucs"] + +[sub_resource type="Resource" id="Resource_n3xai"] +script = ExtResource("2_ibucs") +inputActionName = "ui_left" +metadata/_custom_type_script = "uid://e7fduwypgvwr" + +[resource] +script = ExtResource("1_u5wou") +sensors = [SubResource("Resource_n3xai")] +metadata/_custom_type_script = "uid://eid0qnlvq4n1" diff --git a/Runtime/Sensors/Default-Sensors/UI/Sensors/UI Next Menu.tres b/Runtime/Sensors/Default-Sensors/UI/Sensors/UI Next Menu.tres new file mode 100644 index 0000000..607e4a9 --- /dev/null +++ b/Runtime/Sensors/Default-Sensors/UI/Sensors/UI Next Menu.tres @@ -0,0 +1,9 @@ +[gd_resource type="Resource" script_class="CombineSensor" load_steps=3 format=3 uid="uid://ccff1bj35qcl0"] + +[ext_resource type="Script" uid="uid://eid0qnlvq4n1" path="res://addons/rokojori_action_library/Runtime/Sensors/CombineSensor.cs" id="1_8e2n5"] +[ext_resource type="Resource" uid="uid://jbud1yjmxysm" path="res://addons/rokojori_action_library/Runtime/Sensors/Default-Sensors/Gamepad/Buttons/Shoulder Right, RB, R1.tres" id="2_m7ahn"] + +[resource] +script = ExtResource("1_8e2n5") +sensors = [ExtResource("2_m7ahn")] +metadata/_custom_type_script = "uid://eid0qnlvq4n1" diff --git a/Runtime/Sensors/Default-Sensors/UI/Sensors/UI Previous Menu.tres b/Runtime/Sensors/Default-Sensors/UI/Sensors/UI Previous Menu.tres new file mode 100644 index 0000000..30f0a76 --- /dev/null +++ b/Runtime/Sensors/Default-Sensors/UI/Sensors/UI Previous Menu.tres @@ -0,0 +1,9 @@ +[gd_resource type="Resource" script_class="CombineSensor" load_steps=3 format=3 uid="uid://dtykoghdisv37"] + +[ext_resource type="Script" uid="uid://eid0qnlvq4n1" path="res://addons/rokojori_action_library/Runtime/Sensors/CombineSensor.cs" id="1_r1ua5"] +[ext_resource type="Resource" uid="uid://cituiuw6e1fho" path="res://addons/rokojori_action_library/Runtime/Sensors/Default-Sensors/Gamepad/Buttons/Shoulder Left, LB, L1.tres" id="2_in8jh"] + +[resource] +script = ExtResource("1_r1ua5") +sensors = [ExtResource("2_in8jh")] +metadata/_custom_type_script = "uid://eid0qnlvq4n1" diff --git a/Runtime/Sensors/Default-Sensors/UI/Sensors/UI Right.tres b/Runtime/Sensors/Default-Sensors/UI/Sensors/UI Right.tres new file mode 100644 index 0000000..d9fd33f --- /dev/null +++ b/Runtime/Sensors/Default-Sensors/UI/Sensors/UI Right.tres @@ -0,0 +1,14 @@ +[gd_resource type="Resource" script_class="CombineSensor" load_steps=4 format=3 uid="uid://dafu3alp6wr25"] + +[ext_resource type="Script" uid="uid://eid0qnlvq4n1" path="res://addons/rokojori_action_library/Runtime/Sensors/CombineSensor.cs" id="1_rqdfo"] +[ext_resource type="Script" uid="uid://e7fduwypgvwr" path="res://addons/rokojori_action_library/Runtime/Sensors/InputMapActionSensor.cs" id="2_oj4wy"] + +[sub_resource type="Resource" id="Resource_tuqbj"] +script = ExtResource("2_oj4wy") +inputActionName = "ui_right" +metadata/_custom_type_script = "uid://e7fduwypgvwr" + +[resource] +script = ExtResource("1_rqdfo") +sensors = [SubResource("Resource_tuqbj")] +metadata/_custom_type_script = "uid://eid0qnlvq4n1" diff --git a/Runtime/Sensors/Default-Sensors/UI/Sensors/UI Up.tres b/Runtime/Sensors/Default-Sensors/UI/Sensors/UI Up.tres new file mode 100644 index 0000000..a8a5b9e --- /dev/null +++ b/Runtime/Sensors/Default-Sensors/UI/Sensors/UI Up.tres @@ -0,0 +1,14 @@ +[gd_resource type="Resource" script_class="CombineSensor" load_steps=4 format=3 uid="uid://r8bfiv34ghev"] + +[ext_resource type="Script" uid="uid://eid0qnlvq4n1" path="res://addons/rokojori_action_library/Runtime/Sensors/CombineSensor.cs" id="1_j2g18"] +[ext_resource type="Script" uid="uid://e7fduwypgvwr" path="res://addons/rokojori_action_library/Runtime/Sensors/InputMapActionSensor.cs" id="2_5pcht"] + +[sub_resource type="Resource" id="Resource_esl73"] +script = ExtResource("2_5pcht") +inputActionName = "ui_up" +metadata/_custom_type_script = "uid://e7fduwypgvwr" + +[resource] +script = ExtResource("1_j2g18") +sensors = [SubResource("Resource_esl73")] +metadata/_custom_type_script = "uid://eid0qnlvq4n1" diff --git a/Runtime/Sensors/Default-Sensors/UI/UI Inputs Group.tres b/Runtime/Sensors/Default-Sensors/UI/UI Inputs Group.tres new file mode 100644 index 0000000..d6a43b4 --- /dev/null +++ b/Runtime/Sensors/Default-Sensors/UI/UI Inputs Group.tres @@ -0,0 +1,16 @@ +[gd_resource type="Resource" script_class="SensorGroup" load_steps=10 format=3 uid="uid://ca1e6qd423hg"] + +[ext_resource type="Script" uid="uid://da4bhmvkury2" path="res://addons/rokojori_action_library/Runtime/Sensors/SensorGroup.cs" id="1_n7t1q"] +[ext_resource type="Resource" uid="uid://dfvs7wbygwmhk" path="res://addons/rokojori_action_library/Runtime/Sensors/Default-Sensors/UI/Sensors/UI Cancel.tres" id="2_yi61e"] +[ext_resource type="Resource" uid="uid://ciia3k58fa5w" path="res://addons/rokojori_action_library/Runtime/Sensors/Default-Sensors/UI/Sensors/UI Confirm.tres" id="3_vqhth"] +[ext_resource type="Resource" uid="uid://ckyf78p517ga1" path="res://addons/rokojori_action_library/Runtime/Sensors/Default-Sensors/UI/Sensors/UI Down.tres" id="4_vjp62"] +[ext_resource type="Resource" uid="uid://cqatyb80rpor0" path="res://addons/rokojori_action_library/Runtime/Sensors/Default-Sensors/UI/Sensors/UI Left.tres" id="5_3twes"] +[ext_resource type="Resource" uid="uid://ccff1bj35qcl0" path="res://addons/rokojori_action_library/Runtime/Sensors/Default-Sensors/UI/Sensors/UI Next Menu.tres" id="6_rvbkj"] +[ext_resource type="Resource" uid="uid://dtykoghdisv37" path="res://addons/rokojori_action_library/Runtime/Sensors/Default-Sensors/UI/Sensors/UI Previous Menu.tres" id="7_jx650"] +[ext_resource type="Resource" uid="uid://dafu3alp6wr25" path="res://addons/rokojori_action_library/Runtime/Sensors/Default-Sensors/UI/Sensors/UI Right.tres" id="8_ttnbi"] +[ext_resource type="Resource" uid="uid://r8bfiv34ghev" path="res://addons/rokojori_action_library/Runtime/Sensors/Default-Sensors/UI/Sensors/UI Up.tres" id="9_h04cc"] + +[resource] +script = ExtResource("1_n7t1q") +sensors = [ExtResource("2_yi61e"), ExtResource("3_vqhth"), ExtResource("9_h04cc"), ExtResource("4_vjp62"), ExtResource("5_3twes"), ExtResource("8_ttnbi"), ExtResource("6_rvbkj"), ExtResource("7_jx650")] +metadata/_custom_type_script = "uid://da4bhmvkury2" diff --git a/Runtime/Sensors/GamePadAxisSensor.cs b/Runtime/Sensors/GamePadAxisSensor.cs index b08a057..81f0955 100644 --- a/Runtime/Sensors/GamePadAxisSensor.cs +++ b/Runtime/Sensors/GamePadAxisSensor.cs @@ -28,6 +28,37 @@ namespace Rokojori SetFloatValue( _lastInput ); } + + public override bool IsSensor( InputEvent ev ) + { + // this.LogInfo( "Checking axis sensor:", Sensor.GetInputEventInfo( ev ) ); + + var joypadAxisEvent = ev as InputEventJoypadMotion; + + if ( joypadAxisEvent == null ) + { + return false; + } + + if ( joypadAxisEvent.Axis != axis ) + { + return false; + } + + if ( type == GamePadAxisType.Positive ) + { + // this.LogInfo( "Is positive axis sensor:", Sensor.GetInputEventInfo( ev ) ); + return joypadAxisEvent.AxisValue > 0; + } + else if ( type == GamePadAxisType.Negative ) + { + // this.LogInfo( "Is negative axis sensor:", Sensor.GetInputEventInfo( ev ) ); + return joypadAxisEvent.AxisValue < 0; + } + + return false; + } + public void _Input( InputEvent ev ) { var joypadAxisEvent = ev as InputEventJoypadMotion; diff --git a/Runtime/Sensors/GamePadButtonSensor.cs b/Runtime/Sensors/GamePadButtonSensor.cs index 965cb86..abf08fe 100644 --- a/Runtime/Sensors/GamePadButtonSensor.cs +++ b/Runtime/Sensors/GamePadButtonSensor.cs @@ -24,7 +24,24 @@ namespace Rokojori { return RJLog.GetInfo( this, button ); } - + + public override bool IsSensor( InputEvent ev ) + { + var joypadButtonEvent = ev as InputEventJoypadButton; + + if ( joypadButtonEvent == null ) + { + return false; + } + + if ( joypadButtonEvent.ButtonIndex != button ) + { + return false; + } + + return true; + } + public void _Input( InputEvent ev ) { var joypadButtonEvent = ev as InputEventJoypadButton; diff --git a/Runtime/Sensors/HoldSensor.cs b/Runtime/Sensors/HoldSensor.cs index 92ce34f..0468162 100644 --- a/Runtime/Sensors/HoldSensor.cs +++ b/Runtime/Sensors/HoldSensor.cs @@ -17,6 +17,19 @@ namespace Rokojori [Export] public Sensor triggerButton; + public override bool IsSensor( InputEvent ie ) + { + var holdButtonPressed = holdButton.isActive; + var needsToBePressed = ! negateHoldButton; + + if ( holdButtonPressed == needsToBePressed ) + { + return false; + } + + return triggerButton.IsSensor( ie ); + } + protected override void UpdateValue() { if ( holdButton == null || triggerButton == null ) @@ -41,7 +54,7 @@ namespace Rokojori SetFloatValue( triggerButton.value ); } - public override string ToString() + public override string ToString() { return RJLog.GetInfo( this, holdButton, triggerButton ); } diff --git a/Runtime/Sensors/InputMapActionSensor.cs b/Runtime/Sensors/InputMapActionSensor.cs index 1c3f238..a241c5b 100644 --- a/Runtime/Sensors/InputMapActionSensor.cs +++ b/Runtime/Sensors/InputMapActionSensor.cs @@ -26,6 +26,33 @@ namespace Rokojori return RJLog.GetInfo( this, inputActionName, pollMode ); } + public override bool IsSensor( InputEvent ie ) + { + // this.LogInfo( "Checking action input:", Sensor.GetInputEventInfo( ie ) ); + + if ( ie.IsActionPressed( inputActionName, true, true ) ) + { + var strength = ie.GetActionStrength( inputActionName ); + var isActive = strength > 0.01f; + + if ( isActive ) + { + // this.LogInfo( "Matching pressed action input:", Sensor.GetInputEventInfo( ie ) ); + } + + return isActive; + } + + var released = ie.IsActionReleased( inputActionName, true ); + + if ( released ) + { + // this.LogInfo( "Matching released action input:", Sensor.GetInputEventInfo( ie ) ); + } + + return released; + } + protected override void UpdateValue() { if ( PollMode.Button == pollMode ) diff --git a/Runtime/Sensors/KeySensor.cs b/Runtime/Sensors/KeySensor.cs index 5dea8dd..3a06b9f 100644 --- a/Runtime/Sensors/KeySensor.cs +++ b/Runtime/Sensors/KeySensor.cs @@ -47,6 +47,56 @@ namespace Rokojori SetFloatValue( _lastInput ); } + public override bool IsSensor( InputEvent ev ) + { + var keyEvent = ev as InputEventKey; + + + if ( keyEvent == null ) + { + return false; + } + + if ( keyEvent.Keycode != key ) + { + return false; + } + + if ( keyLocation != KeyLocation.Unspecified && keyEvent.Location != KeyLocation.Unspecified ) + { + if ( keyEvent.Location != keyLocation ) + { + return false; + } + } + + var checkModifiers = modifiersEnabled && + ( + ModifiersMode.Hold_Modifiers_All_The_Time == modifiersMode || + _lastInput == 0 && ModifiersMode.Hold_Modifiers_Only_On_Down == modifiersMode + ); + + if ( checkModifiers ) + { + if ( ! TrilleanLogic.Matches( ctrlHold, keyEvent.CtrlPressed ) ) + { + return false; + } + + if ( ! TrilleanLogic.Matches( altHold, keyEvent.AltPressed ) ) + { + return false; + } + + if ( ! TrilleanLogic.Matches( shiftHold, keyEvent.ShiftPressed ) ) + { + return false; + } + } + + return true; + } + public void _Input( InputEvent ev ) { var keyEvent = ev as InputEventKey; diff --git a/Runtime/Sensors/MouseButtonSensor.cs b/Runtime/Sensors/MouseButtonSensor.cs index a14bbb9..1f97596 100644 --- a/Runtime/Sensors/MouseButtonSensor.cs +++ b/Runtime/Sensors/MouseButtonSensor.cs @@ -58,6 +58,56 @@ namespace Rokojori } + public override bool IsSensor( InputEvent ev ) + { + var mouseEvent = ev as InputEventMouseButton; + + if ( mouseEvent == null ) + { + return false; + } + + if ( mouseEvent.ButtonIndex != button ) + { + return false; + } + + var checkModifiers = modifiersEnabled && + ( + ModifiersMode.Hold_Modifiers_All_The_Time == modifiersMode || + _lastInput == 0 && ModifiersMode.Hold_Modifiers_Only_On_Down == modifiersMode + ); + + if ( checkModifiers ) + { + + if ( ! TrilleanLogic.Matches( ctrlHold, mouseEvent.CtrlPressed ) ) + { + return false; + } + + if ( ! TrilleanLogic.Matches( altHold, mouseEvent.AltPressed ) ) + { + return false; + } + + if ( ! TrilleanLogic.Matches( shiftHold, mouseEvent.ShiftPressed ) ) + { + return false; + } + } + + var isActive = mouseEvent.IsPressed(); + + if ( IsWheel() && ! isActive ) + { + return false; + } + + return true; + } + + public void _Input( InputEvent ev ) { diff --git a/Runtime/Sensors/MouseMotionDelta.cs b/Runtime/Sensors/MouseMotionDelta.cs index 405f024..30ade9e 100644 --- a/Runtime/Sensors/MouseMotionDelta.cs +++ b/Runtime/Sensors/MouseMotionDelta.cs @@ -35,6 +35,11 @@ namespace Rokojori _lastInput = 0; } + public override bool IsSensor( InputEvent ev ) + { + return ev is InputEventMouseMotion; + } + public void _Input( InputEvent ev ) { var mouseEvent = ev as InputEventMouseMotion ; diff --git a/Runtime/Sensors/MouseScreenRelative.cs b/Runtime/Sensors/MouseScreenRelative.cs index 17f2c55..2fc85fe 100644 --- a/Runtime/Sensors/MouseScreenRelative.cs +++ b/Runtime/Sensors/MouseScreenRelative.cs @@ -31,6 +31,11 @@ namespace Rokojori return RJLog.GetInfo( this, motionType ); } + public override bool IsSensor( InputEvent ev ) + { + return ev is InputEventMouseMotion; + } + public void _Input( InputEvent ev ) { var mouseEvent = ev as InputEventMouseMotion ; diff --git a/Runtime/Sensors/Sensor.cs b/Runtime/Sensors/Sensor.cs index 03935d5..d461c50 100644 --- a/Runtime/Sensors/Sensor.cs +++ b/Runtime/Sensors/Sensor.cs @@ -6,7 +6,7 @@ namespace Rokojori { [Tool] [GlobalClass, Icon("res://addons/rokojori_action_library/Icons/Sensor.svg")] - public partial class Sensor: Resource + public abstract partial class Sensor: Resource { [Export] public LocaleText name; @@ -52,6 +52,61 @@ namespace Rokojori public virtual bool WasActive( int device ) => isUp; public virtual bool IsActive( int device ) => isUp; + public virtual bool IsDown( InputEvent ie ){ return IsSensor( ie ) && ie.IsPressed(); } + public virtual bool IsUp( InputEvent ie ){ return IsSensor( ie ) && ie.IsReleased(); } + public abstract bool IsSensor( InputEvent ie ); + + public virtual bool IsRepeatDown( ref float lastActivation, float delay = 0.5f, float repeatDuration = 0.1f ) + { + var now = TimeLine.osTime; + + if ( isDown ) + { + lastActivation = now + delay; + return true; + } + + var value = isActive && ( now - lastActivation ) > repeatDuration; + + if ( value ) + { + lastActivation = now; + } + + return value; + } + + public static string GetInputEventInfo( InputEvent ie ) + { + var type = ie.GetType().Name; + var isPressed = ie.IsPressed(); + var isReleeased = ie.IsReleased(); + + var details = ""; + if ( ie is InputEventKey k ) + { + details = "key: " + k.Keycode + " " + k.KeyLabel; + } + else if ( ie is InputEventJoypadButton b ) + { + details = "gamepad button: " + b.ButtonIndex; + } + else if ( ie is InputEventJoypadMotion a ) + { + details = "gamepad axis: " + a.Axis + " " + a.AxisValue; + } + else if ( ie is InputEventMouseButton mb ) + { + details = "mouse button: " + mb.ButtonIndex + " " + mb.ButtonMask; + } + else if ( ie is InputEventMouseMotion mm ) + { + details = "mouse motion: " + mm.Position + " " + mm.Relative; + } + + return type + " pressed:" + isPressed + " released: " + isReleeased + " " + details; + } + public bool consumed => _consumed; diff --git a/Runtime/Sensors/SensorManager.cs b/Runtime/Sensors/SensorManager.cs index 2c8b2b7..28d4d53 100644 --- a/Runtime/Sensors/SensorManager.cs +++ b/Runtime/Sensors/SensorManager.cs @@ -263,7 +263,8 @@ namespace Rokojori { return; } - //this.LogInfo( "Register", s ); + + this.LogInfo( "Register", s ); if ( ! sensorToRunner.ContainsKey( s ) ) { @@ -410,6 +411,18 @@ namespace Rokojori } //this.LogInfo( "AddSensorsFrom", obj ); + + if ( obj is CombineSensor cs ) + { + + cs.sensors.ForEach( s => + { + this.LogInfo( "Adding Combine Sensor:", s ); + AddSensor( s ); + } + ); + return; + } try { diff --git a/Runtime/Shading/Library/Bezier.gdshaderinc b/Runtime/Shading/Library/Bezier.gdshaderinc new file mode 100644 index 0000000..2cff2e7 --- /dev/null +++ b/Runtime/Shading/Library/Bezier.gdshaderinc @@ -0,0 +1,65 @@ +// #include "res://addons/rokojori_action_library/Runtime/Shading/Library/Bezier.gdshaderinc" + + +float cubicBezier( float t, float p0, float p1, float p2, float p3 ) +{ + float bp0 = ( 1.0 - t ) * ( 1.0 - t ) * ( 1.0 - t ); + float bp1 = 3.0 * ( 1.0 - t ) * ( 1.0 - t ) * t; + float bp2 = 3.0 * ( 1.0 - t ) * t * t; + float bp3 = t * t * t; + + return p0 * bp0 + p1 * bp1 + p2 * bp2 + p3 * bp3; +} + +vec2 cubicBezier( float t, vec2 p0, vec2 p1, vec2 p2, vec2 p3 ) +{ + float bp0 = ( 1.0 - t ) * ( 1.0 - t ) * ( 1.0 - t ); + float bp1 = 3.0 * ( 1.0 - t ) * ( 1.0 - t ) * t; + float bp2 = 3.0 * ( 1.0 - t ) * t * t; + float bp3 = t * t * t; + + return p0 * bp0 + p1 * bp1 + p2 * bp2 + p3 * bp3; +} + + +vec3 cubicBezier( float t, vec3 p0, vec3 p1, vec3 p2, vec3 p3 ) +{ + float bp0 = ( 1.0 - t ) * ( 1.0 - t ) * ( 1.0 - t ); + float bp1 = 3.0 * ( 1.0 - t ) * ( 1.0 - t ) * t; + float bp2 = 3.0 * ( 1.0 - t ) * t * t; + float bp3 = t * t * t; + + return p0 * bp0 + p1 * bp1 + p2 * bp2 + p3 * bp3; +} + +vec3 cubicBezierDerivative( float t, vec3 p0, vec3 p1, vec3 p2, vec3 p3 ) +{ + vec3 d0 = ( p1 - p0 ); + vec3 d1 = ( p2 - p1 ); + vec3 d2 = ( p3 - p2 ); + + float bp0 = 3.0 * ( 1.0 - t ) * ( 1.0 - t ); + float bp1 = 6.0 * ( 1.0 - t ) * t; + float bp2 = 3.0 * t * t; + + + return d0 * bp0 + d1 * bp1 + d2 * bp2; +} + + +vec3 rationalCubicBezier( float t, + vec3 p0, vec3 p1, vec3 p2, vec3 p3, + float w0, float w1, float w2, float w3 + ) +{ + float bp0 = ( 1.0 - t ) * ( 1.0 - t ) * ( 1.0 - t ) * w0; + float bp1 = 3.0 * ( 1.0 - t ) * ( 1.0 - t ) * t * w1; + float bp2 = 3.0 * ( 1.0 - t ) * t * t * w2; + float bp3 = t * t * t * w3; + + vec3 weighted = p0 * bp0 + p1 * bp1 + p2 * bp2 + p3 * bp3; + + float projection = bp0 + bp1 + bp2 + bp3; + + return weighted / projection; +} diff --git a/Runtime/Shading/Library/Bezier.gdshaderinc.uid b/Runtime/Shading/Library/Bezier.gdshaderinc.uid new file mode 100644 index 0000000..763a737 --- /dev/null +++ b/Runtime/Shading/Library/Bezier.gdshaderinc.uid @@ -0,0 +1 @@ +uid://dmrr025l0bwyj diff --git a/Runtime/Shading/Library/SDF.gdshaderinc b/Runtime/Shading/Library/SDF.gdshaderinc index f3708c5..50b3b31 100644 --- a/Runtime/Shading/Library/SDF.gdshaderinc +++ b/Runtime/Shading/Library/SDF.gdshaderinc @@ -279,6 +279,45 @@ float sdRoundedX( in vec2 p, in float w, in float r ) return length(p-min(p.x+p.y,w)*0.5) - r; } +// float sdBezier( vec2 pos, vec2 pointA, vec2 pointB, vec2 pointC ) +// { +// vec2 a = pointB - pointA; +// vec2 b = pointA - 2.0*pointB + pointC; +// vec2 c = a * 2.0; +// vec2 d = pointA - pos; + +// float kk = 1.0/dot(b,b); +// float kx = kk * dot(a,b); +// float ky = kk * (2.0*dot(a,a)+dot(d,b)) / 3.0; +// float kz = kk * dot(d,a); +// float res = 0.0; +// float p = ky - kx*kx; +// float p3 = p*p*p; +// float q = kx*(2.0*kx*kx-3.0*ky) + kz; +// float h = q*q + 4.0*p3; + +// if( h >= 0.0 ) +// { +// h = sqrt(h); +// vec2 x = (vec2(h,-h)-q)/2.0; +// vec2 uv = sign(x)*pow(abs(x), vec2(1.0/3.0)); +// float t = clamp( uv.x+uv.y-kx, 0.0, 1.0 ); +// res = dot2(d + (c + b*t)*t); +// } +// else +// { +// float z = sqrt(-p); +// float v = acos( q/(p*z*2.0) ) / 3.0; +// float m = cos(v); +// float n = sin(v)*1.732050808; +// vec3 t = clamp(vec3(m+m,-n-m,n-m)*z-kx,0.0,1.0); +// res = min( dot2(d+(c+b*t.x)*t.x), +// dot2(d+(c+b*t.y)*t.y) ); +// } + +// return sqrt( res ); +// } + // float sdPolygon( in vec2[N] v, in vec2 p ) // { // float d = dot(p-v[0],p-v[0]); diff --git a/Runtime/Shading/Library/Transform.gdshaderinc b/Runtime/Shading/Library/Transform.gdshaderinc index 8998f0b..866e7cd 100644 --- a/Runtime/Shading/Library/Transform.gdshaderinc +++ b/Runtime/Shading/Library/Transform.gdshaderinc @@ -655,6 +655,41 @@ vec2 worldUVfromLocalXZ( vec3 localVertex, vec2 centerXZ, vec2 sizeXZ, mat4 _MOD return worldUVfromWorldXZ( worldVertex, centerXZ, sizeXZ ); } +mat3 createBasis( vec3 x, vec3 y, vec3 z ) +{ + return mat3( x, y, z ); +} + +mat3 lookRotation( vec3 forward, vec3 up ) +{ + vec3 z = normalize( forward ); + vec3 x = normalize( cross( up, z ) ); + vec3 y = cross( z, x ); + + return createBasis( x, y, z ); +} + +vec4 quaternionFromLookRotation( vec3 forward, vec3 up ) +{ + mat3 rotationMatrix = lookRotation( forward, up ); + + return quaternionFromMatrix( rotationMatrix ); +} + +mat4 createMat4FromBasisAndOrigin( mat3 basis, vec3 origin ) +{ + mat4 transform = mat4( + + vec4( basis[0], 0.0 ), + vec4( basis[1], 0.0 ), + vec4( basis[2], 0.0 ), + vec4( origin, 1.0 ) + ); + + return transform; +} + + mat3 createFromToRotation( vec3 from, vec3 to ) { diff --git a/Runtime/Shading/Properties/FloatPropertyName.cs b/Runtime/Shading/Properties/FloatPropertyName.cs index 8048013..035007f 100644 --- a/Runtime/Shading/Properties/FloatPropertyName.cs +++ b/Runtime/Shading/Properties/FloatPropertyName.cs @@ -59,7 +59,15 @@ namespace Rokojori } + public void SetInstance( GeometryInstance3D gi, float value ) + { + _SetInstance( gi, value ); + } + public float GetInstance( GeometryInstance3D gi, float fallback = 0f) + { + return _GetInstance( gi, fallback ); + } public void Set( Material material, float value ) diff --git a/Runtime/Shading/Properties/ShaderPropertyName.cs b/Runtime/Shading/Properties/ShaderPropertyName.cs index 07b6fca..26a28a1 100644 --- a/Runtime/Shading/Properties/ShaderPropertyName.cs +++ b/Runtime/Shading/Properties/ShaderPropertyName.cs @@ -31,6 +31,23 @@ namespace Rokojori _SetStandardValue( m, value ); } + public void _SetInstance<[MustBeVariant] T>( GeometryInstance3D mi, T value ) + { + var variant = Variant.From( value ); + mi.SetInstanceShaderParameter( propertyName, variant ); + return; + } + + public T _GetInstance<[MustBeVariant] T>( GeometryInstance3D mi, T value ) + { + if ( mi == null ) + { + return value; + } + + return mi.GetInstanceShaderParameter( propertyName ).As(); + } + public T _Get<[MustBeVariant] T>( Material material, T fallback ) { if ( material is ShaderMaterial shaderMaterial ) diff --git a/Runtime/Shading/Properties/Vector3PropertyName.cs b/Runtime/Shading/Properties/Vector3PropertyName.cs index db45b16..96bfca2 100644 --- a/Runtime/Shading/Properties/Vector3PropertyName.cs +++ b/Runtime/Shading/Properties/Vector3PropertyName.cs @@ -27,6 +27,16 @@ namespace Rokojori return _Get( material, Vector3.Zero ); } + public void SetInstance( GeometryInstance3D gi, Vector3 value ) + { + _SetInstance( gi, value ); + } + + public Vector3 GetInstance( GeometryInstance3D gi ) + { + return _GetInstance( gi, Vector3.Zero ); + } + public static Vector3PropertyName Create( string name ) { var p = new Vector3PropertyName(); diff --git a/Runtime/Structures/QueueList.cs b/Runtime/Structures/QueueList.cs index 1f2eafd..97cd391 100644 --- a/Runtime/Structures/QueueList.cs +++ b/Runtime/Structures/QueueList.cs @@ -46,7 +46,7 @@ namespace Rokojori return; } - Lists.RemoveRange( this, _queuedRemovals ); + Lists.RemoveList( this, _queuedRemovals ); _queuedRemovals.Clear(); } diff --git a/Runtime/Text/JSON/Serializers/JSONDeserializer.cs b/Runtime/Text/JSON/Serializers/JSONDeserializer.cs index 4242ac9..1a51c7d 100644 --- a/Runtime/Text/JSON/Serializers/JSONDeserializer.cs +++ b/Runtime/Text/JSON/Serializers/JSONDeserializer.cs @@ -6,6 +6,7 @@ using System.Text; using System; +using System.Linq; namespace Rokojori @@ -74,13 +75,22 @@ namespace Rokojori } var type = parent.GetType(); + + if ( IsSerializableDictionary( type ) ) + { + DeserializeDictionaryField( data, parent as IDictionary, name, -1 ); + return; + } + var field = type.GetField( name ); if ( field == null ) { - RJLog.Log( "Field not present: " + name ); + + + RJLog.Log( "Field not present: " + name, "in", type.Name ); return; } diff --git a/Runtime/Text/Lexing/LexerLibrary/UIExpressionLexer.cs b/Runtime/Text/Lexing/LexerLibrary/UIExpressionLexer.cs new file mode 100644 index 0000000..19e2261 --- /dev/null +++ b/Runtime/Text/Lexing/LexerLibrary/UIExpressionLexer.cs @@ -0,0 +1,43 @@ +using System.Collections; +using System.Collections.Generic; +using System.Text.RegularExpressions; + +namespace Rokojori +{ + + public class UIExpressionLexer:Lexer + { + public static List Lex( string source ) + { + var lexer = new UIExpressionLexer(); + var events = lexer.LexToList( source ); + + if ( lexer.hasError ) + { + return null; + } + + events.ForEach( ev => { ev.GrabMatch( source ); } ); + return events; + } + + public UIExpressionLexer() + { + AddAllMatchers( + LexerMatcherLibrary.SingleLineCommentMatcher, + LexerMatcherLibrary.MultiLineCommentMatcher, + LexerMatcherLibrary.NumberMatcher, + LexerMatcherLibrary.NullMatcher, + LexerMatcherLibrary.BoolMatcher, + LexerMatcherLibrary.BreakMatcher, + LexerMatcherLibrary.WhiteSpaceMatcher, + LexerMatcherLibrary.LogicMatcher, + LexerMatcherLibrary.BracketMatcher, + LexerMatcherLibrary.OperatorMatcher, + LexerMatcherLibrary.CFunctionMatcher, + LexerMatcherLibrary.CwordMatcher, + LexerMatcherLibrary.AnySymbolMatcher + ); + } + } +} \ No newline at end of file diff --git a/Runtime/Text/Lexing/LexerLibrary/UIExpressionLexer.cs.uid b/Runtime/Text/Lexing/LexerLibrary/UIExpressionLexer.cs.uid new file mode 100644 index 0000000..b8e707a --- /dev/null +++ b/Runtime/Text/Lexing/LexerLibrary/UIExpressionLexer.cs.uid @@ -0,0 +1 @@ +uid://p6e2rj7eba6x diff --git a/Runtime/Text/Text.cs b/Runtime/Text/Text.cs index b5c071c..c584cd3 100644 --- a/Runtime/Text/Text.cs +++ b/Runtime/Text/Text.cs @@ -135,6 +135,11 @@ namespace Rokojori public static string ReplaceStart( this string source, string start, string replacement = "" ) { + if ( start == "" ) + { + return source; + } + if ( source.StartsWith( start ) ) { return replacement + source.Substring( start.Length ); @@ -145,6 +150,11 @@ namespace Rokojori public static string ReplaceEnd( this string source, string ending, string replacement = "" ) { + if ( ending == "" ) + { + return source; + } + if ( source.EndsWith( ending ) ) { return source.Substring( 0, source.Length - ending.Length ) + replacement; diff --git a/Runtime/Tools/Arrays.cs b/Runtime/Tools/Arrays.cs index 0a54c4f..aa9e0e8 100644 --- a/Runtime/Tools/Arrays.cs +++ b/Runtime/Tools/Arrays.cs @@ -35,7 +35,7 @@ namespace Rokojori } - public static int FindIndex( T[] values, Func predicate ) + public static int FindIndex( this T[] values, Func predicate ) { if ( values == null ) { diff --git a/Runtime/Tools/Lists.cs b/Runtime/Tools/Lists.cs index 5ff2b4c..1a060e0 100644 --- a/Runtime/Tools/Lists.cs +++ b/Runtime/Tools/Lists.cs @@ -666,7 +666,7 @@ namespace Rokojori } } - public static void RemoveRange( List list, List removals ) + public static void RemoveList( this List list, List removals ) { var removalSet = new HashSet(); removalSet.UnionWith( removals ); diff --git a/Runtime/UI/Actions/SetFocusedControl.cs b/Runtime/UI/Actions/SetFocusedControl.cs new file mode 100644 index 0000000..2a9d743 --- /dev/null +++ b/Runtime/UI/Actions/SetFocusedControl.cs @@ -0,0 +1,27 @@ + +using Godot; +using System; + +namespace Rokojori; + +[Tool,GlobalClass] +public partial class SetFocusedControl: Action +{ + [Export] + public Control control; + + protected override void _OnTrigger() + { + this.CallDeferred( + ()=> + { + control.GrabFocus(); + + + + control.LogInfo( "Grabbing Focus:", control.HasFocus() ); + } + ); + + } +} diff --git a/Runtime/UI/Actions/SetFocusedControl.cs.uid b/Runtime/UI/Actions/SetFocusedControl.cs.uid new file mode 100644 index 0000000..fa16911 --- /dev/null +++ b/Runtime/UI/Actions/SetFocusedControl.cs.uid @@ -0,0 +1 @@ +uid://dx7xkcqyf6vyf diff --git a/Runtime/UI/Actions/SetUIElementActiveState.cs b/Runtime/UI/Actions/SetUIElementActiveState.cs new file mode 100644 index 0000000..858b617 --- /dev/null +++ b/Runtime/UI/Actions/SetUIElementActiveState.cs @@ -0,0 +1,43 @@ + +using Godot; +using System; + +namespace Rokojori; + +[Tool,GlobalClass] +public partial class SetUIElementActiveState: Action +{ + + [Export] + public Control uiNode; + + public enum ActiveState + { + Set_Active, + Remove_Active + } + + [Export] + public ActiveState activeState = ActiveState.Set_Active; + + protected override void _OnTrigger() + { + var uiStyleable = uiNode as UIStylePropertyContainer; + + if ( uiStyleable == null ) + { + return; + } + + + if ( ActiveState.Set_Active == activeState ) + { + uiStyleable.AddUISelectorFlag( UISelectorFlag.Active ); + } + else + { + uiStyleable.RemoveUISelectorFlag( UISelectorFlag.Active ); + } + + } +} diff --git a/Runtime/UI/Actions/SetUIElementActiveState.cs.uid b/Runtime/UI/Actions/SetUIElementActiveState.cs.uid new file mode 100644 index 0000000..fbf0646 --- /dev/null +++ b/Runtime/UI/Actions/SetUIElementActiveState.cs.uid @@ -0,0 +1 @@ +uid://di6haj23ecabu diff --git a/Runtime/UI/Actions/SetUIStyle.cs b/Runtime/UI/Actions/SetUIStyle.cs index 22cb760..0b73451 100644 --- a/Runtime/UI/Actions/SetUIStyle.cs +++ b/Runtime/UI/Actions/SetUIStyle.cs @@ -2,27 +2,26 @@ using Godot; using System; -namespace Rokojori +namespace Rokojori; + +[Tool,GlobalClass] +public partial class SetUIStyle: Action { - [Tool,GlobalClass] - public partial class SetUIStyle: Action - { - [Export] - public Control uiNode; + [Export] + public Control uiNode; - [Export] - public UIStyle style; + [Export] + public UIStyle style; - protected override void _OnTrigger() + protected override void _OnTrigger() + { + var uiStyleable = uiNode as UIStylePropertyContainer; + + if ( uiStyleable == null ) { - var uiStyleable = uiNode as UIStylePropertyContainer; - - if ( uiStyleable == null ) - { - return; - } - - uiStyleable.SetUIStyleParent( style ); + return; } + + uiStyleable.SetUIStyleParent( style ); } -} \ No newline at end of file +} diff --git a/Runtime/UI/Nodes/UIImage.cs b/Runtime/UI/Nodes/Image/UIImage.cs similarity index 87% rename from Runtime/UI/Nodes/UIImage.cs rename to Runtime/UI/Nodes/Image/UIImage.cs index 11d227a..3b08bf1 100644 --- a/Runtime/UI/Nodes/UIImage.cs +++ b/Runtime/UI/Nodes/Image/UIImage.cs @@ -88,6 +88,55 @@ namespace Rokojori public override void _Ready() { + FocusEntered += ()=> + { + this.LogInfo( "Focused", setActiveWhenFocused.Length ); + AddUISelectorFlag( UISelectorFlag.Focus ); + + var sound = UIStyle.GetUISound( this, UISoundProperty.FocusEntered ); + + if ( sound != null ) + { + GetUI().PlaySound( sound ); + } + + onFocusEntered?.Trigger(); + + setActiveWhenFocused?.ForEach( + ( c )=> + { + var uiStylable = c as UIStylePropertyContainerNode; + + uiStylable?.AddUISelectorFlag( UISelectorFlag.Active ); + } + ); + + }; + + FocusExited += ()=> + { + this.LogInfo( "Blurred" ); + RemoveUISelectorFlag( UISelectorFlag.Focus ); + + var sound = UIStyle.GetUISound( this, UISoundProperty.FocusExited ); + + if ( sound != null ) + { + GetUI().PlaySound( sound ); + } + + onFocusExited?.Trigger(); + + setActiveWhenFocused?.ForEach( + ( c )=> + { + var uiStylable = c as UIStylePropertyContainerNode; + + uiStylable?.RemoveUISelectorFlag( UISelectorFlag.Active ); + } + ); + }; + MouseEntered += ()=> { AddUISelectorFlag( UISelectorFlag.Hover, hoverID ); @@ -423,18 +472,62 @@ namespace Rokojori public UILayout GetUILayout() { return UILayout.___; - } + } - [ExportGroup( "Pointer" )] + + [ExportGroup( "Interactivity" )] [Export] public UICursor hoverCursor; + [Export] + public Action onFocusEntered; + + [Export] + public Action onFocusExited; + + [Export] + public Control[] setActiveWhenFocused = []; + public UICursor GetHoverCursor( UIStylePropertyContainer container ) { return hoverCursor; } + [ExportGroup( "Sound" )] + [Export] + public UISoundData onFocusSound; + [Export] + public UISoundData onBlurSound; + + public UISoundData GetUISoundProperty( UISoundProperty property ) + { + if ( UISoundProperty.FocusEntered == property ) + { + return onFocusSound; + } + else if ( UISoundProperty.FocusExited == property ) + { + return onFocusSound; + } + + return null; + } + + public void SetUISoundProperty( UISoundProperty property, UISoundData stream ) + { + if ( UISoundProperty.FocusEntered == property ) + { + onFocusSound = stream; + } + else if ( UISoundProperty.FocusExited == property ) + { + onFocusSound = stream; + } + } + + + public ShaderUIColor[] GetShaderUIColors() { return colorProperties; @@ -562,6 +655,9 @@ namespace Rokojori } + [Export] + public bool debugOutput = false; + public void Update() { @@ -611,15 +707,17 @@ namespace Rokojori var numberProperties = imageType != null ? imageType.GetNumberShaderProperties() : []; var numberPropertyName = new FloatPropertyName(); + var assignmentInfo = ""; + foreach ( var n in numberProperties ) { var relative = 100f; - if ( n.EndsWith( ".x" ) ) + if ( n.EndsWith( ".x" ) || n.EndsWith( "X" ) ) { relative = w; } - else if ( n.EndsWith( ".y" ) ) + else if ( n.EndsWith( ".y" ) || n.EndsWith( "Y" ) ) { relative = h; } @@ -628,8 +726,18 @@ namespace Rokojori var value = UINumber.Compute( this, UIStyleNumberProperty.FloatShaderProperty, n, 0, relative ); numberPropertyName.propertyName = n; numberPropertyName.Set( Material, value ); - } + if ( debugOutput ) + { + assignmentInfo += "\n" + numberPropertyName.propertyName + "=" + value._FFF(); + } + + } + + if ( debugOutput ) + { + this.LogInfo( assignmentInfo ); + } } diff --git a/Runtime/UI/Nodes/UIImage.cs.uid b/Runtime/UI/Nodes/Image/UIImage.cs.uid similarity index 100% rename from Runtime/UI/Nodes/UIImage.cs.uid rename to Runtime/UI/Nodes/Image/UIImage.cs.uid diff --git a/Runtime/UI/Nodes/UIImageTypes/NinePatchUIImageType.cs b/Runtime/UI/Nodes/Image/UIImageTypes/NinePatchUIImageType.cs similarity index 100% rename from Runtime/UI/Nodes/UIImageTypes/NinePatchUIImageType.cs rename to Runtime/UI/Nodes/Image/UIImageTypes/NinePatchUIImageType.cs diff --git a/Runtime/UI/Nodes/UIImageTypes/NinePatchUIImageType.cs.uid b/Runtime/UI/Nodes/Image/UIImageTypes/NinePatchUIImageType.cs.uid similarity index 100% rename from Runtime/UI/Nodes/UIImageTypes/NinePatchUIImageType.cs.uid rename to Runtime/UI/Nodes/Image/UIImageTypes/NinePatchUIImageType.cs.uid diff --git a/Runtime/UI/Nodes/UIImageTypes/RoundedRectangleUIImageType.cs b/Runtime/UI/Nodes/Image/UIImageTypes/RoundedRectangleUIImageType.cs similarity index 100% rename from Runtime/UI/Nodes/UIImageTypes/RoundedRectangleUIImageType.cs rename to Runtime/UI/Nodes/Image/UIImageTypes/RoundedRectangleUIImageType.cs diff --git a/Runtime/UI/Nodes/UIImageTypes/RoundedRectangleUIImageType.cs.uid b/Runtime/UI/Nodes/Image/UIImageTypes/RoundedRectangleUIImageType.cs.uid similarity index 100% rename from Runtime/UI/Nodes/UIImageTypes/RoundedRectangleUIImageType.cs.uid rename to Runtime/UI/Nodes/Image/UIImageTypes/RoundedRectangleUIImageType.cs.uid diff --git a/Runtime/UI/Nodes/UIImageTypes/SliderUIImageType.cs b/Runtime/UI/Nodes/Image/UIImageTypes/SliderUIImageType.cs similarity index 79% rename from Runtime/UI/Nodes/UIImageTypes/SliderUIImageType.cs rename to Runtime/UI/Nodes/Image/UIImageTypes/SliderUIImageType.cs index 29ec7f4..fed7316 100644 --- a/Runtime/UI/Nodes/UIImageTypes/SliderUIImageType.cs +++ b/Runtime/UI/Nodes/Image/UIImageTypes/SliderUIImageType.cs @@ -28,9 +28,11 @@ namespace Rokojori SliderShader.strokeSize.propertyName, SliderShader.offset.propertyName, SliderShader.sliderStrokeSize.propertyName, - SliderShader.sliderSize.propertyName + ".x", - SliderShader.sliderSize.propertyName + ".y", - SliderShader.sliderBorders.propertyName + SliderShader.sliderSizeX.propertyName, + SliderShader.sliderSizeY.propertyName, + SliderShader.sliderBorders.propertyName, + SliderShader.sliderSizeMarginX.propertyName, + SliderShader.sliderSizeMarginY.propertyName, ]; public override string[] GetNumberShaderProperties() @@ -94,6 +96,22 @@ namespace Rokojori set { _sliderSizeY = value; onChange.DispatchEvent( null ); } } + UINumber _sliderSizeMarginX; + [Export] + public UINumber sliderSizeMarginX + { + get => _sliderSizeMarginX; + set { _sliderSizeMarginX = value; onChange.DispatchEvent( null ); } + } + + UINumber _sliderSizeMarginY; + [Export] + public UINumber sliderSizeMarginY + { + get => _sliderSizeMarginY; + set { _sliderSizeMarginY = value; onChange.DispatchEvent( null ); } + } + UINumber _sliderBorderRadius; [Export] public UINumber sliderBorderRadius @@ -163,16 +181,26 @@ namespace Rokojori return offset; } - if ( SliderShader.sliderSize.propertyName + ".x" == shaderPropertyName ) + if ( SliderShader.sliderSizeX.propertyName == shaderPropertyName ) { return sliderSizeX; } - if ( SliderShader.sliderSize.propertyName + ".y" == shaderPropertyName ) + if ( SliderShader.sliderSizeY.propertyName == shaderPropertyName ) { return sliderSizeY; } + if ( SliderShader.sliderSizeMarginX.propertyName == shaderPropertyName ) + { + return sliderSizeMarginX; + } + + if ( SliderShader.sliderSizeMarginY.propertyName == shaderPropertyName ) + { + return sliderSizeMarginY; + } + if ( SliderShader.sliderStrokeSize.propertyName == shaderPropertyName ) { return sliderStrokeSize; @@ -188,27 +216,30 @@ namespace Rokojori return null; } + [Export] + public bool disableCaching = false; + protected override void _Assign( UIImage image ) { - if ( _materials.ContainsKey( image ) ) + if ( _materials.ContainsKey( image ) && ! disableCaching ) { - this.LogInfo( "Has Image in cached materials", HierarchyName.Of( image ) ); + // this.LogInfo( "Has Image in cached materials", HierarchyName.Of( image ) ); if ( image.Material == null ) { - this.LogInfo( "Material was null, assigned Image from cached materials" ); + // this.LogInfo( "Material was null, assigned Image from cached materials" ); image.Material = _materials[ image ]; } else { - this.LogInfo( "Did not assigned material, already exists" ); + // this.LogInfo( "Did not assigned material, already exists" ); } return; } else { - this.LogInfo( "Image had no material and was not cached, caching & creating material", HierarchyName.Of( image ) ); + // this.LogInfo( "Image had no material and was not cached, caching & creating material", HierarchyName.Of( image ) ); } _materials[ image ] = new SliderMaterial(); diff --git a/Runtime/UI/Nodes/UIImageTypes/SliderUIImageType.cs.uid b/Runtime/UI/Nodes/Image/UIImageTypes/SliderUIImageType.cs.uid similarity index 100% rename from Runtime/UI/Nodes/UIImageTypes/SliderUIImageType.cs.uid rename to Runtime/UI/Nodes/Image/UIImageTypes/SliderUIImageType.cs.uid diff --git a/Runtime/UI/Nodes/UIImageTypes/UIImageType.cs b/Runtime/UI/Nodes/Image/UIImageTypes/UIImageType.cs similarity index 100% rename from Runtime/UI/Nodes/UIImageTypes/UIImageType.cs rename to Runtime/UI/Nodes/Image/UIImageTypes/UIImageType.cs diff --git a/Runtime/UI/Nodes/UIImageTypes/UIImageType.cs.uid b/Runtime/UI/Nodes/Image/UIImageTypes/UIImageType.cs.uid similarity index 100% rename from Runtime/UI/Nodes/UIImageTypes/UIImageType.cs.uid rename to Runtime/UI/Nodes/Image/UIImageTypes/UIImageType.cs.uid diff --git a/Runtime/UI/Nodes/Selections/ListSelection/ChangeUIListSelection.cs b/Runtime/UI/Nodes/Selections/ListSelection/ChangeUIListSelection.cs new file mode 100644 index 0000000..15ee4c1 --- /dev/null +++ b/Runtime/UI/Nodes/Selections/ListSelection/ChangeUIListSelection.cs @@ -0,0 +1,45 @@ +using Godot; +using Rokojori; +using System.Collections.Generic; +using System.Linq; + +namespace Rokojori; + +[Tool] +[GlobalClass] +public partial class ChangeUIListSelection:Action +{ + + [Export] + public UIListSelection selection; + + public enum Mode + { + Set, + Change + } + + [Export] + public Mode mode; + + [Export] + public int value; + + protected override void _OnTrigger() + { + + if ( selection == null ) + { + return; + } + + if ( Mode.Set == mode ) + { + selection.selected = value; + } + else if ( Mode.Change == mode ) + { + selection.selected = MathX.Repeat( selection.selected + value, selection.values.Length ); + } + } +} \ No newline at end of file diff --git a/Runtime/UI/Nodes/Selections/ListSelection/ChangeUIListSelection.cs.uid b/Runtime/UI/Nodes/Selections/ListSelection/ChangeUIListSelection.cs.uid new file mode 100644 index 0000000..f989e90 --- /dev/null +++ b/Runtime/UI/Nodes/Selections/ListSelection/ChangeUIListSelection.cs.uid @@ -0,0 +1 @@ +uid://b50yldymrhply diff --git a/Runtime/UI/Nodes/Selections/ListSelection/UIListSelection.cs b/Runtime/UI/Nodes/Selections/ListSelection/UIListSelection.cs new file mode 100644 index 0000000..62eb714 --- /dev/null +++ b/Runtime/UI/Nodes/Selections/ListSelection/UIListSelection.cs @@ -0,0 +1,72 @@ +using Godot; +using Rokojori; +using System.Collections.Generic; +using System.Linq; + +namespace Rokojori; + +[Tool] +[GlobalClass] +public partial class UIListSelection:UIText, UIFocusProcessor +{ + int _selected = -1; + LocalizedString _selectedOption = null; + + public string SerializeSelectedOption() + { + return _selectedOption.GetLocalizedString( LocaleCode.en ); + } + + public void SetSelectedBySerialized( string serializedEntry ) + { + var index = values.ToList().FindIndex( v => v.GetLocalizedString( LocaleCode.en ) == serializedEntry ); + + selected = index; + + } + + public void OnFocusProcess( double delta ) + { + + } + + [Export] + public Action onSelectionChange; + public EventSlot _onSelectionChange = new EventSlot(); + + [Export] + public int selected + { + get => _selected; + set + { + if ( values == null || values.Length <= 0 ) + { + _selected = selected; + return; + } + + var next = Mathf.Clamp( value, 0, values.Length - 1 ); + + if ( _selected == next ) + { + return; + } + + _selected = next; + SyncSelection(); + onSelectionChange?.Trigger(); + _onSelectionChange.DispatchEvent( _selected ); + } + } + + void SyncSelection() + { + locale = values[ _selected ]; + } + + [Export] + public LocalizedString[] values = []; + + +} \ No newline at end of file diff --git a/Runtime/UI/Nodes/Selections/ListSelection/UIListSelection.cs.uid b/Runtime/UI/Nodes/Selections/ListSelection/UIListSelection.cs.uid new file mode 100644 index 0000000..c893bdf --- /dev/null +++ b/Runtime/UI/Nodes/Selections/ListSelection/UIListSelection.cs.uid @@ -0,0 +1 @@ +uid://2ftd0bt6rrgo diff --git a/Runtime/UI/Nodes/Sliders/ScrollSlider/UIScrollSlider.cs b/Runtime/UI/Nodes/Sliders/ScrollSlider/UIScrollSlider.cs new file mode 100644 index 0000000..135b978 --- /dev/null +++ b/Runtime/UI/Nodes/Sliders/ScrollSlider/UIScrollSlider.cs @@ -0,0 +1,75 @@ +using Godot; +using Rokojori; +using System.Collections.Generic; +using System.Linq; + +namespace Rokojori; + +[Tool] +[GlobalClass,Icon("res://addons/rokojori_action_library/Icons/UIImage.svg")] +public partial class UIScrollSlider:UISlider +{ + [Export] + public Control scrollArea; + + [Export] + public Control scrollContainer; + + bool _hasEventListener = false; + + public override void _Ready() + { + base._Ready(); + + if ( ! _hasEventListener ) + { + _onSliderChange.AddAction( ( pos ) => { SyncScroll(); } ); + _hasEventListener = true; + } + + } + + [Export] + public bool recreateMaterial = false; + + public override void _Process( double delta ) + { + if ( recreateMaterial ) + { + UpdateImageType(); + recreateMaterial = false; + } + + base._Process( delta ); + } + + Vector2 _lastOffset = Vector2.Zero; + + public void SyncScroll() + { + var containerSize = scrollContainer.Size; + var areaSize = scrollArea.Size; + + var scroll = areaSize - containerSize; + scroll = scroll.Max( Vector2.Zero ); + + var stylable = scrollArea as UIStylePropertyContainerNode; + + var scrollOffset = -scroll * sliderValue; + + var diff = _lastOffset - scrollOffset; + + this.LogInfo( scroll, sliderValue, scrollOffset ); + + + if ( stylable == null ) + { + scrollArea.Position = scroll * sliderValue; + } + else + { + stylable.SetUIStyleNumberProperty( UIStyleNumberProperty.Left, UINumber.Create( scrollOffset.X, "px" ) ); + stylable.SetUIStyleNumberProperty( UIStyleNumberProperty.Top, UINumber.Create( scrollOffset.Y, "px" ) ); + } + } +} \ No newline at end of file diff --git a/Runtime/UI/Nodes/Sliders/ScrollSlider/UIScrollSlider.cs.uid b/Runtime/UI/Nodes/Sliders/ScrollSlider/UIScrollSlider.cs.uid new file mode 100644 index 0000000..2371658 --- /dev/null +++ b/Runtime/UI/Nodes/Sliders/ScrollSlider/UIScrollSlider.cs.uid @@ -0,0 +1 @@ +uid://ciqgpp82a2wr0 diff --git a/Runtime/UI/Nodes/Sliders/UISlider.cs b/Runtime/UI/Nodes/Sliders/UISlider.cs new file mode 100644 index 0000000..d8de45f --- /dev/null +++ b/Runtime/UI/Nodes/Sliders/UISlider.cs @@ -0,0 +1,478 @@ + +using Godot; +using Rokojori; +using System.Collections.Generic; +using System.Linq; + +namespace Rokojori; + +[Tool] +[GlobalClass,Icon("res://addons/rokojori_action_library/Icons/UIImage.svg")] +public partial class UISlider:UIImage, UIFocusProcessor +{ + public enum Direction + { + Vertical, + Horizontal, + Both + } + + [Export] + public Direction direction = Direction.Vertical; + + [Export] + public float offsetPerInput = 1f / 20f; + + + [Export] + public Smoothing smoothing; + + + [Export] + public Action onSliderChange; + public readonly EventSlot _onSliderChange = new EventSlot(); + + [ExportGroup("Testing")] + // [Export( PropertyHint.Range, "0,1")] + // public Vector2 editorSliderValue = Vector2.Zero; + + Vector2 _sliderValue; + + [Export( PropertyHint.Range, "0,1")] + public Vector2 sliderValue + { + get { return _sliderValue; } + set + { + _sliderValue = value; + SyncSliderValue(); + } + } + + public float mainValue => direction == Direction.Vertical ? sliderValue.Y : sliderValue.X; + + public Vector2 GetNextSliderMainValue( float value ) + { + if ( Direction.Vertical == direction ) + { + return new Vector2( 0.5f, value ); + } + else + { + return new Vector2( value, 0.5f ); + } + } + + public void SetSliderMainValue( float value ) + { + if ( Direction.Vertical == direction ) + { + _sliderValue.Y = value; + } + else + { + _sliderValue.X = value; + } + + SyncSliderValue(); + + _onSliderChange.DispatchEvent( _sliderValue ); + onSliderChange?.Trigger(); + + } + + void SyncSliderValue() + { + SliderShader.sliderValue.Set( Material, sliderValue ); + // this.LogInfo( "Set slider value:", sliderValue, Material ); + + // var sm = Material as ShaderMaterial; + // sm.SetShaderParameter( "sliderValue", sliderValue ); + } + + public override void _Ready() + { + base._Ready(); + + if ( imageType == null ) + { + imageType = new SliderUIImageType(); + } + + if ( Texture == null ) + { + Texture = UI.whiteTexture.Get(); + } + + var uiSliderImageType = _imageType as SliderUIImageType; + + if ( uiSliderImageType != null ) + { + uiSliderImageType.Clear( this ); + uiSliderImageType.Assign( this ); + + } + + ComputeUIAncestorDepth(); + + SyncSliderValue(); + + + AssignListener(); + } + + [Export] + public bool debugInfo = false; + + [Export] + public string[] propertyInfos = []; + + + float lastLeft = 0f; + float lastRight = 0f; + float lastUp = 0f; + float lastDown = 0f; + + public void OnFocusProcess( double delta ) + { + var settings = GetUI().settings; + + if ( settings == null ) + { + return; + } + + if ( Direction.Horizontal == direction ) + { + + var offset = 0; + + if ( settings.uiLeft.IsRepeatDown( ref lastLeft ) ) + { + offset --; + } + + if ( settings.uiRight.IsRepeatDown( ref lastRight ) ) + { + offset ++; + } + + if ( offset != 0 ) + { + var nextMainValue = MathX.Clamp01( mainValue + offset * offsetPerInput ); + nextValue = NormalizedToButtonPosition( GetNextSliderMainValue( nextMainValue ) ); + + if ( ! _updatingPosition ) + { + _updatingPosition = true; + GetUI().onProcess.AddAction( UpdatePosition ); + } + + } + } + + + // UpdatePosition( (float) delta ); + } + + // public override void _GuiInput( InputEvent inputEvent ) + // { + // if ( ! processInputs ) + // { + // return; + // } + + // if ( ! HasFocus() ) + // { + // return; + // } + + // var settings = GetUI()?.settings; + + // if ( settings == null ) + // { + // return; + // } + + // if ( Direction.Horizontal == direction ) + // { + // var offset = 0; + + // // this.LogInfo( Sensor.GetInputEventInfo( inputEvent ) ); + // // this.LogInfo( + // // "Is Horizontal", + // // "Left:", settings.uiLeft.IsSensor( inputEvent ), "Left Down:", settings.uiLeft.IsDown( inputEvent ), + // // "Right:", settings.uiRight.IsSensor( inputEvent ), "Right Down:", settings.uiRight.IsDown( inputEvent ) + // // ); + + // if ( settings.uiLeft.IsDown( inputEvent ) ) + // { + // offset --; + // } + + // if ( settings.uiRight.IsDown( inputEvent ) ) + // { + // offset ++; + // } + + // if ( offset != 0 ) + // { + // // this.LogInfo( "Offset", offset ); + + // var nextValue = MathX.Clamp01( mainValue + offset * offsetPerInput ); + // SetSliderMainValue( nextValue ); + // } + // } + + // if ( Direction.Vertical == direction ) + // { + // var offset = 0; + + // if ( settings.uiUp?.isActive ?? false ) + // { + // offset --; + // } + + // if ( settings.uiDown?.isActive ?? false ) + // { + // offset ++; + // } + + // var nextValue = MathX.Clamp01( mainValue + offset * offsetPerInput ); + // SetSliderMainValue( nextValue ); + // } + // } + + public override void _Process( double delta ) + { + // ProcessInputs(); + + if ( ! debugInfo ) + { + return; + } + + + + + var it = imageType as SliderUIImageType; + + if ( it == null ) + { + return; + } + + var propNames = it.GetNumberShaderProperties(); + + 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 ); + + var infos = new List(); + + for ( int i = 0; i < propNames.Length; i++ ) + { + var n = propNames[ i ]; + var p = it.GetUIStyleNumberProperty( UIStyleNumberProperty.FloatShaderProperty, n ); + + if ( p == null ) + { + continue; + } + + var relative = 100f; + + if ( n.EndsWith( "X" ) ) + { + relative = w; + } + else if ( n.EndsWith( "Y" ) ) + { + relative = h; + } + + + var value = UINumber.Compute( this, UIStyleNumberProperty.FloatShaderProperty, n, 0, relative ); + infos.Add( "[" + n + "] (" + p.value._FFF() + " * " + p.unit +") :" + value._FFF() ); + } + + propertyInfos = infos.ToArray(); + + this.LogInfo( propertyInfos ); + + + debugInfo = false; + + } + + + + UIDragging.UIDraggingCallbacks leftMouseCallbacks; + Vector2 cachedMouseOffset; + Vector2 cachedButtonPosition; + + bool _dragging = false; + bool _updatingPosition = false; + + string scrollID = IDGenerator.GenerateID(); + + float ComputeShaderProperty( string n, float relative = 100 ) + { + return UINumber.Compute( this, UIStyleNumberProperty.FloatShaderProperty, n, 0, relative ); + } + + Vector2 sliderSize + { + get + { + 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 ); + + var valueX = ComputeShaderProperty( SliderShader.sliderSizeX.propertyName, w ); + var valueY = ComputeShaderProperty( SliderShader.sliderSizeY.propertyName, h ); + + return new Vector2( valueX, valueY ); + } + } + + Vector2 sliderSizeMargins + { + get + { + 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 ); + + var valueX = ComputeShaderProperty( SliderShader.sliderSizeMarginX.propertyName, w ); + var valueY = ComputeShaderProperty( SliderShader.sliderSizeMarginY.propertyName, h ); + + return new Vector2( valueX, valueY ); + } + } + + Vector2 sliderRange => Size - ( sliderSize + sliderSizeMargins ); + Vector2 sliderOffset => sliderSize; + + Vector2 buttonPositionMin + { + get { return NormalizedToButtonPosition( Vector2.Zero ); } + } + + Vector2 buttonPositionMax + { + get { return NormalizedToButtonPosition( Vector2.One ); } + } + + + Vector2 NormalizedToButtonPosition( Vector2 normalized ) + { + return normalized * sliderRange + sliderOffset; + } + + Vector2 ButtonPositionToNormalized( Vector2 buttonPosition ) + { + return ( buttonPosition - sliderOffset ) / sliderRange; + } + + + bool _listenerAssigned = false; + + void AssignListener() + { + if ( _listenerAssigned ) + { + return; + } + + leftMouseCallbacks = UIDragging.OnLeftMouseButton( this, + ( ev )=> + { + if ( ev.isStart ) + { + if ( ! ( _updatingPosition || _dragging ) ) + { + cachedButtonPosition = NormalizedToButtonPosition( sliderValue ); + smoothing?.SetCurrent( cachedButtonPosition ); + + _dragging = true; + _updatingPosition = true; + + ev.ui.onProcess.AddAction( UpdatePosition ); + } + + } + else if ( ev.isEnd ) + { + _dragging = false; + } + + var nextPosition = cachedButtonPosition + ev.distanceToStart; + nextValue = nextPosition.Clamp( buttonPositionMin, buttonPositionMax ); + + } + ); + + _listenerAssigned = true; + } + + Vector2 nextValue; + + Vector2 GetButtonScrollRange() + { + return Vector2.Zero; + // return ( Size - button.Size ).Max( Vector2.Zero ); + } + + Vector2 cachedOffset = Vector2.Zero; + + void UpdatePosition( float delta ) + { + + var value = Smoothing.Apply( smoothing, nextValue, delta ); + + // this.LogInfo( "UpdatePosition:", value ); + + var uiStyleContainer = ( UIStylePropertyContainerNode ) this; + + uiStyleContainer.SetLayoutDirtyFlag(); + + if ( ! _dragging && ( value - nextValue ).Length() < 1 ) + { + var ui = UIHolder.GetUI( this ); + ui.onProcess.RemoveAction( UpdatePosition ); + _updatingPosition = false; + // this.LogInfo( "Removed Processing" ); + + value = nextValue; + + uiStyleContainer.RemoveUISelectorFlag( UISelectorFlag.Scrolling, scrollID ); + + } + + var currentSliderValue = ButtonPositionToNormalized( value ); + + if ( Direction.Vertical == direction ) + { + currentSliderValue.X = 0.5f; + } + else if ( Direction.Horizontal == direction ) + { + currentSliderValue.Y = 0.5f; + } + + _sliderValue = currentSliderValue; + SyncSliderValue(); + + onSliderChange?.Trigger(); + _onSliderChange.DispatchEvent( _sliderValue ); + + } + +} diff --git a/Runtime/UI/Nodes/UISlider.cs.uid b/Runtime/UI/Nodes/Sliders/UISlider.cs.uid similarity index 100% rename from Runtime/UI/Nodes/UISlider.cs.uid rename to Runtime/UI/Nodes/Sliders/UISlider.cs.uid diff --git a/Runtime/UI/Nodes/Sliders/ValueSlider/UIFloatValueMode.cs b/Runtime/UI/Nodes/Sliders/ValueSlider/UIFloatValueMode.cs new file mode 100644 index 0000000..f4e1bd2 --- /dev/null +++ b/Runtime/UI/Nodes/Sliders/ValueSlider/UIFloatValueMode.cs @@ -0,0 +1,125 @@ +using Godot; + +namespace Rokojori; + +[Tool] +[GlobalClass] +public partial class UIFloatValueMode:UIValueSliderMode +{ + [Export] + public LocalizedString prefix; + + [Export] + public float min = 0; + + [Export] + public float max = 1; + + [Export] + public int steps = -1; + + [Export] + public float stepSize = -1; + + public enum DecimialPoints + { + Int, + I_0, + I_00, + I_000 + } + + [Export] + public DecimialPoints decimialPoints = DecimialPoints.Int; + + [Export] + public LocalizedString suffix; + + public static UIFloatValueMode From( NumberAppSetting numberAppSetting ) + { + var mode = new UIFloatValueMode(); + mode.CopyFrom( numberAppSetting ); + return mode; + } + + public void CopyFrom( NumberAppSetting numberAppSetting ) + { + prefix = numberAppSetting.prefix; + suffix = numberAppSetting.suffix; + steps = numberAppSetting.steps; + stepSize = numberAppSetting.stepSize; + min = numberAppSetting.min; + max = numberAppSetting.max; + decimialPoints = numberAppSetting.decimialPoints; + } + + public int combinedSteps => steps > 0 ? steps : + stepSize > 0 ? Mathf.CeilToInt( ( max - min ) / stepSize ) : + -1; + + + + + public string prefixValue => prefix?.currentValue ?? ""; + public string suffixValue => suffix?.currentValue ?? ""; + + public float quantize( float normalized ) + { + var comSteps = combinedSteps; + + if ( comSteps <= 0 ) + { + return normalized; + } + + return MathX.SnapRounded( normalized, 1f / comSteps ); + } + + public override string NormalizedToLabel( float normalized ) + { + normalized = quantize( normalized ); + + var value = MathX.LerpClamped( min, max, normalized ); + + var stringValue = ""; + + if ( DecimialPoints.Int == decimialPoints ) + { + stringValue = Mathf.RoundToInt( value ) + ""; + } + else + { + stringValue = DecimialPoints.I_0 == decimialPoints ? value._F() : + DecimialPoints.I_00 == decimialPoints ? value._FF() : + value._FFF(); + } + + + return prefixValue + stringValue + suffixValue; + } + + public float GetValueFromNormalized( float normalized ) + { + normalized = quantize( normalized ); + return MathX.LerpClamped( min, max, normalized ); + } + + public override string GetSerializedValue( float normalized ) + { + return GetValueFromNormalized( normalized )._G(); + } + + public override float FromSerializedToNormalized( string serialized ) + { + var value = RegexUtility.ParseFloat( serialized ); + return MathX.Normalize( value, min, max ); + } + + public override float LabelToNormalized( string label ) + { + var value = RegexUtility.ParseFloat( label.ReplaceStart( prefixValue, "" ).ReplaceEnd( suffixValue, "" ) ); + + return MathX.Normalize( value, min, max ); + } + +} \ No newline at end of file diff --git a/Runtime/UI/Nodes/Sliders/ValueSlider/UIFloatValueMode.cs.uid b/Runtime/UI/Nodes/Sliders/ValueSlider/UIFloatValueMode.cs.uid new file mode 100644 index 0000000..56710fc --- /dev/null +++ b/Runtime/UI/Nodes/Sliders/ValueSlider/UIFloatValueMode.cs.uid @@ -0,0 +1 @@ +uid://bsonpc71ochpe diff --git a/Runtime/UI/Nodes/Sliders/ValueSlider/UIResolutionScaleMode.cs b/Runtime/UI/Nodes/Sliders/ValueSlider/UIResolutionScaleMode.cs new file mode 100644 index 0000000..3341eee --- /dev/null +++ b/Runtime/UI/Nodes/Sliders/ValueSlider/UIResolutionScaleMode.cs @@ -0,0 +1,26 @@ +using Godot; + +namespace Rokojori; + +[Tool] +[GlobalClass] +public partial class UIResolutionScaleMode:UIFloatValueMode +{ + [Export] + public float userScaleToResolutionScale = 1f / 100f; + public Vector2 windowSize; + + + + public override string NormalizedToLabel( float normalized ) + { + var stringValue = base.NormalizedToLabel( normalized ); + var scale = GetValueFromNormalized( normalized ) * userScaleToResolutionScale; + + var win = windowSize * scale; + var winx = Mathf.RoundToInt( win.X ); + var winy = Mathf.RoundToInt( win.Y ); + + return stringValue + "(" + winx + "x" + winy +")"; + } +} \ No newline at end of file diff --git a/Runtime/UI/Nodes/Sliders/ValueSlider/UIResolutionScaleMode.cs.uid b/Runtime/UI/Nodes/Sliders/ValueSlider/UIResolutionScaleMode.cs.uid new file mode 100644 index 0000000..1231c56 --- /dev/null +++ b/Runtime/UI/Nodes/Sliders/ValueSlider/UIResolutionScaleMode.cs.uid @@ -0,0 +1 @@ +uid://dtli3dnpem82l diff --git a/Runtime/UI/Nodes/Sliders/ValueSlider/UIValueSlider.cs b/Runtime/UI/Nodes/Sliders/ValueSlider/UIValueSlider.cs new file mode 100644 index 0000000..7a64586 --- /dev/null +++ b/Runtime/UI/Nodes/Sliders/ValueSlider/UIValueSlider.cs @@ -0,0 +1,51 @@ +using Godot; +using Rokojori; +using System.Collections.Generic; +using System.Linq; + +namespace Rokojori; + +[Tool] +[GlobalClass,Icon("res://addons/rokojori_action_library/Icons/UIImage.svg")] +public partial class UIValueSlider:UISlider +{ + [Export] + public UIText valueText; + + [Export] + public UIValueSliderMode mode; + + bool _hasEventListener = false; + + public override void _Ready() + { + base._Ready(); + + if ( ! _hasEventListener ) + { + _onSliderChange.AddAction( ( pos ) => { SyncScroll(); } ); + _hasEventListener = true; + } + + } + + [Export] + public bool recreateMaterial = false; + + public override void _Process( double delta ) + { + if ( recreateMaterial ) + { + UpdateImageType(); + recreateMaterial = false; + } + + base._Process( delta ); + } + + public void SyncScroll() + { + var label = mode.NormalizedToLabel( mainValue ); + valueText.locale = LocaleText.Create( label ); + } +} \ No newline at end of file diff --git a/Runtime/UI/Nodes/Sliders/ValueSlider/UIValueSlider.cs.uid b/Runtime/UI/Nodes/Sliders/ValueSlider/UIValueSlider.cs.uid new file mode 100644 index 0000000..9619b94 --- /dev/null +++ b/Runtime/UI/Nodes/Sliders/ValueSlider/UIValueSlider.cs.uid @@ -0,0 +1 @@ +uid://cqi3jitprf7o0 diff --git a/Runtime/UI/Nodes/Sliders/ValueSlider/UIValueSliderMode.cs b/Runtime/UI/Nodes/Sliders/ValueSlider/UIValueSliderMode.cs new file mode 100644 index 0000000..8613cf8 --- /dev/null +++ b/Runtime/UI/Nodes/Sliders/ValueSlider/UIValueSliderMode.cs @@ -0,0 +1,24 @@ +using Godot; +using Rokojori; +using System.Collections.Generic; +using System.Linq; + +namespace Rokojori; + +[Tool] +[GlobalClass] +public abstract partial class UIValueSliderMode:Resource +{ + public abstract string NormalizedToLabel( float normalized ); + public virtual string GetSerializedValue( float normalized ) + { + return NormalizedToLabel( normalized ); + } + + public abstract float LabelToNormalized( string label ); + public virtual float FromSerializedToNormalized( string serialized ) + { + return LabelToNormalized( serialized ); + } + +} \ No newline at end of file diff --git a/Runtime/UI/Nodes/Sliders/ValueSlider/UIValueSliderMode.cs.uid b/Runtime/UI/Nodes/Sliders/ValueSlider/UIValueSliderMode.cs.uid new file mode 100644 index 0000000..27bce3d --- /dev/null +++ b/Runtime/UI/Nodes/Sliders/ValueSlider/UIValueSliderMode.cs.uid @@ -0,0 +1 @@ +uid://srhht1qmu0jv diff --git a/Runtime/UI/Nodes/UIFocusProcessor.cs b/Runtime/UI/Nodes/UIFocusProcessor.cs new file mode 100644 index 0000000..dd8b79f --- /dev/null +++ b/Runtime/UI/Nodes/UIFocusProcessor.cs @@ -0,0 +1,11 @@ + +using Godot; +using Rokojori; +using System.Collections.Generic; + +namespace Rokojori; + +public interface UIFocusProcessor +{ + public void OnFocusProcess( double delta ); +} diff --git a/Runtime/UI/Nodes/UIFocusProcessor.cs.uid b/Runtime/UI/Nodes/UIFocusProcessor.cs.uid new file mode 100644 index 0000000..c992adc --- /dev/null +++ b/Runtime/UI/Nodes/UIFocusProcessor.cs.uid @@ -0,0 +1 @@ +uid://dx4fcgne8btqm diff --git a/Runtime/UI/Nodes/UIRegion.cs b/Runtime/UI/Nodes/UIRegion.cs index 00ef565..0eda2ed 100644 --- a/Runtime/UI/Nodes/UIRegion.cs +++ b/Runtime/UI/Nodes/UIRegion.cs @@ -136,7 +136,45 @@ namespace Rokojori { return activeColorTransitions; } - + + [ExportGroup( "Sound" )] + [Export] + public UISoundData onFocusSound; + [Export] + public UISoundData onBlurSound; + + public UISoundData GetUISoundProperty( UISoundProperty property ) + { + if ( UISoundProperty.FocusEntered == property ) + { + return onFocusSound; + } + else if ( UISoundProperty.FocusExited == property ) + { + return onFocusSound; + } + + return null; + } + + public void SetUISoundProperty( UISoundProperty property, UISoundData stream ) + { + if ( UISoundProperty.FocusEntered == property ) + { + onFocusSound = stream; + } + else if ( UISoundProperty.FocusExited == property ) + { + onFocusSound = stream; + } + } + + [Export] + public Action onFocusEntered; + + [Export] + public Action onFocusExited; + #if TOOLS [ExportGroup("Editor SceneSetup")] [Export] @@ -327,6 +365,36 @@ namespace Rokojori public override void _Ready() { + FocusEntered += ()=> + { + AddUISelectorFlag( UISelectorFlag.Focus ); + + var sound = UIStyle.GetUISound( this, UISoundProperty.FocusEntered ); + + if ( sound != null ) + { + GetUI().PlaySound( sound ); + } + + onFocusEntered?.Trigger(); + + }; + + FocusExited += ()=> + { + RemoveUISelectorFlag( UISelectorFlag.Focus ); + + var sound = UIStyle.GetUISound( this, UISoundProperty.FocusExited ); + + if ( sound != null ) + { + GetUI().PlaySound( sound ); + } + + onFocusExited?.Trigger(); + }; + + MouseEntered += ()=> { AddUISelectorFlag( UISelectorFlag.Hover, hoverID ); @@ -405,6 +473,15 @@ namespace Rokojori UISelector.UpdateParentUISelectorFlags( this ); + this.LogInfo( + "flag:", flag, + "reference:", reference, + "enable:", enable, + "changed:", changed, + "numFlagsBefore:", numFlagsBefore, + "_selectorFlags:", _selectorFlags.Map( sf => sf.ResourcePath + " " + sf.ResourceName ).Join( ", " ) + ); + if ( changed ) { this.SetDirty(); diff --git a/Runtime/UI/Nodes/UIScrollContainer.cs b/Runtime/UI/Nodes/UIScrollContainer.cs deleted file mode 100644 index 2da30f9..0000000 --- a/Runtime/UI/Nodes/UIScrollContainer.cs +++ /dev/null @@ -1,39 +0,0 @@ - -using Godot; -using Rokojori; -using System.Collections.Generic; -using System.Linq; - -namespace Rokojori -{ - [Tool] - [GlobalClass,Icon("res://addons/rokojori_action_library/Icons/UIRegion.svg")] - public partial class UIScrollContainer:UIRegion - { - [Export] - public Control horizontalSlider; - - [Export] - public Control verticalSlider; - - [Export] - public Control content; - - public override void _Ready() - { - - } - - bool _initialized = false; - - void Initialize() - { - if ( _initialized ) - { - return; - } - - - } - } -} \ No newline at end of file diff --git a/Runtime/UI/Nodes/UIScrollContainer.cs.uid b/Runtime/UI/Nodes/UIScrollContainer.cs.uid deleted file mode 100644 index 32b5443..0000000 --- a/Runtime/UI/Nodes/UIScrollContainer.cs.uid +++ /dev/null @@ -1 +0,0 @@ -uid://btmqvwluvjwo0 diff --git a/Runtime/UI/Nodes/UISlider.cs b/Runtime/UI/Nodes/UISlider.cs deleted file mode 100644 index 2e7269f..0000000 --- a/Runtime/UI/Nodes/UISlider.cs +++ /dev/null @@ -1,302 +0,0 @@ - - - - -using Godot; -using Rokojori; -using System.Collections.Generic; -using System.Linq; - -namespace Rokojori -{ - [Tool] - [GlobalClass,Icon("res://addons/rokojori_action_library/Icons/UIImage.svg")] - public partial class UISlider:UIImage - { - public enum Direction - { - Vertical, - Horizontal, - Both - } - - [Export] - public Direction direction = Direction.Vertical; - - [Export] - public Smoothing smoothing; - - Vector2 _sliderValue; - - [Export] - public Vector2 sliderValue - { - get { return _sliderValue; } - set - { - _sliderValue = value; - SyncSliderValue(); - } - } - - void SyncSliderValue() - { - SliderShader.sliderValue.Set( Material, sliderValue ); - } - - public override void _Ready() - { - base._Ready(); - - if ( imageType == null ) - { - imageType = new SliderUIImageType(); - } - - if ( Texture == null ) - { - Texture = UI.whiteTexture.Get(); - } - - var uiSliderImageType = _imageType as SliderUIImageType; - - if ( uiSliderImageType != null ) - { - uiSliderImageType.Clear( this ); - uiSliderImageType.Assign( this ); - - } - - ComputeUIAncestorDepth(); - - SyncSliderValue(); - - - AssignListener(); - } - - [Export] - public bool debugInfo = false; - - [Export] - public string[] propertyInfos = []; - - public override void _Process( double delta ) - { - if ( ! debugInfo ) - { - return; - } - - var it = imageType as SliderUIImageType; - - if ( it == null ) - { - return; - } - - var propNames = it.GetNumberShaderProperties(); - - 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 ); - - var infos = new List(); - for ( int i = 0; i < propNames.Length; i++ ) - { - var n = propNames[ i ]; - var p = it.GetUIStyleNumberProperty( UIStyleNumberProperty.FloatShaderProperty, n ); - - if ( p == null ) - { - continue; - } - - var relative = 100f; - - if ( n.EndsWith( ".x" ) ) - { - relative = w; - } - else if ( n.EndsWith( ".y" ) ) - { - relative = h; - } - - - var value = UINumber.Compute( this, UIStyleNumberProperty.FloatShaderProperty, n, 0, relative ); - infos.Add( "[" + n + "] (" + p.value._FFF() + " * " + p.unit +") :" + value._FFF() ); - } - - propertyInfos = infos.ToArray(); - - this.LogInfo( propertyInfos ); - - - debugInfo = false; - - } - - - - UIDragging.UIDraggingCallbacks leftMouseCallbacks; - Vector2 cachedMouseOffset; - Vector2 cachedButtonPosition; - - bool _dragging = false; - bool _updatingPosition = false; - - string scrollID = IDGenerator.GenerateID(); - - float ComputeShaderProperty( string n, float relative = 100 ) - { - return UINumber.Compute( this, UIStyleNumberProperty.FloatShaderProperty, n, 0, relative ); - } - - Vector2 sliderSize - { - get - { - 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 ); - - var valueX = ComputeShaderProperty( SliderShader.sliderSize.propertyNameX, w ); - var valueY = ComputeShaderProperty( SliderShader.sliderSize.propertyNameY, h ); - - return new Vector2( valueX, valueY ); - } - } - - Vector2 sliderSizeMargins - { - get - { - 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 ); - - var valueX = ComputeShaderProperty( SliderShader.sliderSizeMargins.propertyNameX, w ); - var valueY = ComputeShaderProperty( SliderShader.sliderSizeMargins.propertyNameY, h ); - - return new Vector2( valueX, valueY ); - } - } - - Vector2 sliderRange => Size - ( sliderSize + sliderSizeMargins ); - Vector2 sliderOffset => sliderSize; - - Vector2 buttonPositionMin - { - get { return NormalizedToButtonPosition( Vector2.Zero ); } - } - - Vector2 buttonPositionMax - { - get { return NormalizedToButtonPosition( Vector2.One ); } - } - - - Vector2 NormalizedToButtonPosition( Vector2 normalized ) - { - return normalized * sliderRange + sliderOffset; - } - - Vector2 ButtonPositionToNormalized( Vector2 buttonPosition ) - { - return ( buttonPosition - sliderOffset ) / sliderRange; - } - - - bool _listenerAssigned = false; - - void AssignListener() - { - if ( _listenerAssigned ) - { - return; - } - - leftMouseCallbacks = UIDragging.OnLeftMouseButton( this, - ( ev )=> - { - if ( ev.isStart ) - { - cachedButtonPosition = NormalizedToButtonPosition( sliderValue ); - smoothing.SetCurrent( cachedButtonPosition ); - - _dragging = true; - _updatingPosition = true; - - ev.ui.onProcess.AddAction( UpdatePosition ); - } - else if ( ev.isEnd ) - { - _dragging = false; - } - - var nextPosition = cachedButtonPosition + ev.distanceToStart; - nextValue = nextPosition.Clamp( buttonPositionMin, buttonPositionMax ); - - } - ); - - _listenerAssigned = true; - } - - Vector2 nextValue; - - Vector2 GetButtonScrollRange() - { - return Vector2.Zero; - // return ( Size - button.Size ).Max( Vector2.Zero ); - } - - Vector2 cachedOffset = Vector2.Zero; - - void UpdatePosition( float delta ) - { - // this.LogInfo( "UpdatePosition" ); - var value = Smoothing.Apply( smoothing, nextValue, delta ); - - var uiStyleContainer = ( UIStylePropertyContainerNode ) this; - - uiStyleContainer.SetLayoutDirtyFlag(); - - if ( ! _dragging && ( value - nextValue ).Length() < 1 ) - { - var ui = UIHolder.GetUI( this ); - ui.onProcess.RemoveAction( UpdatePosition ); - _updatingPosition = false; - // this.LogInfo( "Removed Processing" ); - - value = nextValue; - - uiStyleContainer.RemoveUISelectorFlag( UISelectorFlag.Scrolling, scrollID ); - - } - - var currentSliderValue = ButtonPositionToNormalized( value ); - - if ( Direction.Vertical == direction ) - { - currentSliderValue.X = 0.5f; - } - else if ( Direction.Vertical == direction ) - { - currentSliderValue.Y = 0.5f; - } - - _sliderValue = currentSliderValue; - SyncSliderValue(); - - } - - } -} \ No newline at end of file diff --git a/Runtime/UI/Nodes/UIText.cs b/Runtime/UI/Nodes/UIText.cs index 3ee8c49..2cac4fd 100644 --- a/Runtime/UI/Nodes/UIText.cs +++ b/Runtime/UI/Nodes/UIText.cs @@ -156,6 +156,8 @@ namespace Rokojori [Export] public UIColor selfModulationColor; + + public Font GetFont() { return font; @@ -180,9 +182,52 @@ namespace Rokojori string hoverID = IDGenerator.GenerateID(); UICursor appliedCursor = null; - + public override void _Ready() { + FocusEntered += ()=> + { + AddUISelectorFlag( UISelectorFlag.Focus ); + + var sound = UIStyle.GetUISound( this, UISoundProperty.FocusEntered ); + + if ( sound != null ) + { + GetUI().PlaySound( sound ); + } + + setActiveWhenFocused?.ForEach( + ( c )=> + { + var uiStylable = c as UIStylePropertyContainerNode; + + uiStylable?.AddUISelectorFlag( UISelectorFlag.Active ); + } + ); + + }; + + FocusExited += ()=> + { + RemoveUISelectorFlag( UISelectorFlag.Focus ); + + var sound = UIStyle.GetUISound( this, UISoundProperty.FocusExited ); + + if ( sound != null ) + { + GetUI().PlaySound( sound ); + } + + setActiveWhenFocused?.ForEach( + ( c )=> + { + var uiStylable = c as UIStylePropertyContainerNode; + + uiStylable?.RemoveUISelectorFlag( UISelectorFlag.Active ); + } + ); + }; + MouseEntered += ()=> { AddUISelectorFlag( UISelectorFlag.Hover, hoverID ); @@ -300,16 +345,30 @@ namespace Rokojori } public override void _GuiInput( InputEvent inputEvent ) - { + { + var ui = GetUI(); + + // this.LogInfo( "InputEvent", inputEvent, ui.settings.uiConfirm.IsDown( inputEvent ) ); + + if ( ui.settings.uiConfirm.IsDown( inputEvent ) ) + { + onUIConfirm?.Trigger(); + // GD.Print("ui_accept pressed while focused"); + // AcceptEvent(); // Optional: stop propagation + } + if ( ! handleMouseEvents ) { return; } + if ( inputEvent is InputEventMouseButton mb ) { if ( mb.Pressed ) { + this.LogInfo( "Clicked" ); + if ( mb.ButtonIndex == MouseButton.Left ) { Action.Trigger( onLeftClick ); @@ -388,7 +447,7 @@ namespace Rokojori } } - [ExportGroup("Pointer")] + [ExportGroup( "Interactivity" )] [Export] public UICursor hoverCursor; @@ -399,6 +458,18 @@ namespace Rokojori } + [Export] + public Action onUIConfirm; + + [Export] + public Action onFocusEntered; + + [Export] + public Action onFocusExited; + + [Export] + public Control[] setActiveWhenFocused = []; + [Export] public bool handleMouseEvents = false; @@ -411,6 +482,39 @@ namespace Rokojori [Export] public Action onRightClick; + [ExportGroup( "Sound" )] + [Export] + public UISoundData onFocusSound; + [Export] + public UISoundData onBlurSound; + + public UISoundData GetUISoundProperty( UISoundProperty property ) + { + if ( UISoundProperty.FocusEntered == property ) + { + return onFocusSound; + } + else if ( UISoundProperty.FocusExited == property ) + { + return onFocusSound; + } + + return null; + } + + public void SetUISoundProperty( UISoundProperty property, UISoundData stream ) + { + if ( UISoundProperty.FocusEntered == property ) + { + onFocusSound = stream; + } + else if ( UISoundProperty.FocusExited == property ) + { + onFocusSound = stream; + } + } + + public UIStyle GetUIStyleParent() { return parentStyle; @@ -447,6 +551,7 @@ namespace Rokojori return null; } + public UINumber GetUIStyleNumberProperty( UIStyleNumberProperty property, string shaderPropertyName, UIStylePropertyContainer source ) diff --git a/Runtime/UI/Shaders/RoundedRectangle/RoundedRectangle.gdshader b/Runtime/UI/Shaders/RoundedRectangle/RoundedRectangle.gdshader index 3d5ddf4..b728cbf 100644 --- a/Runtime/UI/Shaders/RoundedRectangle/RoundedRectangle.gdshader +++ b/Runtime/UI/Shaders/RoundedRectangle/RoundedRectangle.gdshader @@ -12,17 +12,17 @@ uniform float strokeSize = 5; uniform float offset; uniform vec4 fillColor:source_color; -uniform sampler2D fill; +uniform sampler2D fill:source_color; uniform vec4 fillUVTransform; -uniform sampler2D screenFillMultiply; +uniform sampler2D screenFillMultiply:source_color; uniform vec4 screenfillMultiplyUVTransform; uniform vec2 screenfillMultiplyUVMovement; uniform vec4 strokeColor:source_color; -uniform sampler2D stroke; +uniform sampler2D stroke:source_color; uniform vec4 strokeUVTransform; -uniform sampler2D screenStrokeMultiply; +uniform sampler2D screenStrokeMultiply:source_color; uniform vec4 screenStrokeMultiplyUVTransform; uniform vec2 screenStrokeMultiplyUVMovment; @@ -60,10 +60,6 @@ float angleFill( vec2 uv, float angleDegrees, float offsetDegrees ) } } -void vertex() -{ - // Called for every vertex the material is visible on. -} void fragment() { @@ -114,16 +110,12 @@ void fragment() float mask = max ( fillMask , strokeMask ); mask = fillMask + strokeMask; - vec4 tex = texture( TEXTURE, UV ); + // vec4 tex = texture( TEXTURE, UV ); float anglefillState = angleFill( UV - vec2( 0.5 ), fillStateAngle, fillStateOffset ); + + float alpha = COLOR.a * outputColor.a * mask * opacity * anglefillState; + // alpha = clamp( alpha, 0.0, 1.0 ) * 5.0; + COLOR = vec4( COLOR.rgb * outputColor.rgb, alpha ); - COLOR *= vec4( outputColor.rgb * tex.rgb, outputColor.a * mask * opacity * tex.a * anglefillState); - - // Called for every pixel the material is visible on. } - -//void light() { - // Called for every pixel for every light affecting the CanvasItem. - // Uncomment to replace the default light processing function with this one. -//} diff --git a/Runtime/UI/Shaders/Slider/Slider.gdshader b/Runtime/UI/Shaders/Slider/Slider.gdshader index 6d5f972..bc155a3 100644 --- a/Runtime/UI/Shaders/Slider/Slider.gdshader +++ b/Runtime/UI/Shaders/Slider/Slider.gdshader @@ -35,9 +35,14 @@ uniform vec2 screenStrokeMultiplyUVMovment; group_uniforms; group_uniforms Slider; -uniform vec2 sliderSize; -uniform vec2 sliderSizeMargins; -uniform float sliderBorders; +// uniform vec2 sliderSize = vec2( 0.0 ); +// uniform vec2 sliderMinSize = vec2( 5.0, 5.0 ); +uniform float sliderSizeX = 0.0; +uniform float sliderSizeY = 0.0; +uniform float sliderSizeMarginX = 0.0; +uniform float sliderSizeMarginY = 0.0; +// uniform vec2 sliderSizeMargins = vec2( 0.0 ); +uniform float sliderBorders = 0.0; uniform vec2 sliderValue; group_uniforms; @@ -63,15 +68,17 @@ vec4 createBorders( float borderSize, vec2 rectSize ) vec4 getSliderLayer( vec2 pixelPosition ) { - vec2 sliderValueRange = size - ( sliderSize + sliderSizeMargins ); - vec2 sliderValueOffset = ( sliderSize + sliderSizeMargins ) / 2.0; + vec2 _sliderSize = vec2( sliderSizeX, sliderSizeY ); + vec2 _sliderMargins = vec2( sliderSizeMarginX, sliderSizeMarginY ); + vec2 sliderValueRange = size - ( _sliderSize + _sliderMargins ); + vec2 sliderValueOffset = ( _sliderSize + _sliderMargins ) / 2.0; vec2 sliderPosition = sliderValueOffset + sliderValueRange * sliderValue; - vec4 borders = createBorders( sliderBorders, sliderSize ); + vec4 borders = createBorders( sliderBorders, _sliderSize ); - float sd = sdRoundedBox( pixelPosition - sliderPosition, sliderSize / 2.0, borders ); + float sd = sdRoundedBox( pixelPosition - sliderPosition, _sliderSize / 2.0, borders ); // vec4 sliderLayer = sdf_coloredShape( sd, sliderStrokeSize, sliderFillColor, sliderStrokeColor ); @@ -126,9 +133,9 @@ void fragment() outputColor.rgb = LINEARtoSRGB( outputColor.rgb ); } - vec4 tex = texture( TEXTURE, UV ); + // vec4 tex = texture( TEXTURE, UV ); - COLOR = vec4( outputColor.rgb * tex.rgb, outputColor.a * opacity * tex.a); + COLOR = vec4( outputColor.rgb * COLOR.rgb, outputColor.a * opacity * COLOR.a); } diff --git a/Runtime/UI/Shaders/Slider/SliderMaterial.cs b/Runtime/UI/Shaders/Slider/SliderMaterial.cs index 5b75755..5d39b8e 100644 --- a/Runtime/UI/Shaders/Slider/SliderMaterial.cs +++ b/Runtime/UI/Shaders/Slider/SliderMaterial.cs @@ -6,9 +6,11 @@ namespace Rokojori public class SliderShader { + ///* public static readonly CachedResource shader = new CachedResource( "res://addons/rokojori_action_library/Runtime/UI/Shaders/Slider/Slider.gdshader" - ); + ); + //*/ public static readonly FloatPropertyName opacity = FloatPropertyName.Create( "opacity" ); public static readonly BoolPropertyName blendLinear = BoolPropertyName.Create( "blendLinear" ); @@ -29,8 +31,10 @@ namespace Rokojori public static readonly Sampler2DPropertyName screenStrokeMultiply = Sampler2DPropertyName.Create( "screenStrokeMultiply" ); public static readonly Vector4PropertyName screenStrokeMultiplyUvTransform = Vector4PropertyName.Create( "screenStrokeMultiplyUVTransform" ); public static readonly Vector2PropertyName screenStrokeMultiplyUvMovment = Vector2PropertyName.Create( "screenStrokeMultiplyUVMovment" ); - public static readonly Vector2PropertyName sliderSize = Vector2PropertyName.Create( "sliderSize" ); - public static readonly Vector2PropertyName sliderSizeMargins = Vector2PropertyName.Create( "sliderSizeMargins" ); + public static readonly FloatPropertyName sliderSizeX = FloatPropertyName.Create( "sliderSizeX" ); + public static readonly FloatPropertyName sliderSizeY = FloatPropertyName.Create( "sliderSizeY" ); + public static readonly FloatPropertyName sliderSizeMarginX = FloatPropertyName.Create( "sliderSizeMarginX" ); + public static readonly FloatPropertyName sliderSizeMarginY = FloatPropertyName.Create( "sliderSizeMarginY" ); public static readonly FloatPropertyName sliderBorders = FloatPropertyName.Create( "sliderBorders" ); public static readonly Vector2PropertyName sliderValue = Vector2PropertyName.Create( "sliderValue" ); public static readonly ColorPropertyName sliderFillColor = ColorPropertyName.Create( "sliderFillColor" ); @@ -63,8 +67,10 @@ namespace Rokojori public readonly CustomMaterialProperty screenStrokeMultiply; public readonly CustomMaterialProperty screenStrokeMultiplyUvTransform; public readonly CustomMaterialProperty screenStrokeMultiplyUvMovment; - public readonly CustomMaterialProperty sliderSize; - public readonly CustomMaterialProperty sliderSizeMargins; + public readonly CustomMaterialProperty sliderSizeX; + public readonly CustomMaterialProperty sliderSizeY; + public readonly CustomMaterialProperty sliderSizeMarginX; + public readonly CustomMaterialProperty sliderSizeMarginY; public readonly CustomMaterialProperty sliderBorders; public readonly CustomMaterialProperty sliderValue; public readonly CustomMaterialProperty sliderFillColor; @@ -73,7 +79,9 @@ namespace Rokojori public SliderMaterial() { + ///* Shader = SliderShader.shader.Get(); + //*/ opacity = new CustomMaterialProperty( this, SliderShader.opacity ); blendLinear = new CustomMaterialProperty( this, SliderShader.blendLinear ); @@ -94,8 +102,10 @@ namespace Rokojori screenStrokeMultiply = new CustomMaterialProperty( this, SliderShader.screenStrokeMultiply ); screenStrokeMultiplyUvTransform = new CustomMaterialProperty( this, SliderShader.screenStrokeMultiplyUvTransform ); screenStrokeMultiplyUvMovment = new CustomMaterialProperty( this, SliderShader.screenStrokeMultiplyUvMovment ); - sliderSize = new CustomMaterialProperty( this, SliderShader.sliderSize ); - sliderSizeMargins = new CustomMaterialProperty( this, SliderShader.sliderSizeMargins ); + sliderSizeX = new CustomMaterialProperty( this, SliderShader.sliderSizeX ); + sliderSizeY = new CustomMaterialProperty( this, SliderShader.sliderSizeY ); + sliderSizeMarginX = new CustomMaterialProperty( this, SliderShader.sliderSizeMarginX ); + sliderSizeMarginY = new CustomMaterialProperty( this, SliderShader.sliderSizeMarginY ); sliderBorders = new CustomMaterialProperty( this, SliderShader.sliderBorders ); sliderValue = new CustomMaterialProperty( this, SliderShader.sliderValue ); sliderFillColor = new CustomMaterialProperty( this, SliderShader.sliderFillColor ); diff --git a/Runtime/UI/Sound/UISoundData.cs b/Runtime/UI/Sound/UISoundData.cs new file mode 100644 index 0000000..9aee3f7 --- /dev/null +++ b/Runtime/UI/Sound/UISoundData.cs @@ -0,0 +1,20 @@ + +using Godot; + +namespace Rokojori; + +[Tool] +[GlobalClass] +public partial class UISoundData: Resource +{ + [Export] + public Godot.AudioStream audio; + + [Export( PropertyHint.Range, "0,1")] + public float volume = 1f; + + [Export( PropertyHint.Range, "-36,36")] + public float pitchSemitonesOffset = 0f; + +} + diff --git a/Runtime/UI/Sound/UISoundData.cs.uid b/Runtime/UI/Sound/UISoundData.cs.uid new file mode 100644 index 0000000..70289ee --- /dev/null +++ b/Runtime/UI/Sound/UISoundData.cs.uid @@ -0,0 +1 @@ +uid://glochk7x1rvw diff --git a/Runtime/UI/Styling/Presets/Numbers/0% (Left or Top).tres b/Runtime/UI/Styling/Presets/Numbers/0% (Left or Top).tres new file mode 100644 index 0000000..a308586 --- /dev/null +++ b/Runtime/UI/Styling/Presets/Numbers/0% (Left or Top).tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="UINumber" load_steps=2 format=3 uid="uid://cnbvpelp78wan"] + +[ext_resource type="Script" uid="uid://cnkyynboxg1qg" path="res://addons/rokojori_action_library/Runtime/UI/Styling/UINumber.cs" id="1_rgh8u"] + +[resource] +script = ExtResource("1_rgh8u") +unit = "%" +metadata/_custom_type_script = "uid://cnkyynboxg1qg" diff --git a/Runtime/UI/Styling/Presets/Numbers/0em (None).tres b/Runtime/UI/Styling/Presets/Numbers/0em (None).tres new file mode 100644 index 0000000..74886a5 --- /dev/null +++ b/Runtime/UI/Styling/Presets/Numbers/0em (None).tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="UINumber" load_steps=2 format=3 uid="uid://uarw3swsgl7"] + +[ext_resource type="Script" uid="uid://cnkyynboxg1qg" path="res://addons/rokojori_action_library/Runtime/UI/Styling/UINumber.cs" id="1_r2bdw"] + +[resource] +script = ExtResource("1_r2bdw") +unit = "em" +metadata/_custom_type_script = "uid://cnkyynboxg1qg" diff --git a/Runtime/UI/Styling/Presets/Numbers/100ph (Parent Height).tres b/Runtime/UI/Styling/Presets/Numbers/100ph (Parent Height).tres new file mode 100644 index 0000000..4b66a10 --- /dev/null +++ b/Runtime/UI/Styling/Presets/Numbers/100ph (Parent Height).tres @@ -0,0 +1,9 @@ +[gd_resource type="Resource" script_class="UINumber" load_steps=2 format=3 uid="uid://did6kmvhnaxbd"] + +[ext_resource type="Script" uid="uid://cnkyynboxg1qg" path="res://addons/rokojori_action_library/Runtime/UI/Styling/UINumber.cs" id="1_6l6dl"] + +[resource] +script = ExtResource("1_6l6dl") +value = 100.0 +unit = "ph" +metadata/_custom_type_script = "uid://cnkyynboxg1qg" diff --git a/Runtime/UI/Styling/Presets/Numbers/100pw (Parent Width).tres b/Runtime/UI/Styling/Presets/Numbers/100pw (Parent Width).tres new file mode 100644 index 0000000..687bddc --- /dev/null +++ b/Runtime/UI/Styling/Presets/Numbers/100pw (Parent Width).tres @@ -0,0 +1,9 @@ +[gd_resource type="Resource" script_class="UINumber" load_steps=2 format=3 uid="uid://dr68b4fprxige"] + +[ext_resource type="Script" uid="uid://cnkyynboxg1qg" path="res://addons/rokojori_action_library/Runtime/UI/Styling/UINumber.cs" id="1_qyj25"] + +[resource] +script = ExtResource("1_qyj25") +value = 100.0 +unit = "pw" +metadata/_custom_type_script = "uid://cnkyynboxg1qg" diff --git a/Runtime/UI/Styling/Presets/Numbers/100vh (Window Height).tres b/Runtime/UI/Styling/Presets/Numbers/100vh (Window Height).tres new file mode 100644 index 0000000..a772416 --- /dev/null +++ b/Runtime/UI/Styling/Presets/Numbers/100vh (Window Height).tres @@ -0,0 +1,9 @@ +[gd_resource type="Resource" script_class="UINumber" load_steps=2 format=3 uid="uid://deq3rcspgbfg7"] + +[ext_resource type="Script" uid="uid://cnkyynboxg1qg" path="res://addons/rokojori_action_library/Runtime/UI/Styling/UINumber.cs" id="1_77r26"] + +[resource] +script = ExtResource("1_77r26") +value = 100.0 +unit = "vh" +metadata/_custom_type_script = "uid://cnkyynboxg1qg" diff --git a/Runtime/UI/Styling/Presets/Numbers/100vw (Window Width).tres b/Runtime/UI/Styling/Presets/Numbers/100vw (Window Width).tres new file mode 100644 index 0000000..c5ec0cc --- /dev/null +++ b/Runtime/UI/Styling/Presets/Numbers/100vw (Window Width).tres @@ -0,0 +1,9 @@ +[gd_resource type="Resource" script_class="UINumber" load_steps=2 format=3 uid="uid://fqdnpeq4oiq4"] + +[ext_resource type="Script" uid="uid://cnkyynboxg1qg" path="res://addons/rokojori_action_library/Runtime/UI/Styling/UINumber.cs" id="1_3a5q4"] + +[resource] +script = ExtResource("1_3a5q4") +value = 100.0 +unit = "vw" +metadata/_custom_type_script = "uid://cnkyynboxg1qg" diff --git a/Runtime/UI/Styling/Presets/Numbers/50% (Centered).tres b/Runtime/UI/Styling/Presets/Numbers/50% (Centered).tres new file mode 100644 index 0000000..8b5b65e --- /dev/null +++ b/Runtime/UI/Styling/Presets/Numbers/50% (Centered).tres @@ -0,0 +1,9 @@ +[gd_resource type="Resource" script_class="UINumber" load_steps=2 format=3 uid="uid://csgadj1kyjd7x"] + +[ext_resource type="Script" uid="uid://cnkyynboxg1qg" path="res://addons/rokojori_action_library/Runtime/UI/Styling/UINumber.cs" id="1_4kw5p"] + +[resource] +script = ExtResource("1_4kw5p") +value = 50.0 +unit = "%" +metadata/_custom_type_script = "uid://cnkyynboxg1qg" diff --git a/Runtime/UI/Styling/UINumber.cs b/Runtime/UI/Styling/UINumber.cs index cf5c434..b748582 100644 --- a/Runtime/UI/Styling/UINumber.cs +++ b/Runtime/UI/Styling/UINumber.cs @@ -391,10 +391,51 @@ namespace Rokojori public string formula; public Godot.Collections.Array inputs; public float result; + public HashSet variables = null; - public bool Matches( UINumber number, Godot.Collections.Array inputs ) + public bool ContainsVariable( string varName ) { - if ( number.unit != formula ) + if ( variables == null ) + { + ParseVariables(); + } + + return variables.Contains( varName ); + } + + public void ParseVariables() + { + variables = new HashSet(); + + var lexer = new UIExpressionLexer(); + var events = lexer.LexToList( formula ); + + var list = new List(); + + events.ForEach( + ( tk )=> + { + if ( ! tk.Is( LexerMatcherLibrary.CwordMatcher ) ) + { + return; + } + + tk.GrabMatch( formula ); + variables.Add( tk.match ); + + list.Add( tk.match ); + } + ); + + // if ( variables.Count > 0 ) + // { + // RJLog.Log( "Formula", formula, "Variables:", variables.ToList().Join() ); + // } + } + + public bool Matches( string cachedFormula, Godot.Collections.Array inputs ) + { + if ( cachedFormula != formula ) { return false; } @@ -414,9 +455,9 @@ namespace Rokojori static List cachedExpressions = new List(); static int maxCachedExpressions = 50; - static int GetCacheIndex( UINumber number, Godot.Collections.Array inputs ) + static int GetCacheIndex( string formula, Godot.Collections.Array inputs ) { - return cachedExpressions.FindIndex( c => c.Matches( number, inputs ) ); + return cachedExpressions.FindIndex( c => c.Matches( formula, inputs ) ); } static float ComputeBaseValue( Control control, UINumber number, float width, float height, float relative, string numberUnit = null ) @@ -538,11 +579,11 @@ namespace Rokojori return number.value * ComputeBaseValue( control, number, width, height, relative ); } - var parentControl = control.GetParent() as Control;; + var parentControl = control.GetParent() as Control; var inputs = GetInputs( control, number, parentControl, width, height, relative ); - var cacheIndex = GetCacheIndex( number, inputs ); + var cacheIndex = GetCacheIndex( number.unit, inputs ); if ( cacheIndex != -1 ) { @@ -555,7 +596,13 @@ namespace Rokojori var expression = new Expression(); - var expressionText = number.unit == null ? "" : RegexUtility.Replace( number.unit, "%", " * relative " ); + var ui = UI.Get( control ); + + var hasVariables = false; + var expressionText = ui.InsertVariables( number.unit ?? "", ref hasVariables ); + + expressionText = RegexUtility.Replace( expressionText, "%", " * relative " ); + expressionText = RegexUtility.Replace( expressionText, @"\b(\d+)\s*(em|v[wh]|p[wh]|c[wh]|c[xy]|ui[wh])\b", "$1*$2" ); @@ -577,12 +624,31 @@ namespace Rokojori var result = (float) ( scale * expression.Execute( inputs ).AsDouble() ); + // if ( ! hasVariables ) + // { Cache( number.unit, inputs, result ); + // } return result; } + public static void ClearCacheFor( UINumberVariable variable ) + { + var removals = new List(); + + foreach ( var exp in cachedExpressions ) + { + if ( exp.ContainsVariable( variable.variableName ) ) + { + // RJLog.Log( "Clearing cached expression:", "'" + exp.formula + "'"); + removals.Add( exp ); + } + } + + cachedExpressions.RemoveList( removals ); + } + static void Cache( string formula, Godot.Collections.Array inputs, float result ) { CachedExpressionData data = null; @@ -599,8 +665,7 @@ namespace Rokojori data.formula = formula; data.inputs = inputs; - data.result = result; - + data.result = result; } diff --git a/Runtime/UI/Styling/UINumberVariable.cs b/Runtime/UI/Styling/UINumberVariable.cs new file mode 100644 index 0000000..f3d23eb --- /dev/null +++ b/Runtime/UI/Styling/UINumberVariable.cs @@ -0,0 +1,59 @@ + +using Godot; +using Rokojori; +using System.Globalization; + +namespace Rokojori; + +[Tool] +[GlobalClass] +public partial class UINumberVariable:Resource +{ + [Export] + public string variableName = ""; + + [Export] + public string variableValue = ""; + + [Export] + public float variableScale = 1; + + + public string GetFormula() + { + return "( " + variableScale.ToString( CultureInfo.InvariantCulture ) + " * " + variableValue + " )"; + } + + public bool IsEqualTo( UINumberVariable other ) + { + if ( other == null ) + { + return false; + } + + if ( other.variableName != variableName ) + { + return false; + } + + if ( other.variableScale != variableScale ) + { + return false; + } + + if ( other.variableValue != variableValue ) + { + return false; + } + + return true; + } + + + [Export,ReadOnly] + public string compileResult = ""; + + +} + + diff --git a/Runtime/UI/Styling/UINumberVariable.cs.uid b/Runtime/UI/Styling/UINumberVariable.cs.uid new file mode 100644 index 0000000..15f7119 --- /dev/null +++ b/Runtime/UI/Styling/UINumberVariable.cs.uid @@ -0,0 +1 @@ +uid://b53p1cuq8hkcw diff --git a/Runtime/UI/Styling/UIStyle.cs b/Runtime/UI/Styling/UIStyle.cs index 46ca791..bf8e515 100644 --- a/Runtime/UI/Styling/UIStyle.cs +++ b/Runtime/UI/Styling/UIStyle.cs @@ -3,6 +3,7 @@ using Godot; using Rokojori; using System.Collections.Generic; using System.Linq; +using System.Runtime.ConstrainedExecution; namespace Rokojori { @@ -113,7 +114,38 @@ namespace Rokojori [Export] public ShaderUINumber[] numberProperties = new ShaderUINumber[ 0 ]; - + + [ExportGroup( "Sound" )] + [Export] + public UISoundData onFocusSound; + [Export] + public UISoundData onBlurSound; + + public UISoundData GetUISoundProperty( UISoundProperty property ) + { + if ( UISoundProperty.FocusEntered == property ) + { + return onFocusSound; + } + else if ( UISoundProperty.FocusExited == property ) + { + return onFocusSound; + } + + return null; + } + + public void SetUISoundProperty( UISoundProperty property, UISoundData stream ) + { + if ( UISoundProperty.FocusEntered == property ) + { + onFocusSound = stream; + } + else if ( UISoundProperty.FocusExited == property ) + { + onFocusSound = stream; + } + } public Font GetFont() { @@ -975,6 +1007,7 @@ namespace Rokojori } + public static UIPosition Position( UIStylePropertyContainer container ) { if ( container == null ) @@ -1155,6 +1188,26 @@ namespace Rokojori return GetReferenceableColorProperty( container, property, shaderPropertyName, source ); } + + public static UISoundData GetUISound( UIStylePropertyContainer container, UISoundProperty property ) + { + var ownSound = container.GetUISoundProperty( property ); + + if ( ownSound != null ) + { + return ownSound; + } + + var parent = container.GetUIStyleParent(); + + if ( parent == null ) + { + return null; + } + + return GetUISound( parent, property ); + + } } } \ No newline at end of file diff --git a/Runtime/UI/Styling/UIStyleProperty.cs b/Runtime/UI/Styling/UIStyleProperty.cs index 5fd5780..e449de0 100644 --- a/Runtime/UI/Styling/UIStyleProperty.cs +++ b/Runtime/UI/Styling/UIStyleProperty.cs @@ -44,6 +44,12 @@ namespace Rokojori FloatShaderProperty } + public enum UISoundProperty + { + FocusEntered, + FocusExited + } + public class UIStyleNumberPropertyAndName { public UIStyleNumberProperty styleProperty; diff --git a/Runtime/UI/Styling/UIStylePropertyContainer.cs b/Runtime/UI/Styling/UIStylePropertyContainer.cs index 88ed2d9..53541b0 100644 --- a/Runtime/UI/Styling/UIStylePropertyContainer.cs +++ b/Runtime/UI/Styling/UIStylePropertyContainer.cs @@ -20,6 +20,9 @@ namespace Rokojori Font GetFont(); + UISoundData GetUISoundProperty( UISoundProperty property ); + void SetUISoundProperty( UISoundProperty property, UISoundData stream ); + UINumber GetUIStyleNumberProperty( UIStyleNumberProperty property, string shaderPropertyName, UIStylePropertyContainer source ); void SetUIStyleNumberProperty( UIStyleNumberProperty property, UINumber number ); diff --git a/Runtime/UI/UI-Selectors/Presets/Active 100% Selector Style.tres b/Runtime/UI/UI-Selectors/Presets/Active 100% Selector Style.tres new file mode 100644 index 0000000..7152b35 --- /dev/null +++ b/Runtime/UI/UI-Selectors/Presets/Active 100% Selector Style.tres @@ -0,0 +1,11 @@ +[gd_resource type="Resource" script_class="UISelectorStyle" load_steps=4 format=3 uid="uid://cxq4cfdnk7c25"] + +[ext_resource type="Script" uid="uid://bqypmtxqo5rnf" path="res://addons/rokojori_action_library/Runtime/UI/Styling/UISelectorStyle.cs" id="1_ytj2f"] +[ext_resource type="Resource" uid="uid://do3q5tipotyn3" path="res://addons/rokojori_action_library/Runtime/UI/UI-Selectors/Presets/Active Selector.tres" id="2_r7shh"] +[ext_resource type="Resource" uid="uid://brjq22uvnpxuv" path="res://addons/rokojori_action_library/Runtime/UI/UI-Selectors/Presets/Mod 100% Style.tres" id="3_x1wpc"] + +[resource] +script = ExtResource("1_ytj2f") +selector = ExtResource("2_r7shh") +style = ExtResource("3_x1wpc") +metadata/_custom_type_script = "uid://bqypmtxqo5rnf" diff --git a/Runtime/UI/UI-Selectors/Presets/Active Selector.tres b/Runtime/UI/UI-Selectors/Presets/Active Selector.tres new file mode 100644 index 0000000..43b0bb5 --- /dev/null +++ b/Runtime/UI/UI-Selectors/Presets/Active Selector.tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="UISelector" load_steps=2 format=3 uid="uid://do3q5tipotyn3"] + +[ext_resource type="Script" uid="uid://brmxttyvbwoit" path="res://addons/rokojori_action_library/Runtime/UI/Styling/UISelector.cs" id="1_u7tnw"] + +[resource] +script = ExtResource("1_u7tnw") +active = 1 +metadata/_custom_type_script = "uid://brmxttyvbwoit" diff --git a/Runtime/UI/UI-Selectors/Presets/Focus 100% Selector Style.tres b/Runtime/UI/UI-Selectors/Presets/Focus 100% Selector Style.tres new file mode 100644 index 0000000..5b42c62 --- /dev/null +++ b/Runtime/UI/UI-Selectors/Presets/Focus 100% Selector Style.tres @@ -0,0 +1,11 @@ +[gd_resource type="Resource" script_class="UISelectorStyle" load_steps=4 format=3 uid="uid://cvc0wabrro18q"] + +[ext_resource type="Script" uid="uid://bqypmtxqo5rnf" path="res://addons/rokojori_action_library/Runtime/UI/Styling/UISelectorStyle.cs" id="1_2joc3"] +[ext_resource type="Resource" uid="uid://dgx4ue1pvvltj" path="res://addons/rokojori_action_library/Runtime/UI/UI-Selectors/Presets/Focus Selector.tres" id="2_351ev"] +[ext_resource type="Resource" uid="uid://brjq22uvnpxuv" path="res://addons/rokojori_action_library/Runtime/UI/UI-Selectors/Presets/Mod 100% Style.tres" id="3_46vc8"] + +[resource] +script = ExtResource("1_2joc3") +selector = ExtResource("2_351ev") +style = ExtResource("3_46vc8") +metadata/_custom_type_script = "uid://bqypmtxqo5rnf" diff --git a/Runtime/UI/UI-Selectors/Presets/Focus Selector.tres b/Runtime/UI/UI-Selectors/Presets/Focus Selector.tres new file mode 100644 index 0000000..25910fd --- /dev/null +++ b/Runtime/UI/UI-Selectors/Presets/Focus Selector.tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="UISelector" load_steps=2 format=3 uid="uid://dgx4ue1pvvltj"] + +[ext_resource type="Script" uid="uid://brmxttyvbwoit" path="res://addons/rokojori_action_library/Runtime/UI/Styling/UISelector.cs" id="1_7xeoa"] + +[resource] +script = ExtResource("1_7xeoa") +focus = 1 +metadata/_custom_type_script = "uid://brmxttyvbwoit" diff --git a/Runtime/UI/UI-Selectors/Presets/Hover 80% Selector Style.tres b/Runtime/UI/UI-Selectors/Presets/Hover 80% Selector Style.tres new file mode 100644 index 0000000..ba36786 --- /dev/null +++ b/Runtime/UI/UI-Selectors/Presets/Hover 80% Selector Style.tres @@ -0,0 +1,11 @@ +[gd_resource type="Resource" script_class="UISelectorStyle" load_steps=4 format=3 uid="uid://d15wkkwgtlh0n"] + +[ext_resource type="Script" uid="uid://bqypmtxqo5rnf" path="res://addons/rokojori_action_library/Runtime/UI/Styling/UISelectorStyle.cs" id="1_a0wuj"] +[ext_resource type="Resource" uid="uid://cfctpa7mv11nj" path="res://addons/rokojori_action_library/Runtime/UI/UI-Selectors/Presets/Hover Selector.tres" id="2_dm1hb"] +[ext_resource type="Resource" uid="uid://cy7m6e0be3mqw" path="res://addons/rokojori_action_library/Runtime/UI/UI-Selectors/Presets/Mod 80% Style.tres" id="3_e4mab"] + +[resource] +script = ExtResource("1_a0wuj") +selector = ExtResource("2_dm1hb") +style = ExtResource("3_e4mab") +metadata/_custom_type_script = "uid://bqypmtxqo5rnf" diff --git a/Runtime/UI/UI-Selectors/Presets/Hover Selector.tres b/Runtime/UI/UI-Selectors/Presets/Hover Selector.tres new file mode 100644 index 0000000..7869acf --- /dev/null +++ b/Runtime/UI/UI-Selectors/Presets/Hover Selector.tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="UISelector" load_steps=2 format=3 uid="uid://cfctpa7mv11nj"] + +[ext_resource type="Script" uid="uid://brmxttyvbwoit" path="res://addons/rokojori_action_library/Runtime/UI/Styling/UISelector.cs" id="1_fyxpi"] + +[resource] +script = ExtResource("1_fyxpi") +hover = 1 +metadata/_custom_type_script = "uid://brmxttyvbwoit" diff --git a/Runtime/UI/UI-Selectors/Presets/Mod 100% Style.tres b/Runtime/UI/UI-Selectors/Presets/Mod 100% Style.tres new file mode 100644 index 0000000..012b433 --- /dev/null +++ b/Runtime/UI/UI-Selectors/Presets/Mod 100% Style.tres @@ -0,0 +1,13 @@ +[gd_resource type="Resource" script_class="UIStyle" load_steps=4 format=3 uid="uid://brjq22uvnpxuv"] + +[ext_resource type="Script" uid="uid://drqb0pm5ub64g" path="res://addons/rokojori_action_library/Runtime/UI/Styling/UIColor.cs" id="1_bdlk7"] +[ext_resource type="Script" uid="uid://chmcc71dvu4vj" path="res://addons/rokojori_action_library/Runtime/UI/Styling/UIStyle.cs" id="2_p68sf"] + +[sub_resource type="Resource" id="Resource_7s7su"] +script = ExtResource("1_bdlk7") +metadata/_custom_type_script = "uid://drqb0pm5ub64g" + +[resource] +script = ExtResource("2_p68sf") +modulationColor = SubResource("Resource_7s7su") +metadata/_custom_type_script = "uid://chmcc71dvu4vj" diff --git a/Runtime/UI/UI-Selectors/Presets/Mod 80% Style.tres b/Runtime/UI/UI-Selectors/Presets/Mod 80% Style.tres new file mode 100644 index 0000000..0b03ac5 --- /dev/null +++ b/Runtime/UI/UI-Selectors/Presets/Mod 80% Style.tres @@ -0,0 +1,14 @@ +[gd_resource type="Resource" script_class="UIStyle" load_steps=4 format=3 uid="uid://cy7m6e0be3mqw"] + +[ext_resource type="Script" uid="uid://drqb0pm5ub64g" path="res://addons/rokojori_action_library/Runtime/UI/Styling/UIColor.cs" id="1_5k4i7"] +[ext_resource type="Script" uid="uid://chmcc71dvu4vj" path="res://addons/rokojori_action_library/Runtime/UI/Styling/UIStyle.cs" id="2_qkfun"] + +[sub_resource type="Resource" id="Resource_wxaam"] +script = ExtResource("1_5k4i7") +color = Color(1, 1, 1, 0.80784315) +metadata/_custom_type_script = "uid://drqb0pm5ub64g" + +[resource] +script = ExtResource("2_qkfun") +modulationColor = SubResource("Resource_wxaam") +metadata/_custom_type_script = "uid://chmcc71dvu4vj" diff --git a/Runtime/UI/UI.cs b/Runtime/UI/UI.cs index 1a7c4ab..ab3dad0 100644 --- a/Runtime/UI/UI.cs +++ b/Runtime/UI/UI.cs @@ -1,7 +1,9 @@ using Godot; +using Godot.Collections; using System; using System.Collections.Generic; +using System.Text; namespace Rokojori { @@ -25,6 +27,102 @@ namespace Rokojori [Export] public float fontZoom = 1; + [Export] + public UINumberVariable[] variables = []; + + [Export] + public int numUpdates = 0; + + [Export] + public Control focusedControl; + + [ExportToolButton("Update Variables")] + public Callable updateVariablesButton => Callable.From( + ()=> + { + CreateVariableValues(); + } + ); + + [ExportToolButton("Clear UI Number Cache")] + public Callable clearUINumberCacheButton => Callable.From( + ()=> + { + CreateVariableValues(); + } + ); + System.Collections.Generic.Dictionary _variableValues = null; + + void CreateVariableValues() + { + _variableValues = new System.Collections.Generic.Dictionary(); + _cachedVariables = new List(); + + variables.ForEach( + ( v )=> + { + _variableValues[ v.variableName ] = v.GetFormula(); + _cachedVariables.Add( (UINumberVariable)v.Duplicate() ); + } + ); + + variables.ForEach( + ( v )=> + { + UINumber.ClearCacheFor( v ); + } + ); + + + } + + public string InsertVariables( string value, ref bool hasVariables ) + { + if ( variables == null || variables.Length == 0 ) + { + hasVariables = false; + return value; + } + + if ( _variableValues == null ) + { + CreateVariableValues(); + } + + var tokens = UIExpressionLexer.Lex( value ); + + var output = new StringBuilder(); + + var tokensContainVariable = false; + + tokens.ForEach( + ( tk )=> + { + if ( tk.isErrorOrDone ) + { + return; + } + + if ( tk.Is( LexerMatcherLibrary.CwordMatcher ) && _variableValues.ContainsKey( tk.match ) ) + { + output.Append( _variableValues[ tk.match ] ); + tokensContainVariable = true; + return; + } + + output.Append( tk.match ); + + } + ); + + hasVariables = tokensContainVariable; + + return output.ToString(); + + + + } + public enum UpdateMode { Always, @@ -180,7 +278,12 @@ namespace Rokojori public bool sizeChanged => _resizeFlag; public bool fontSizeChanged => _fontSizeFlag; - + + // [Export] + // public UISlider focusedSlider = null; + + // [Export] + // public UIListSelection focusedListSelection = null; public override void _Process( double delta ) { @@ -222,12 +325,24 @@ namespace Rokojori } + focusedControl = GetViewport().GuiGetFocusOwner() as Control; + + if ( focusedControl != null && focusedControl is UIHolderControl uih && focusedControl is UIFocusProcessor fp ) + { + if ( uih.GetUI() == this ) + { + fp.OnFocusProcess( delta ); + } + } + onProcess.DispatchEvent( (float)delta ); UpdateFontSize(); + UpdateVariables(); UpdateUIElements(); uiSize = Size; + // customDisposerIDs = _customDisposers.Map( c => c.GetUID() + ":" + c.GetInfo() ).ToArray(); } @@ -238,6 +353,51 @@ namespace Rokojori UpdateFontSize(); } + List _cachedVariables = []; + + public void UpdateVariables() + { + if ( _cachedVariables.Count != variables.Length ) + { + CreateVariableValues(); + return; + } + + var recreate = false; + + for ( int i = 0; ! recreate && i < _cachedVariables.Count; i++ ) + { + var v = variables[ i ]; + + if ( _cachedVariables[ i ] == null && v == null ) + { + continue; + } + + if ( _cachedVariables[ i ] == null || v == null ) + { + recreate = true; + continue; + } + + if ( _cachedVariables[ i ].IsEqualTo( v ) ) + { + continue; + } + + _cachedVariables[ i ] = (UINumberVariable) v.Duplicate(); + UINumber.ClearCacheFor( v ); + _variableValues[ v.variableName ] = v.GetFormula(); + } + + if ( recreate ) + { + CreateVariableValues(); + } + + + } + public readonly EventSlot onInputEvent = new EventSlot(); public readonly EventSlot onProcess = new EventSlot(); @@ -323,8 +483,7 @@ namespace Rokojori if ( _fontSizeFlag || _resizeFlag ) { _dirty.Clear(); - UpdateAllUIRegions(); - + UpdateAllUIRegions(); } else { @@ -362,6 +521,7 @@ namespace Rokojori ); + var updated = 0; sorted.ForEach( ( s )=> @@ -374,9 +534,12 @@ namespace Rokojori // ( s as Control).LogInfo( "Updating:", s ); UpdateElement( s ); + updated ++; } ); + numUpdates = updated; + _updated.Clear(); _dirty.RemoveWhere( d => ! d.IsDirty() ); @@ -451,7 +614,60 @@ namespace Rokojori return GetWindow().Size; } } + + System.Collections.Generic.Dictionary _audioPlayers = new System.Collections.Generic.Dictionary(); + + public AudioStreamPlayer _GetAudioPlayer( UISoundData data ) + { + AudioStreamPlayer freePlayer = null; + + foreach ( var p in _audioPlayers ) + { + var player = p.Key; + + if ( player.Playing ) + { + continue; + } + + if ( player.Stream != data.audio ) + { + freePlayer = player; + continue; + } + + return player; + + } + + if ( freePlayer != null ) + { + return freePlayer; + } + + var newPlayer = this.CreateChild(); + + _audioPlayers[ newPlayer ] = 0; + return newPlayer; + } + + public void PlaySound( UISoundData soundData ) + { + var player = _GetAudioPlayer( soundData ); + + player.Stream = soundData.audio; + player.VolumeLinear = soundData.volume; + player.PitchScale = MathAudio.SemitonesToFrequencyScaler( soundData.pitchSemitonesOffset ); + player.Playing = true; + + } + // public void Focus( Control control ) + // { + // var focusParent = + // while ( control ) + // } + } } \ No newline at end of file diff --git a/Runtime/UI/UIAppSettings/Background/MinimalisticBackgroundGenerator.cs b/Runtime/UI/UIAppSettings/Background/MinimalisticBackgroundGenerator.cs new file mode 100644 index 0000000..41d186d --- /dev/null +++ b/Runtime/UI/UIAppSettings/Background/MinimalisticBackgroundGenerator.cs @@ -0,0 +1,28 @@ + +using Godot; +using Rokojori; +using System.Collections.Generic; +using System.Linq; + +namespace Rokojori; + +[Tool] +[GlobalClass] +public partial class MinimalisticBackgroundGenerator:UIAppSettingsBackgroundGenerator +{ + [Export] + public UIStyle backgroundStyle; + + [Export] + public UIImageType imageType; + + public override UIStylePropertyContainerNode GenerateBackground( UIAppSettings uiAppSettings ) + { + var background = uiAppSettings.CreateChild( "Background" ); + background.imageType = imageType; + background.parentStyle = backgroundStyle; + background.Texture = UI.whiteTexture.Get(); + + return background; + } +} diff --git a/Runtime/UI/UIAppSettings/Background/MinimalisticBackgroundGenerator.cs.uid b/Runtime/UI/UIAppSettings/Background/MinimalisticBackgroundGenerator.cs.uid new file mode 100644 index 0000000..ab4ef4a --- /dev/null +++ b/Runtime/UI/UIAppSettings/Background/MinimalisticBackgroundGenerator.cs.uid @@ -0,0 +1 @@ +uid://blysxpmf7v02p diff --git a/Runtime/UI/UIAppSettings/Background/UIAppSettingsBackgroundGenerator.cs b/Runtime/UI/UIAppSettings/Background/UIAppSettingsBackgroundGenerator.cs new file mode 100644 index 0000000..f92a6ef --- /dev/null +++ b/Runtime/UI/UIAppSettings/Background/UIAppSettingsBackgroundGenerator.cs @@ -0,0 +1,14 @@ + +using Godot; +using Rokojori; +using System.Collections.Generic; +using System.Linq; + +namespace Rokojori; + +[Tool] +[GlobalClass] +public abstract partial class UIAppSettingsBackgroundGenerator:Resource +{ + public abstract UIStylePropertyContainerNode GenerateBackground( UIAppSettings uiAppSettings ); +} diff --git a/Runtime/UI/UIAppSettings/Background/UIAppSettingsBackgroundGenerator.cs.uid b/Runtime/UI/UIAppSettings/Background/UIAppSettingsBackgroundGenerator.cs.uid new file mode 100644 index 0000000..1ebd977 --- /dev/null +++ b/Runtime/UI/UIAppSettings/Background/UIAppSettingsBackgroundGenerator.cs.uid @@ -0,0 +1 @@ +uid://b13ld5mt028g1 diff --git a/Runtime/UI/UIAppSettings/CategoryPages/MinimalisticCategoryPagesGenerator.cs b/Runtime/UI/UIAppSettings/CategoryPages/MinimalisticCategoryPagesGenerator.cs new file mode 100644 index 0000000..9f4a7f6 --- /dev/null +++ b/Runtime/UI/UIAppSettings/CategoryPages/MinimalisticCategoryPagesGenerator.cs @@ -0,0 +1,130 @@ + +using Godot; +using Rokojori; +using System.Collections.Generic; +using System.Linq; + +namespace Rokojori; + +[Tool] +[GlobalClass] +public partial class MinimalisticCategoryPagesGenerator:UIAppSettingsCategoryPageGenerator +{ + [Export] + public UIStyle pageStyle; + + [Export] + public UIStyle pageBackgroundStyle; + + [Export] + public UIImageType pageBackgroundImageType; + + [Export] + public UIStyle sliderStyle; + + [Export] + public SliderUIImageType sliderImageType; + + [Export] + public UIStyle scrollAreaStyle; + + [Export] + public UIStyle appSettingHandlerStyle; + + [Export] + public UIStyle appSettingBackgroundStyle; + + [Export] + public UIImageType appSettingBackgroundImage; + + [Export] + public UIStyle appSettingLabelRegionStyle; + + [Export] + public UIStyle appSettingLabelStyle; + + [Export] + public PackedScene appSettingNumberController; + + [Export] + public PackedScene appSettingListController; + + + public override UIAppSettingsCategoryPage GenerateCategoryPage( + UIAppSettings uiAppSettings, AppSettingsCategory category + ) + { + var page = uiAppSettings.CreateChild( "[ " + category.title.currentValue + " ]"); + page.category = category; + page.parentStyle = pageStyle; + + var pageBG = page.CreateChild( "Background" ); + pageBG.parentStyle = pageBackgroundStyle; + pageBG.imageType = pageBackgroundImageType; + pageBG.Texture = UI.whiteTexture.Get(); + + var scrollArea = page.CreateChild( "Scroll Area" ); + scrollArea.parentStyle = scrollAreaStyle; + + category.settings.ForEach( + ( setting )=> + { + + var name = "- " + setting.title.currentValue; + + UIAppSettingHandler handler = null; + + if ( setting is NumberAppSetting ) + { + handler = scrollArea.CreateChild( name ); + } + else if ( setting is ListAppSetting ) + { + handler = scrollArea.CreateChild( name ); + } + + handler.parentStyle = appSettingHandlerStyle; + handler.appSetting = setting; + + var handlerBG = handler.CreateChild( name + " BG"); + handlerBG.parentStyle = appSettingBackgroundStyle; + handlerBG.imageType = appSettingBackgroundImage; + handlerBG.Texture = UI.whiteTexture.Get(); + + var labelRegion = handler.CreateChild( name + " Label Container"); + labelRegion.parentStyle = appSettingLabelRegionStyle; + + var label = labelRegion.CreateChild( name + " Label" ); + label.locale = setting.title; + label.parentStyle = appSettingLabelStyle; + + if ( setting is NumberAppSetting ) + { + var numberHandler = (UINumberAppSettingHandler) handler; + var numberController = handler.CreateChild( appSettingNumberController, "Number Handler" ); + numberHandler.slider = numberController.Get(); + numberHandler.slider.setActiveWhenFocused = [ handler ]; + + } + + if ( setting is ListAppSetting ) + { + var listHandler = (UIListAppSettingHandler) handler; + var listController = handler.CreateChild( appSettingNumberController, "List Handler" ); + listHandler.list = listController.Get(); + listHandler.list.setActiveWhenFocused = [ handler ]; + } + } + ); + + var slider = page.CreateChild( "Scroll Area Slider" ); + slider.scrollArea = scrollArea; + slider.scrollContainer = page; + slider.parentStyle = sliderStyle; + slider.imageType = sliderImageType; + + + return page; + } + +} diff --git a/Runtime/UI/UIAppSettings/CategoryPages/MinimalisticCategoryPagesGenerator.cs.uid b/Runtime/UI/UIAppSettings/CategoryPages/MinimalisticCategoryPagesGenerator.cs.uid new file mode 100644 index 0000000..7765d4d --- /dev/null +++ b/Runtime/UI/UIAppSettings/CategoryPages/MinimalisticCategoryPagesGenerator.cs.uid @@ -0,0 +1 @@ +uid://djagabirt3f6 diff --git a/Runtime/UI/UIAppSettings/CategoryPages/UIAppSettingsCategoryPage.cs b/Runtime/UI/UIAppSettings/CategoryPages/UIAppSettingsCategoryPage.cs new file mode 100644 index 0000000..fae9fb4 --- /dev/null +++ b/Runtime/UI/UIAppSettings/CategoryPages/UIAppSettingsCategoryPage.cs @@ -0,0 +1,51 @@ + +using Godot; +using Rokojori; +using System.Collections.Generic; +using System.Linq; + +namespace Rokojori; + +[Tool] +[GlobalClass] +public partial class UIAppSettingsCategoryPage:UIRegion +{ + [Export] + public AppSettingsCategory category; + + [Export] + public Action onInitialize; + + [Export] + public Action onActive; + + public virtual void _OnInitialize() + { + LoadSettingsOfHandlers(); + } + + public virtual void _OnActivated() + { + LoadSettingsOfHandlers(); + FocusHandler(); + } + + + + public void LoadSettingsOfHandlers() + { + var handlers = this.GetAll(); + handlers.ForEach( h => h.LoadSetting() ); + + + } + + public void FocusHandler() + { + var handlers = this.GetAll(); + var firstHandler = handlers[ 0 ]; + + firstHandler.FocusHandler(); + } + +} diff --git a/Runtime/UI/UIAppSettings/CategoryPages/UIAppSettingsCategoryPage.cs.uid b/Runtime/UI/UIAppSettings/CategoryPages/UIAppSettingsCategoryPage.cs.uid new file mode 100644 index 0000000..94aa9cf --- /dev/null +++ b/Runtime/UI/UIAppSettings/CategoryPages/UIAppSettingsCategoryPage.cs.uid @@ -0,0 +1 @@ +uid://c6gtpvaih4u5d diff --git a/Runtime/UI/UIAppSettings/CategoryPages/UIAppSettingsCategoryPageGenerator.cs b/Runtime/UI/UIAppSettings/CategoryPages/UIAppSettingsCategoryPageGenerator.cs new file mode 100644 index 0000000..f2c621f --- /dev/null +++ b/Runtime/UI/UIAppSettings/CategoryPages/UIAppSettingsCategoryPageGenerator.cs @@ -0,0 +1,14 @@ + +using Godot; +using Rokojori; +using System.Collections.Generic; +using System.Linq; + +namespace Rokojori; + +[Tool] +[GlobalClass] +public abstract partial class UIAppSettingsCategoryPageGenerator:Resource +{ + public abstract UIAppSettingsCategoryPage GenerateCategoryPage( UIAppSettings uiAppSettings, AppSettingsCategory category ); +} diff --git a/Runtime/UI/UIAppSettings/CategoryPages/UIAppSettingsCategoryPageGenerator.cs.uid b/Runtime/UI/UIAppSettings/CategoryPages/UIAppSettingsCategoryPageGenerator.cs.uid new file mode 100644 index 0000000..57d4a6c --- /dev/null +++ b/Runtime/UI/UIAppSettings/CategoryPages/UIAppSettingsCategoryPageGenerator.cs.uid @@ -0,0 +1 @@ +uid://b3qwyhgss87kp diff --git a/Runtime/UI/UIAppSettings/Handlers/Presets/List Controller.tscn b/Runtime/UI/UIAppSettings/Handlers/Presets/List Controller.tscn new file mode 100644 index 0000000..caca557 --- /dev/null +++ b/Runtime/UI/UIAppSettings/Handlers/Presets/List Controller.tscn @@ -0,0 +1,158 @@ +[gd_scene load_steps=19 format=3 uid="uid://blvco0pityhm1"] + +[ext_resource type="Script" uid="uid://c2hicupu28nbi" path="res://addons/rokojori_action_library/Runtime/UI/Nodes/UIRegion.cs" id="1_1w55f"] +[ext_resource type="Script" uid="uid://cnkyynboxg1qg" path="res://addons/rokojori_action_library/Runtime/UI/Styling/UINumber.cs" id="2_xupgh"] +[ext_resource type="Script" uid="uid://rqs2m0u6yvvf" path="res://addons/rokojori_action_library/Runtime/UI/Nodes/UIText.cs" id="3_emuhf"] +[ext_resource type="Script" uid="uid://bvj322mokkq63" path="res://addons/rokojori_action_library/Runtime/Localization/LocaleText.cs" id="4_nso1f"] +[ext_resource type="Script" uid="uid://chmcc71dvu4vj" path="res://addons/rokojori_action_library/Runtime/UI/Styling/UIStyle.cs" id="5_v6jyw"] +[ext_resource type="Script" uid="uid://b50yldymrhply" path="res://addons/rokojori_action_library/Runtime/UI/Nodes/Selections/ListSelection/ChangeUIListSelection.cs" id="6_28vtr"] +[ext_resource type="Script" uid="uid://2ftd0bt6rrgo" path="res://addons/rokojori_action_library/Runtime/UI/Nodes/Selections/ListSelection/UIListSelection.cs" id="7_4f0b5"] +[ext_resource type="Script" uid="uid://b4yjsis2fh64c" path="res://addons/rokojori_action_library/Runtime/Actions/ActionList.cs" id="8_001d7"] + +[sub_resource type="Resource" id="Resource_7e4fb"] +script = ExtResource("2_xupgh") +value = 2.0 +unit = "em" +metadata/_custom_type_script = "uid://cnkyynboxg1qg" + +[sub_resource type="LabelSettings" id="LabelSettings_qiba2"] + +[sub_resource type="Resource" id="Resource_o8r6f"] +script = ExtResource("4_nso1f") +en = "◀" +metadata/_custom_type_script = "uid://bvj322mokkq63" + +[sub_resource type="Resource" id="Resource_4wsps"] +script = ExtResource("5_v6jyw") +metadata/_custom_type_script = "uid://chmcc71dvu4vj" + +[sub_resource type="Resource" id="Resource_0schf"] +script = ExtResource("2_xupgh") +value = 25.0 +unit = "em" +metadata/_custom_type_script = "uid://cnkyynboxg1qg" + +[sub_resource type="LabelSettings" id="LabelSettings_eoac7"] + +[sub_resource type="Resource" id="Resource_ewl2f"] +script = ExtResource("4_nso1f") +en = "Value A" +metadata/_custom_type_script = "uid://bvj322mokkq63" + +[sub_resource type="Resource" id="Resource_swro7"] +script = ExtResource("4_nso1f") +en = "Other Value" +metadata/_custom_type_script = "uid://bvj322mokkq63" + +[sub_resource type="LabelSettings" id="LabelSettings_iajf2"] + +[sub_resource type="Resource" id="Resource_jgo2j"] +script = ExtResource("4_nso1f") +en = "▶" +metadata/_custom_type_script = "uid://bvj322mokkq63" + +[node name="List Handler" type="Control"] +layout_mode = 3 +anchors_preset = 0 +offset_left = 115.200005 +offset_top = 4.17776 +offset_right = 426.24005 +offset_bottom = 21.177761 +pivot_offset = Vector2(155.52002, 8.5) +script = ExtResource("1_1w55f") +metadata/_custom_type_script = "uid://c2hicupu28nbi" + +[node name="UIRegion2" type="Control" parent="."] +anchors_preset = 0 +offset_right = 23.04 +offset_bottom = 17.0 +pivot_offset = Vector2(11.52, 8.5) +mouse_filter = 1 +script = ExtResource("1_1w55f") +width = SubResource("Resource_7e4fb") +metadata/_custom_type_script = "uid://c2hicupu28nbi" + +[node name="UIText3" type="Label" parent="UIRegion2"] +layout_mode = 0 +offset_left = 6.0200005 +offset_right = 17.02 +offset_bottom = 17.0 +pivot_offset = Vector2(5.5, 8.5) +mouse_filter = 1 +label_settings = SubResource("LabelSettings_qiba2") +script = ExtResource("3_emuhf") +locale = SubResource("Resource_o8r6f") +parentStyle = SubResource("Resource_4wsps") +handleMouseEvents = true + +[node name="ChangeUIListSelection" type="Node" parent="UIRegion2" node_paths=PackedStringArray("selection")] +script = ExtResource("6_28vtr") +selection = NodePath("../../UIRegion/UIListSelection") +mode = 1 +value = -1 +metadata/_custom_type_script = "uid://b50yldymrhply" + +[node name="UIRegion" type="Control" parent="."] +anchors_preset = 0 +offset_left = 23.04 +offset_right = 288.00003 +offset_bottom = 17.0 +pivot_offset = Vector2(132.48001, 8.5) +mouse_filter = 1 +script = ExtResource("1_1w55f") +width = SubResource("Resource_0schf") +metadata/_custom_type_script = "uid://c2hicupu28nbi" + +[node name="UIListSelection" type="Label" parent="UIRegion" node_paths=PackedStringArray("onFocusEntered", "onFocusExited")] +layout_mode = 0 +offset_left = 97.48001 +offset_right = 167.48001 +offset_bottom = 17.0 +pivot_offset = Vector2(35, 8.5) +label_settings = SubResource("LabelSettings_eoac7") +script = ExtResource("7_4f0b5") +values = [SubResource("Resource_ewl2f"), SubResource("Resource_swro7")] +locale = SubResource("Resource_swro7") +parentStyle = SubResource("Resource_4wsps") +onFocusEntered = NodePath("../../On Focus Entered") +onFocusExited = NodePath("../../On Focus Exited") +metadata/_custom_type_script = "uid://2ftd0bt6rrgo" + +[node name="UIRegion4" type="Control" parent="."] +anchors_preset = 0 +offset_left = 288.00003 +offset_right = 311.04004 +offset_bottom = 17.0 +pivot_offset = Vector2(11.520004, 8.5) +mouse_filter = 1 +script = ExtResource("1_1w55f") +width = SubResource("Resource_7e4fb") +metadata/_custom_type_script = "uid://c2hicupu28nbi" + +[node name="UIText2" type="Label" parent="UIRegion4"] +layout_mode = 0 +offset_left = 6.0200005 +offset_right = 17.02 +offset_bottom = 17.0 +pivot_offset = Vector2(5.5, 8.5) +mouse_filter = 1 +label_settings = SubResource("LabelSettings_iajf2") +script = ExtResource("3_emuhf") +locale = SubResource("Resource_jgo2j") +parentStyle = SubResource("Resource_4wsps") +handleMouseEvents = true + +[node name="ChangeUIListSelection2" type="Node" parent="UIRegion4" node_paths=PackedStringArray("selection")] +script = ExtResource("6_28vtr") +selection = NodePath("../../UIRegion/UIListSelection") +mode = 1 +value = 1 +metadata/_custom_type_script = "uid://b50yldymrhply" + +[node name="On Focus Entered" type="Node" parent="."] +script = ExtResource("8_001d7") +metadata/_custom_type_script = "uid://b4yjsis2fh64c" + +[node name="On Focus Exited" type="Node" parent="."] +script = ExtResource("8_001d7") +metadata/_custom_type_script = "uid://b4yjsis2fh64c" diff --git a/Runtime/UI/UIAppSettings/Handlers/Presets/Number Controller.tscn b/Runtime/UI/UIAppSettings/Handlers/Presets/Number Controller.tscn new file mode 100644 index 0000000..3b67bda --- /dev/null +++ b/Runtime/UI/UIAppSettings/Handlers/Presets/Number Controller.tscn @@ -0,0 +1,235 @@ +[gd_scene load_steps=39 format=3 uid="uid://58yaanrblnvj"] + +[ext_resource type="Script" uid="uid://c2hicupu28nbi" path="res://addons/rokojori_action_library/Runtime/UI/Nodes/UIRegion.cs" id="1_ucjfr"] +[ext_resource type="Script" uid="uid://1pymvcckklic" path="res://addons/rokojori_action_library/Runtime/UI/Shaders/Slider/SliderMaterial.cs" id="2_rckb5"] +[ext_resource type="Shader" uid="uid://drifsskg885sj" path="res://addons/rokojori_action_library/Runtime/UI/Shaders/Slider/Slider.gdshader" id="3_ca53k"] +[ext_resource type="Texture2D" uid="uid://coc7upm22lwcw" path="res://addons/rokojori_action_library/Assets/Textures/white.svg" id="4_vb488"] +[ext_resource type="Script" uid="uid://cqi3jitprf7o0" path="res://addons/rokojori_action_library/Runtime/UI/Nodes/Sliders/ValueSlider/UIValueSlider.cs" id="5_p2b8g"] +[ext_resource type="Script" uid="uid://bsonpc71ochpe" path="res://addons/rokojori_action_library/Runtime/UI/Nodes/Sliders/ValueSlider/UIFloatValueMode.cs" id="6_1gbfa"] +[ext_resource type="Script" uid="uid://lhuuedx87rem" path="res://addons/rokojori_action_library/Runtime/Animation/Smoothing/FrameSmoothing.cs" id="7_pjx5d"] +[ext_resource type="Script" uid="uid://cnkyynboxg1qg" path="res://addons/rokojori_action_library/Runtime/UI/Styling/UINumber.cs" id="7_sr7fn"] +[ext_resource type="Script" uid="uid://drqb0pm5ub64g" path="res://addons/rokojori_action_library/Runtime/UI/Styling/UIColor.cs" id="8_74lu0"] +[ext_resource type="Script" uid="uid://cwcm7eu486tr4" path="res://addons/rokojori_action_library/Runtime/UI/Nodes/Image/UIImageTypes/SliderUIImageType.cs" id="9_jpqb0"] +[ext_resource type="Script" uid="uid://rqs2m0u6yvvf" path="res://addons/rokojori_action_library/Runtime/UI/Nodes/UIText.cs" id="10_58ifk"] +[ext_resource type="Script" uid="uid://bvj322mokkq63" path="res://addons/rokojori_action_library/Runtime/Localization/LocaleText.cs" id="11_dmue3"] +[ext_resource type="Script" uid="uid://cdsqunj017b7y" path="res://addons/rokojori_action_library/Runtime/UI/Styling/UICursor.cs" id="11_gdfkg"] +[ext_resource type="Script" uid="uid://chmcc71dvu4vj" path="res://addons/rokojori_action_library/Runtime/UI/Styling/UIStyle.cs" id="12_obxtq"] +[ext_resource type="Script" uid="uid://b4yjsis2fh64c" path="res://addons/rokojori_action_library/Runtime/Actions/ActionList.cs" id="15_v3vxy"] + +[sub_resource type="ShaderMaterial" id="ShaderMaterial_op7xn"] +shader = ExtResource("3_ca53k") +shader_parameter/opacity = 1.0 +shader_parameter/blendLinear = false +shader_parameter/size = Vector2(0, 0) +shader_parameter/sharpness = 5.0 +shader_parameter/borderRadius = 5.0 +shader_parameter/offset = 0.0 +shader_parameter/fillColor = Color(0, 0, 0, 1) +shader_parameter/fillUVTransform = Vector4(0, 0, 0, 0) +shader_parameter/screenfillMultiplyUVTransform = Vector4(0, 0, 0, 0) +shader_parameter/screenfillMultiplyUVMovement = Vector2(0, 0) +shader_parameter/strokeSize = 5.0 +shader_parameter/strokeColor = Color(0, 0, 0, 1) +shader_parameter/strokeUVTransform = Vector4(0, 0, 0, 0) +shader_parameter/screenStrokeMultiplyUVTransform = Vector4(0, 0, 0, 0) +shader_parameter/screenStrokeMultiplyUVMovment = Vector2(0, 0) +shader_parameter/sliderSizeX = 0.0 +shader_parameter/sliderSizeY = 0.0 +shader_parameter/sliderSizeMarginX = 0.0 +shader_parameter/sliderSizeMarginY = 0.0 +shader_parameter/sliderBorders = 0.0 +shader_parameter/sliderValue = Vector2(0.5, 0.5) +shader_parameter/sliderFillColor = Color(0, 0, 0, 1) +shader_parameter/sliderStrokeColor = Color(0, 0, 0, 1) +shader_parameter/sliderStrokeSize = 2.0 +script = ExtResource("2_rckb5") + +[sub_resource type="Resource" id="Resource_ebf7l"] +script = ExtResource("6_1gbfa") +max = 100.0 +metadata/_custom_type_script = "uid://bsonpc71ochpe" + +[sub_resource type="Resource" id="Resource_gdfkg"] +script = ExtResource("7_pjx5d") +frames = 20.0 +metadata/_custom_type_script = "uid://lhuuedx87rem" + +[sub_resource type="Resource" id="Resource_pv02u"] +script = ExtResource("7_sr7fn") +value = 1.0 +unit = "em" +metadata/_custom_type_script = "uid://cnkyynboxg1qg" + +[sub_resource type="Resource" id="Resource_412gp"] +script = ExtResource("8_74lu0") +color = Color(0.3090081, 0.3473884, 0.40495878, 1) +metadata/_custom_type_script = "uid://drqb0pm5ub64g" + +[sub_resource type="Resource" id="Resource_pp0bs"] +script = ExtResource("7_sr7fn") +value = 0.334 +unit = "em" +metadata/_custom_type_script = "uid://cnkyynboxg1qg" + +[sub_resource type="Resource" id="Resource_t2h31"] +script = ExtResource("8_74lu0") +metadata/_custom_type_script = "uid://drqb0pm5ub64g" + +[sub_resource type="Resource" id="Resource_ubijs"] +script = ExtResource("7_sr7fn") +value = 0.598 +unit = "em" +metadata/_custom_type_script = "uid://cnkyynboxg1qg" + +[sub_resource type="Resource" id="Resource_dq7d0"] +script = ExtResource("7_sr7fn") +value = 1.2525 +unit = "em" +metadata/_custom_type_script = "uid://cnkyynboxg1qg" + +[sub_resource type="Resource" id="Resource_tdk3c"] +script = ExtResource("7_sr7fn") +value = 0.6355 +unit = "em" +metadata/_custom_type_script = "uid://cnkyynboxg1qg" + +[sub_resource type="Resource" id="Resource_p7jqt"] +script = ExtResource("8_74lu0") +color = Color(1, 1, 1, 0) +metadata/_custom_type_script = "uid://drqb0pm5ub64g" + +[sub_resource type="Resource" id="Resource_ioimv"] +script = ExtResource("8_74lu0") +color = Color(1, 1, 1, 0) +metadata/_custom_type_script = "uid://drqb0pm5ub64g" + +[sub_resource type="Resource" id="Resource_q8n2a"] +script = ExtResource("7_sr7fn") +unit = "em" +metadata/_custom_type_script = "uid://cnkyynboxg1qg" + +[sub_resource type="Resource" id="Resource_loqre"] +script = ExtResource("9_jpqb0") +fillColor = SubResource("Resource_412gp") +strokeColor = SubResource("Resource_ioimv") +borderRadius = SubResource("Resource_pv02u") +strokeSize = SubResource("Resource_q8n2a") +sliderSizeX = SubResource("Resource_dq7d0") +sliderSizeY = SubResource("Resource_tdk3c") +sliderSizeMarginX = SubResource("Resource_ubijs") +sliderBorderRadius = SubResource("Resource_pp0bs") +sliderFillColor = SubResource("Resource_t2h31") +sliderStrokeColor = SubResource("Resource_p7jqt") + +[sub_resource type="Resource" id="Resource_jhmds"] +script = ExtResource("7_sr7fn") +value = 20.0 +unit = "em" +metadata/_custom_type_script = "uid://cnkyynboxg1qg" + +[sub_resource type="Resource" id="Resource_mseeg"] +script = ExtResource("7_sr7fn") +value = 1.0 +unit = "em" +metadata/_custom_type_script = "uid://cnkyynboxg1qg" + +[sub_resource type="Resource" id="Resource_44lr4"] +script = ExtResource("11_gdfkg") +metadata/_custom_type_script = "uid://cdsqunj017b7y" + +[sub_resource type="Resource" id="Resource_drk6d"] +script = ExtResource("7_sr7fn") +value = 100.0 +unit = "%" +metadata/_custom_type_script = "uid://cnkyynboxg1qg" + +[sub_resource type="Resource" id="Resource_jtfq4"] +script = ExtResource("7_sr7fn") +value = 10.0 +unit = "em" +metadata/_custom_type_script = "uid://cnkyynboxg1qg" + +[sub_resource type="LabelSettings" id="LabelSettings_to3ck"] + +[sub_resource type="Resource" id="Resource_r7l7h"] +script = ExtResource("11_dmue3") +en = "Test" +metadata/_custom_type_script = "uid://bvj322mokkq63" + +[sub_resource type="Resource" id="Resource_4wsps"] +script = ExtResource("12_obxtq") +metadata/_custom_type_script = "uid://chmcc71dvu4vj" + +[sub_resource type="Resource" id="Resource_mk81p"] +script = ExtResource("7_sr7fn") +value = 10.0 +unit = "vw" +metadata/_custom_type_script = "uid://cnkyynboxg1qg" + +[node name="Number Handler" type="Control"] +layout_mode = 3 +anchors_preset = 0 +offset_left = 115.200005 +offset_top = 4.17776 +offset_right = 426.24002 +offset_bottom = 21.177761 +pivot_offset = Vector2(155.52, 8.5) +script = ExtResource("1_ucjfr") +metadata/_custom_type_script = "uid://c2hicupu28nbi" + +[node name="UIValueSlider" type="TextureRect" parent="." node_paths=PackedStringArray("valueText", "onFocusEntered", "onFocusExited")] +material = SubResource("ShaderMaterial_op7xn") +layout_mode = 0 +offset_top = 2.7399998 +offset_right = 230.40001 +offset_bottom = 14.26 +pivot_offset = Vector2(115.200005, 5.76) +focus_mode = 2 +texture = ExtResource("4_vb488") +expand_mode = 1 +script = ExtResource("5_p2b8g") +valueText = NodePath("../UIRegion2/Value") +mode = SubResource("Resource_ebf7l") +direction = 1 +smoothing = SubResource("Resource_gdfkg") +sliderValue = Vector2(0.5, 0.5) +imageType = SubResource("Resource_loqre") +width = SubResource("Resource_jhmds") +height = SubResource("Resource_mseeg") +hoverCursor = SubResource("Resource_44lr4") +onFocusEntered = NodePath("../On Focus Entered") +onFocusExited = NodePath("../On Focus Exited") +metadata/_custom_type_script = "uid://cqi3jitprf7o0" + +[node name="UIRegion2" type="Control" parent="."] +anchors_preset = 0 +offset_left = 230.40001 +offset_right = 311.04 +offset_bottom = 17.0 +pivot_offset = Vector2(40.32, 8.5) +mouse_filter = 1 +script = ExtResource("1_ucjfr") +horizontalAlignment = SubResource("Resource_drk6d") +width = SubResource("Resource_jtfq4") +metadata/_custom_type_script = "uid://c2hicupu28nbi" + +[node name="Value" type="Label" parent="UIRegion2"] +layout_mode = 0 +offset_left = 55.64 +offset_right = 80.64 +offset_bottom = 17.0 +pivot_offset = Vector2(12.5, 8.5) +text = "Test" +label_settings = SubResource("LabelSettings_to3ck") +script = ExtResource("10_58ifk") +locale = SubResource("Resource_r7l7h") +parentStyle = SubResource("Resource_4wsps") +width = SubResource("Resource_mk81p") + +[node name="On Focus Entered" type="Node" parent="."] +script = ExtResource("15_v3vxy") +metadata/_custom_type_script = "uid://b4yjsis2fh64c" + +[node name="On Focus Exited" type="Node" parent="."] +script = ExtResource("15_v3vxy") +metadata/_custom_type_script = "uid://b4yjsis2fh64c" diff --git a/Runtime/UI/UIAppSettings/Handlers/UIAppSettingHandler.cs b/Runtime/UI/UIAppSettings/Handlers/UIAppSettingHandler.cs new file mode 100644 index 0000000..3824a2f --- /dev/null +++ b/Runtime/UI/UIAppSettings/Handlers/UIAppSettingHandler.cs @@ -0,0 +1,21 @@ + +using Godot; +using Rokojori; +using System.Collections.Generic; +using System.Linq; + +namespace Rokojori; + +[Tool] +[GlobalClass] +public abstract partial class UIAppSettingHandler:UIRegion +{ + [Export] + public AppSetting appSetting; + + public abstract void LoadSetting(); + + public abstract void FocusHandler(); + + +} diff --git a/Runtime/UI/UIAppSettings/Handlers/UIAppSettingHandler.cs.uid b/Runtime/UI/UIAppSettings/Handlers/UIAppSettingHandler.cs.uid new file mode 100644 index 0000000..a5bd459 --- /dev/null +++ b/Runtime/UI/UIAppSettings/Handlers/UIAppSettingHandler.cs.uid @@ -0,0 +1 @@ +uid://bcc7cyidhl6wm diff --git a/Runtime/UI/UIAppSettings/Handlers/UIListAppSettingHandler.cs b/Runtime/UI/UIAppSettings/Handlers/UIListAppSettingHandler.cs new file mode 100644 index 0000000..8a6bcc8 --- /dev/null +++ b/Runtime/UI/UIAppSettings/Handlers/UIListAppSettingHandler.cs @@ -0,0 +1,43 @@ + +using Godot; + +namespace Rokojori; + +[Tool] +[GlobalClass] +public partial class UIListAppSettingHandler:UIAppSettingHandler +{ + [Export] + public UIListSelection list; + + public override void _Ready() + { + Initialize(); + } + + public override void FocusHandler() + { + list.CallDeferred( list.GrabFocus ); + } + + public override void LoadSetting() + { + var app = Unique.Get(); + var value = app.GetSetting( appSetting ); + list.SetSelectedBySerialized( value ); + } + + public void Initialize() + { + list.values = ( appSetting as ListAppSetting ).values; + + list._onSelectionChange.AddAction( + ( v2 )=> + { + var app = Unique.Get(); + app.SetSetting( appSetting.id, list.SerializeSelectedOption() ); + appSetting.ApplyValue( app ); + } + ); + } +} diff --git a/Runtime/UI/UIAppSettings/Handlers/UIListAppSettingHandler.cs.uid b/Runtime/UI/UIAppSettings/Handlers/UIListAppSettingHandler.cs.uid new file mode 100644 index 0000000..26ebac2 --- /dev/null +++ b/Runtime/UI/UIAppSettings/Handlers/UIListAppSettingHandler.cs.uid @@ -0,0 +1 @@ +uid://b1uumkpthbl76 diff --git a/Runtime/UI/UIAppSettings/Handlers/UINumberAppSettingHandler.cs b/Runtime/UI/UIAppSettings/Handlers/UINumberAppSettingHandler.cs new file mode 100644 index 0000000..b85c483 --- /dev/null +++ b/Runtime/UI/UIAppSettings/Handlers/UINumberAppSettingHandler.cs @@ -0,0 +1,71 @@ + +using Godot; +using Rokojori; +using System.Collections.Generic; +using System.Linq; + +namespace Rokojori; + +[Tool] +[GlobalClass] +public partial class UINumberAppSettingHandler:UIAppSettingHandler +{ + [Export] + public UIValueSlider slider; + + public override void _Ready() + { + Initialize(); + } + + public override void FocusHandler() + { + slider.CallDeferred( slider.GrabFocus ); + } + + + + public override void LoadSetting() + { + var app = Unique.Get(); + var value = app.GetSetting( appSetting ); + var normalized = slider.mode.FromSerializedToNormalized( value ); + slider.SetSliderMainValue( normalized ); + + this.LogInfo( "Set setting", appSetting.title.currentValue, value, normalized ); + } + + public void Initialize() + { + UIValueSliderMode mode = null; + + if ( appSetting is ResolutionScalingSetting rss ) + { + var resFloatMode = new UIResolutionScaleMode(); + resFloatMode.CopyFrom( appSetting as NumberAppSetting ); + resFloatMode.userScaleToResolutionScale = rss.userScaleToResolutionScale; + mode = resFloatMode; + } + else + { + mode = UIFloatValueMode.From( appSetting as NumberAppSetting ); + } + + slider.mode = mode; + + slider._onSliderChange.AddAction( + ( v2 )=> + { + if ( appSetting is ResolutionScalingSetting ) + { + var resFloatMode = slider.mode as UIResolutionScaleMode; + resFloatMode.windowSize = GetWindow().Size; + } + + var app = Unique.Get(); + app.SetSetting( appSetting.id, slider.mode.GetSerializedValue( slider.mainValue ) ); + appSetting.ApplyValue( app ); + } + ); + } +} diff --git a/Runtime/UI/UIAppSettings/Handlers/UINumberAppSettingHandler.cs.uid b/Runtime/UI/UIAppSettings/Handlers/UINumberAppSettingHandler.cs.uid new file mode 100644 index 0000000..3d59381 --- /dev/null +++ b/Runtime/UI/UIAppSettings/Handlers/UINumberAppSettingHandler.cs.uid @@ -0,0 +1 @@ +uid://yveix6mv8qko diff --git a/Runtime/UI/UIAppSettings/Headers/MinimalisticHeaderGenerator.cs b/Runtime/UI/UIAppSettings/Headers/MinimalisticHeaderGenerator.cs new file mode 100644 index 0000000..2cca47d --- /dev/null +++ b/Runtime/UI/UIAppSettings/Headers/MinimalisticHeaderGenerator.cs @@ -0,0 +1,100 @@ + +using System.Collections.Generic; +using System.Linq; +using Godot; +using Rokojori; + +namespace Rokojori; + +[Tool] +[GlobalClass] +public partial class MinimalisticHeaderGenerator:UIAppSettingsHeaderGenerator +{ + + + [Export] + public UIStyle headerStyle; + + [Export] + public UIStyle backgroundStyle; + + [Export] + public UIImageType backgroundImageType; + + [Export] + public SensorIcon leftIcon; + + [Export] + public SensorIcon rightIcon; + + [Export] + public UIStyle categoryContainerStyle; + + [Export] + public UIStyle categoryIconStyle; + + [Export] + public UIStyle categoryLabelStyle; + + + public override UIAppSettingsHeader GenerateHeader( UIAppSettings uiAppSettings, AppSettings appSettings ) + { + var ignores = new List(); + uiAppSettings.ForEachDirectChild( c => { ignores.Add( c ); } ); + + var header = uiAppSettings.CreateChild( "Header"); + header.parentStyle = headerStyle; + + ignores.Add( header ); + + var background = header.CreateChild( "Background" ); + background.parentStyle = backgroundStyle; + background.imageType = backgroundImageType; + background.Texture = UI.whiteTexture.Get(); + + var leftInfo = header.CreateChild( "Left Input "); + leftInfo.inputIcons = [ leftIcon ]; + leftInfo.deviceFilter = new LastActiveDeviceFilter(); + + + var selectors = new List(); + + for ( int i = 0 ; i < appSettings.categories.Length; i++ ) + { + var category = appSettings.categories[ i ]; + + var categoryRegion = header.CreateChild( "[ " + category.title.currentValue + " ]" ); + categoryRegion.parentStyle = categoryContainerStyle; + + var icon = categoryRegion.CreateChild(); + icon.Texture = category.icon; + icon.parentStyle = categoryIconStyle; + + var label = categoryRegion.CreateChild(); + label.locale = category.title; + label.parentStyle = categoryLabelStyle; + label.MouseFilter = Control.MouseFilterEnum.Pass; + + var selector = label.CreateChild( "Select Page" ); + selector.uiStylable = categoryRegion; + selector.uiAppSettings = uiAppSettings; + selector.category = category; + label.handleMouseEvents = true; + label.onLeftClick = selector; + + selectors.Add( selector ); + } + + header.pageSelectors = selectors.ToArray(); + + + + var rightInfo = header.CreateChild( "Right Input "); + + rightInfo.inputIcons = [ rightIcon ]; + rightInfo.deviceFilter = new LastActiveDeviceFilter(); + + return header; + } + +} diff --git a/Runtime/UI/UIAppSettings/Headers/MinimalisticHeaderGenerator.cs.uid b/Runtime/UI/UIAppSettings/Headers/MinimalisticHeaderGenerator.cs.uid new file mode 100644 index 0000000..b7b0735 --- /dev/null +++ b/Runtime/UI/UIAppSettings/Headers/MinimalisticHeaderGenerator.cs.uid @@ -0,0 +1 @@ +uid://dcc4hk82jju0b diff --git a/Runtime/UI/UIAppSettings/Headers/SelectSettingsPage.cs b/Runtime/UI/UIAppSettings/Headers/SelectSettingsPage.cs new file mode 100644 index 0000000..2cf9201 --- /dev/null +++ b/Runtime/UI/UIAppSettings/Headers/SelectSettingsPage.cs @@ -0,0 +1,55 @@ + +using Godot; +using Rokojori; +using System.Collections.Generic; +using System.Linq; + +namespace Rokojori; + +[Tool] +[GlobalClass] +public partial class SelectSettingsPage:Action +{ + [Export] + public UIAppSettings uiAppSettings; + + [Export] + public AppSettingsCategory category; + + [Export] + public Node uiStylable; + + protected override void _OnTrigger() + { + uiAppSettings.header.pageSelectors.ForEach( + ( ps )=> + { + var stylable = ps.uiStylable as UIStylePropertyContainerNode; + stylable.RemoveUISelectorFlag( UISelectorFlag.Active ); + } + ); + + var ownStylable = uiStylable as UIStylePropertyContainerNode; + ownStylable.AddUISelectorFlag( UISelectorFlag.Active ); + + uiAppSettings.pages.ForEach( + ( p )=> + { + var isActive = p.category == category; + p.SetVisibility( isActive ); + + + if ( ! isActive ) + { + return; + } + + p.onActive?.Trigger(); + p._OnActivated(); + + } + ); + + + } +} diff --git a/Runtime/UI/UIAppSettings/Headers/SelectSettingsPage.cs.uid b/Runtime/UI/UIAppSettings/Headers/SelectSettingsPage.cs.uid new file mode 100644 index 0000000..8880445 --- /dev/null +++ b/Runtime/UI/UIAppSettings/Headers/SelectSettingsPage.cs.uid @@ -0,0 +1 @@ +uid://yhncbks70tby diff --git a/Runtime/UI/UIAppSettings/Headers/UIAppSettingsHeader.cs b/Runtime/UI/UIAppSettings/Headers/UIAppSettingsHeader.cs new file mode 100644 index 0000000..ca632ca --- /dev/null +++ b/Runtime/UI/UIAppSettings/Headers/UIAppSettingsHeader.cs @@ -0,0 +1,15 @@ + +using Godot; +using Rokojori; +using System.Collections.Generic; +using System.Linq; + +namespace Rokojori; + +[Tool] +[GlobalClass] +public partial class UIAppSettingsHeader:UIRegion +{ + [Export] + public SelectSettingsPage[] pageSelectors = []; +} diff --git a/Runtime/UI/UIAppSettings/Headers/UIAppSettingsHeader.cs.uid b/Runtime/UI/UIAppSettings/Headers/UIAppSettingsHeader.cs.uid new file mode 100644 index 0000000..4591ef1 --- /dev/null +++ b/Runtime/UI/UIAppSettings/Headers/UIAppSettingsHeader.cs.uid @@ -0,0 +1 @@ +uid://bxkfi0jawg0gp diff --git a/Runtime/UI/UIAppSettings/Headers/UIAppSettingsHeaderGenerator.cs b/Runtime/UI/UIAppSettings/Headers/UIAppSettingsHeaderGenerator.cs new file mode 100644 index 0000000..8cc39c1 --- /dev/null +++ b/Runtime/UI/UIAppSettings/Headers/UIAppSettingsHeaderGenerator.cs @@ -0,0 +1,14 @@ + +using Godot; +using Rokojori; +using System.Collections.Generic; +using System.Linq; + +namespace Rokojori; + +[Tool] +[GlobalClass] +public abstract partial class UIAppSettingsHeaderGenerator:Resource +{ + public abstract UIAppSettingsHeader GenerateHeader( UIAppSettings uiAppSettings, AppSettings appSettings ); +} diff --git a/Runtime/UI/UIAppSettings/Headers/UIAppSettingsHeaderGenerator.cs.uid b/Runtime/UI/UIAppSettings/Headers/UIAppSettingsHeaderGenerator.cs.uid new file mode 100644 index 0000000..836cd71 --- /dev/null +++ b/Runtime/UI/UIAppSettings/Headers/UIAppSettingsHeaderGenerator.cs.uid @@ -0,0 +1 @@ +uid://bl54i76oblew4 diff --git a/Runtime/UI/UIAppSettings/InitializeUIAppSettings.cs b/Runtime/UI/UIAppSettings/InitializeUIAppSettings.cs new file mode 100644 index 0000000..3223ab7 --- /dev/null +++ b/Runtime/UI/UIAppSettings/InitializeUIAppSettings.cs @@ -0,0 +1,23 @@ + +using Godot; + +namespace Rokojori; + +[Tool] +[GlobalClass] +public partial class InitializeUIAppSettings:Action +{ + [Export] + public UIAppSettings uiAppSettings; + + protected override void _OnTrigger() + { + uiAppSettings.pages.ForEach( + p => + { + p._OnInitialize(); + p.onInitialize?.Trigger(); + } + ); + } +} \ No newline at end of file diff --git a/Runtime/UI/UIAppSettings/InitializeUIAppSettings.cs.uid b/Runtime/UI/UIAppSettings/InitializeUIAppSettings.cs.uid new file mode 100644 index 0000000..f64c319 --- /dev/null +++ b/Runtime/UI/UIAppSettings/InitializeUIAppSettings.cs.uid @@ -0,0 +1 @@ +uid://d22jpcisjv8bx diff --git a/Runtime/UI/UIAppSettings/SetUIAppSettingsReady.cs b/Runtime/UI/UIAppSettings/SetUIAppSettingsReady.cs new file mode 100644 index 0000000..3b0da67 --- /dev/null +++ b/Runtime/UI/UIAppSettings/SetUIAppSettingsReady.cs @@ -0,0 +1,26 @@ + +using Godot; + + +namespace Rokojori; + +[Tool] +[GlobalClass] +public partial class SetUIAppSettingsReady : Action +{ + [Export] + public UIAppSettings uiAppSettings; + + [Export] + public Action newReadyAction; + + protected override void _OnTrigger() + { + if ( uiAppSettings == null ) + { + return; + } + + uiAppSettings.onReady = newReadyAction; + } +} diff --git a/Runtime/UI/UIAppSettings/SetUIAppSettingsReady.cs.uid b/Runtime/UI/UIAppSettings/SetUIAppSettingsReady.cs.uid new file mode 100644 index 0000000..bf9413e --- /dev/null +++ b/Runtime/UI/UIAppSettings/SetUIAppSettingsReady.cs.uid @@ -0,0 +1 @@ +uid://bmqiq2x0pamja diff --git a/Runtime/UI/UIAppSettings/UIAppSettings.cs b/Runtime/UI/UIAppSettings/UIAppSettings.cs new file mode 100644 index 0000000..091ff1c --- /dev/null +++ b/Runtime/UI/UIAppSettings/UIAppSettings.cs @@ -0,0 +1,170 @@ + +using Godot; +using Rokojori; +using System.Collections.Generic; +using System.Linq; + +namespace Rokojori; + +[Tool] +[GlobalClass] +public partial class UIAppSettings:UIRegion +{ + [ExportToolButton( "Create App Settings UI")] + public Callable createAppSettingsUI => Callable.From( + ()=> + { + CreateAppSettingsUI(); + } + ); + + [Export] + public AppSettings appSettings; + + [Export] + public UIAppSettingsGenerator generator; + + public enum MenuChangeMode + { + None, + Clamped, + Wrapped + } + + [Export] + public MenuChangeMode menuChangeMode = MenuChangeMode.Wrapped; + + [Export] + public Action onConfirm; + + [Export] + public Action onCancel; + + [Export] + public Action onReady; + + + [ExportGroup( "References")] + + [Export] + public Node background = null; + + [Export] + public UIAppSettingsHeader header = null; + + [Export] + public UIAppSettingsCategoryPage[] pages = []; + + + + public override void _Process( double delta ) + { + ProcessMenuInputs(); + ProcessMainInputs(); + } + + void ProcessMenuInputs() + { + if ( MenuChangeMode.None == menuChangeMode ) + { + return; + } + + var settings = GetUI().settings; + var wrapped = MenuChangeMode.Wrapped == menuChangeMode; + + if ( settings == null ) + { + return; + } + + if ( settings.uiPreviousMenu?.isDown ?? false ) + { + ChangeMenu( -1, wrapped ); + } + + if ( settings.uiNextMenu?.isDown ?? false ) + { + ChangeMenu( 1, wrapped ); + } + + } + + void ProcessMainInputs() + { + var settings = GetUI().settings; + + if ( settings == null ) + { + return; + } + + if ( settings.uiConfirm?.isDown ?? false ) + { + onConfirm?.Trigger(); + onReady?.Trigger(); + } + + if ( settings.uiCancel?.isDown ?? false ) + { + onCancel?.Trigger(); + onReady?.Trigger(); + } + + } + + void ChangeMenu( int offset, bool wrap ) + { + var selectedPageIndex = pages.FindIndex( p => p.Visible ); + var nextIndex = selectedPageIndex + offset; + + nextIndex = wrap ? MathX.Repeat( nextIndex, pages.Length ) : Mathf.Clamp( nextIndex, 0, pages.Length -1 ); + + + var nextSelectedPage = pages[ nextIndex ]; + var category = nextSelectedPage.category; + + var selector = header.GetAll().Find( selector => selector.category == category ); + // var selector = nextSelectedPage.Get(); + + this.LogInfo( + "SelectedPageIndex:", selectedPageIndex, "nextIndex:", nextIndex, + HierarchyName.Of( nextSelectedPage ), + HierarchyName.Of( selector ) + ); + + selector.Trigger(); + } + + void CreateAppSettingsUI() + { + this.DestroyChildren(); + + background = null; + header = null; + pages = []; + + var resolvedSettings = appSettings ?? Unique.Get().settings; + + background = generator.background.GenerateBackground( this ) as Node; + + resolvedSettings.categories.ForEach( CreateCategory ); + + CreateHeader( resolvedSettings ); + + + + pages.ForEach( p => p.SetVisibility( p.category == appSettings.categories[ 0 ] ) ); + } + + void CreateHeader( AppSettings settings ) + { + header = generator.header.GenerateHeader( this, settings ); + } + + void CreateCategory( AppSettingsCategory category ) + { + var page = generator.catergoryPage.GenerateCategoryPage( this, category ); + pages = pages.Add( page ); + } +} diff --git a/Runtime/UI/UIAppSettings/UIAppSettings.cs.uid b/Runtime/UI/UIAppSettings/UIAppSettings.cs.uid new file mode 100644 index 0000000..1eff144 --- /dev/null +++ b/Runtime/UI/UIAppSettings/UIAppSettings.cs.uid @@ -0,0 +1 @@ +uid://dv2k1qbk8o5id diff --git a/Runtime/UI/UIAppSettings/UIAppSettingsGenerator.cs b/Runtime/UI/UIAppSettings/UIAppSettingsGenerator.cs new file mode 100644 index 0000000..4a7bfec --- /dev/null +++ b/Runtime/UI/UIAppSettings/UIAppSettingsGenerator.cs @@ -0,0 +1,22 @@ + +using Godot; +using Rokojori; +using System.Collections.Generic; +using System.Linq; + +namespace Rokojori; + +[Tool] +[GlobalClass] +public partial class UIAppSettingsGenerator:Resource +{ + [Export] + public UIAppSettingsBackgroundGenerator background; + + [Export] + public UIAppSettingsHeaderGenerator header; + + [Export] + public UIAppSettingsCategoryPageGenerator catergoryPage; + +} diff --git a/Runtime/UI/UIAppSettings/UIAppSettingsGenerator.cs.uid b/Runtime/UI/UIAppSettings/UIAppSettingsGenerator.cs.uid new file mode 100644 index 0000000..050d547 --- /dev/null +++ b/Runtime/UI/UIAppSettings/UIAppSettingsGenerator.cs.uid @@ -0,0 +1 @@ +uid://brw80tdgwgw4t diff --git a/Runtime/UI/UISettings.cs b/Runtime/UI/UISettings.cs index c270dee..4113078 100644 --- a/Runtime/UI/UISettings.cs +++ b/Runtime/UI/UISettings.cs @@ -6,24 +6,55 @@ namespace Rokojori [Tool] [GlobalClass,Icon("res://addons/rokojori_action_library/Icons/UI.svg")] public partial class UISettings : Resource - { + { [Export] public InputIconsLibrary inputIconsLibrary; + [Export] + public TimeLine defaultTimeline; + + [ExportGroup("Font")] [Export] public UINumber fontSize; [Export] public Font defaultFont; + [ExportGroup("Inputs")] + [Export] + public Sensor uiConfirm; + + [Export] + public Sensor uiCancel; + + [Export] + public Sensor uiLeft; + + [Export] + public Sensor uiRight; + + [Export] + public Sensor uiUp; + + [Export] + public Sensor uiDown; + + [Export] + public Sensor uiPreviousMenu; + + [Export] + public Sensor uiNextMenu; + + + [ExportGroup("Shader Settings")] + [Export] public Vector2PropertyName sizePropertyName; [Export] public Vector2PropertyName textureSizePropertyName; - [Export] - public TimeLine defaultTimeline; + } diff --git a/Runtime/VFX/LineVFX/LineMaterial/CustomLineMaterialPreset.cs b/Runtime/VFX/LineVFX/LineMaterial/CustomLineMaterialPreset.cs new file mode 100644 index 0000000..24d39c6 --- /dev/null +++ b/Runtime/VFX/LineVFX/LineMaterial/CustomLineMaterialPreset.cs @@ -0,0 +1,35 @@ +using Godot; +using System.Collections.Generic; + +namespace Rokojori; + +[Tool,GlobalClass] +public partial class CustomLineMaterialPreset:LineMaterialPreset +{ + [Export] + public Material material; + + [Export] + public GeometryInstance3D.ShadowCastingSetting shadows = GeometryInstance3D.ShadowCastingSetting.On; + + [Export] + public LineVFXShaderSetup shaderSetup; + + public override void CreateMaterial( LineVFX lineVFX, MeshInstance3D mi ) + { + mi.SetSurfaceOverrideMaterial( 0, material ); + mi.CastShadow = shadows; + } + + public override void SetPointData( LineVFX lineVFX, MeshInstance3D mi, LinePointData data, bool start ) + { + if ( start ) + { + shaderSetup.start.Set( mi, data ); + } + else + { + shaderSetup.end.Set( mi, data ); + } + } +} diff --git a/Runtime/VFX/LineVFX/LineMaterial/CustomLineMaterialPreset.cs.uid b/Runtime/VFX/LineVFX/LineMaterial/CustomLineMaterialPreset.cs.uid new file mode 100644 index 0000000..ab516c8 --- /dev/null +++ b/Runtime/VFX/LineVFX/LineMaterial/CustomLineMaterialPreset.cs.uid @@ -0,0 +1 @@ +uid://d03apo8legu5r diff --git a/Runtime/VFX/LineVFX/LineMaterial/LineMaterialPreset.cs b/Runtime/VFX/LineVFX/LineMaterial/LineMaterialPreset.cs new file mode 100644 index 0000000..cefde77 --- /dev/null +++ b/Runtime/VFX/LineVFX/LineMaterial/LineMaterialPreset.cs @@ -0,0 +1,11 @@ +using Godot; +using System.Collections.Generic; + +namespace Rokojori; + +[Tool,GlobalClass] +public abstract partial class LineMaterialPreset:Resource +{ + public abstract void CreateMaterial( LineVFX lineVFX, MeshInstance3D mi ); + public abstract void SetPointData( LineVFX lineVFX, MeshInstance3D mi, LinePointData data, bool start ); +} diff --git a/Runtime/VFX/LineVFX/LineMaterial/LineMaterialPreset.cs.uid b/Runtime/VFX/LineVFX/LineMaterial/LineMaterialPreset.cs.uid new file mode 100644 index 0000000..c1ab03d --- /dev/null +++ b/Runtime/VFX/LineVFX/LineMaterial/LineMaterialPreset.cs.uid @@ -0,0 +1 @@ +uid://ja1i66scdmqa diff --git a/Runtime/VFX/LineVFX/LineMaterial/LineVFXShaderPointProperties.cs b/Runtime/VFX/LineVFX/LineMaterial/LineVFXShaderPointProperties.cs new file mode 100644 index 0000000..7dbb15a --- /dev/null +++ b/Runtime/VFX/LineVFX/LineMaterial/LineVFXShaderPointProperties.cs @@ -0,0 +1,34 @@ +using Godot; +using System.Collections.Generic; + +namespace Rokojori; + +[Tool] +[GlobalClass ] +public partial class LineVFXShaderPointProperties:Resource +{ + [Export] + public Vector3PropertyName positionName; + + [Export] + public Vector3PropertyName forwardName; + + [Export] + public Vector3PropertyName upName; + + [Export] + public FloatPropertyName normalizedDistance; + + public void Set( MeshInstance3D mi, LinePointData data ) + { + positionName.SetInstance( mi, data.GetPosition() ); + forwardName.SetInstance( mi, data.GetForward() ); + upName.SetInstance( mi, data.GetUp() ); + + normalizedDistance.SetInstance( mi, data.GetNormalizedDistance() ); + } + + +} + + \ No newline at end of file diff --git a/Runtime/VFX/LineVFX/LineMaterial/LineVFXShaderPointProperties.cs.uid b/Runtime/VFX/LineVFX/LineMaterial/LineVFXShaderPointProperties.cs.uid new file mode 100644 index 0000000..a162510 --- /dev/null +++ b/Runtime/VFX/LineVFX/LineMaterial/LineVFXShaderPointProperties.cs.uid @@ -0,0 +1 @@ +uid://cuo0gcxbb5wv1 diff --git a/Runtime/VFX/LineVFX/LineMaterial/LineVFXShaderSetup.cs b/Runtime/VFX/LineVFX/LineMaterial/LineVFXShaderSetup.cs new file mode 100644 index 0000000..92dfb1a --- /dev/null +++ b/Runtime/VFX/LineVFX/LineMaterial/LineVFXShaderSetup.cs @@ -0,0 +1,18 @@ +using Godot; +using System.Collections.Generic; + +namespace Rokojori; + +[Tool] +[GlobalClass ] +public partial class LineVFXShaderSetup:Resource +{ + [Export] + public LineVFXShaderPointProperties start; + + [Export] + public LineVFXShaderPointProperties end; + +} + + \ No newline at end of file diff --git a/Runtime/VFX/LineVFX/LineMaterial/LineVFXShaderSetup.cs.uid b/Runtime/VFX/LineVFX/LineMaterial/LineVFXShaderSetup.cs.uid new file mode 100644 index 0000000..8d13d52 --- /dev/null +++ b/Runtime/VFX/LineVFX/LineMaterial/LineVFXShaderSetup.cs.uid @@ -0,0 +1 @@ +uid://bxejx7wkhfpuj diff --git a/Runtime/VFX/LineVFX/LineMeshGenerator/CustomMeshGenerator.cs b/Runtime/VFX/LineVFX/LineMeshGenerator/CustomMeshGenerator.cs new file mode 100644 index 0000000..cf67251 --- /dev/null +++ b/Runtime/VFX/LineVFX/LineMeshGenerator/CustomMeshGenerator.cs @@ -0,0 +1,17 @@ +using Godot; +using System.Collections.Generic; + +namespace Rokojori; + +[Tool,GlobalClass] +public partial class CustomMeshGenerator:LineMeshGenerator +{ + [Export] + public Mesh customMesh; + + public override Mesh GetMesh( LineVFX lineVFX, MeshInstance3D mi ) + { + return customMesh; + } + +} \ No newline at end of file diff --git a/Runtime/VFX/LineVFX/LineMeshGenerator/CustomMeshGenerator.cs.uid b/Runtime/VFX/LineVFX/LineMeshGenerator/CustomMeshGenerator.cs.uid new file mode 100644 index 0000000..3eba442 --- /dev/null +++ b/Runtime/VFX/LineVFX/LineMeshGenerator/CustomMeshGenerator.cs.uid @@ -0,0 +1 @@ +uid://c16qq70lt434i diff --git a/Runtime/VFX/LineVFX/LineMeshGenerator/CylinderMeshGenerator.cs b/Runtime/VFX/LineVFX/LineMeshGenerator/CylinderMeshGenerator.cs new file mode 100644 index 0000000..2a85d8f --- /dev/null +++ b/Runtime/VFX/LineVFX/LineMeshGenerator/CylinderMeshGenerator.cs @@ -0,0 +1,40 @@ +using Godot; +using System.Collections.Generic; + +namespace Rokojori; + +[Tool,GlobalClass] +public partial class CylinderMeshGenerator:LineMeshGenerator +{ + [Export] + public int vertices = 16; + + [Export] + public int divisions = 3; + + Mesh segmentMesh; + + public void CreateMesh() + { + var gen = new CylinderGenerator(); + gen.vertices = vertices; + gen.subdivisions = divisions; + segmentMesh = gen.Generate(); + } + + int _v = -1; + int _d = -1; + + public override Mesh GetMesh( LineVFX lineVFX, MeshInstance3D mi ) + { + if ( segmentMesh == null || _v != vertices || _d != divisions) + { + CreateMesh(); + _v = vertices; + _d = divisions; + } + + return segmentMesh; + } + +} \ No newline at end of file diff --git a/Runtime/VFX/LineVFX/LineMeshGenerator/CylinderMeshGenerator.cs.uid b/Runtime/VFX/LineVFX/LineMeshGenerator/CylinderMeshGenerator.cs.uid new file mode 100644 index 0000000..d59de91 --- /dev/null +++ b/Runtime/VFX/LineVFX/LineMeshGenerator/CylinderMeshGenerator.cs.uid @@ -0,0 +1 @@ +uid://dk5uf3xvja04c diff --git a/Runtime/VFX/LineVFX/LineMeshGenerator/LineMeshGenerator.cs b/Runtime/VFX/LineVFX/LineMeshGenerator/LineMeshGenerator.cs new file mode 100644 index 0000000..5ba8c4c --- /dev/null +++ b/Runtime/VFX/LineVFX/LineMeshGenerator/LineMeshGenerator.cs @@ -0,0 +1,10 @@ +using Godot; +using System.Collections.Generic; + +namespace Rokojori; + +[Tool,GlobalClass] +public abstract partial class LineMeshGenerator:Resource +{ + public abstract Mesh GetMesh( LineVFX lineVFX, MeshInstance3D mi ); +} \ No newline at end of file diff --git a/Runtime/VFX/LineVFX/LineMeshGenerator/LineMeshGenerator.cs.uid b/Runtime/VFX/LineVFX/LineMeshGenerator/LineMeshGenerator.cs.uid new file mode 100644 index 0000000..95287fc --- /dev/null +++ b/Runtime/VFX/LineVFX/LineMeshGenerator/LineMeshGenerator.cs.uid @@ -0,0 +1 @@ +uid://cqjqt83vf62e5 diff --git a/Runtime/VFX/LineVFX/LinePoint/AutoLine/AutoLinePointData.cs b/Runtime/VFX/LineVFX/LinePoint/AutoLine/AutoLinePointData.cs new file mode 100644 index 0000000..bd8eedf --- /dev/null +++ b/Runtime/VFX/LineVFX/LinePoint/AutoLine/AutoLinePointData.cs @@ -0,0 +1,25 @@ +using Godot; +using System.Collections.Generic; + +namespace Rokojori; + +[Tool,GlobalClass] +public partial class AutoLinePointData:LinePointData +{ + [Export] + public Vector3 position; + public override Vector3 GetPosition(){ return position; } + + public Vector3 forward; + public override Vector3 GetForward(){ return forward; } + + public Vector3 up; + public override Vector3 GetUp(){ return up; } + + public float normalizedDistance = 0f; + public override float GetNormalizedDistance() + { + return normalizedDistance; + } + +} diff --git a/Runtime/VFX/LineVFX/LinePoint/AutoLine/AutoLinePointData.cs.uid b/Runtime/VFX/LineVFX/LinePoint/AutoLine/AutoLinePointData.cs.uid new file mode 100644 index 0000000..270fad9 --- /dev/null +++ b/Runtime/VFX/LineVFX/LinePoint/AutoLine/AutoLinePointData.cs.uid @@ -0,0 +1 @@ +uid://cvakxgn7tlup8 diff --git a/Runtime/VFX/LineVFX/LinePoint/AutoLine/AutoLinePointList.cs b/Runtime/VFX/LineVFX/LinePoint/AutoLine/AutoLinePointList.cs new file mode 100644 index 0000000..0945d4d --- /dev/null +++ b/Runtime/VFX/LineVFX/LinePoint/AutoLine/AutoLinePointList.cs @@ -0,0 +1,191 @@ +using Godot; +using System.Collections.Generic; + +namespace Rokojori; + +[Tool] +[GlobalClass ] +public abstract partial class AutoLinePointList:LinePointDataGenerator +{ + + + [Export] + public Vector3 up = Vector3.Up; + + [Export( PropertyHint.Range, "0,1")] + public float symmetricTangents = 0; + float _symmetricTangents = 0; + + + [Export] + public bool splitLargeDistances = false; + + [Export] + public float splitTreshold = 1.5f; // 0.75f - 1f + + [Export] + public float splitLength = 1f; + + + [Export] + public float changeTreshold = 0.000001f; + + List _cachedPoints = []; + + protected abstract void _UpdatePoints( LineVFX lineVFX, double delta ); + + public override void Update( LineVFX lineVFX, double delta ) + { + var data = lineVFX.GetData() as AutoLineVFXData; + + if ( data == null ) + { + data = new AutoLineVFXData(); + lineVFX.SetData( data ); + } + + _UpdatePoints( lineVFX, delta ); + + // if ( Mode.Local_ChildPositions_From_Auto_Line_Parent == mode || + // Mode.Global_ChildPositions_From_Auto_Line_Parent == mode + // ) + // { + // UpdatePointsFromParent( lineVFX ); + // } + + if ( ! PointsChanged( lineVFX ) ) + { + return; + } + + if ( _cachedPoints == null ) + { + _cachedPoints = []; + } + + if ( data.points == null ) + { + data.points = []; + } + + if ( _cachedPoints.Count != data.points.Length ) + { + _cachedPoints.Clear(); + for ( int i = 0; i < data.points.Length; i++ ) + { + _cachedPoints.Add( data.points[ i ].position ); + } + } + else + { + for ( int i = 0; i < data.points.Length; i++ ) + { + _cachedPoints[ i ] = data.points[ i ].position; + } + } + + var cd = lineVFX.GetData() as AutoLineVFXData; + + cd.customUpdateID ++; + + var length = 0f; + + for ( int i = 1; i < data.points.Length; i++ ) + { + var d = ( data.points[ i ].position - data.points[ i - 1 ].position ).Length(); + length += d; + + data.points[ i ].normalizedDistance = length; + + } + + for ( int i = 1; i < data.points.Length; i++ ) + { + data.points[ i ].normalizedDistance /= length; + } + + for ( int i = 0; i < data.points.Length && data.points.Length > 1 ; i++ ) + { + if ( i == data.points.Length - 1 ) + { + data.points[ i ].forward = data.points[ i ].position - data.points[ i - 1 ].position; + } + else if ( i == 0 ) + { + data.points[ i ].forward = data.points[ i + 1 ].position - data.points[ i ].position; + } + else + { + var before = data.points[ i ].position - data.points[ i - 1 ].position; + var after = data.points[ i + 1 ].position - data.points[ i ].position; + + if ( symmetricTangents > 0 ) + { + var bLength = before.Length(); + var aLength = after.Length(); + + if ( bLength < aLength ) + { + after = after.Lerp( after.Normalized() * bLength, symmetricTangents ); + } + else + { + before = before.Lerp( before.Normalized() * aLength, symmetricTangents ); + } + } + + data.points[ i ].forward = ( before + after ) * 0.5f; + } + + data.points[ i ].up = up; + } + + _symmetricTangents = symmetricTangents; + cd.points = data.points; + } + + + bool PointsChanged( LineVFX lineVFX) + { + var data = lineVFX.GetData() as AutoLineVFXData; + + if ( data.points == null || _cachedPoints == null ) + { + return true; + } + + if ( data.points.Length != _cachedPoints.Count ) + { + return true; + } + + if ( _symmetricTangents != symmetricTangents ) + { + return true; + } + + + for ( int i = 0; i < data.points.Length; i++ ) + { + var difference = data.points[ i ].position - _cachedPoints[ i ]; + + if ( Mathf.Abs( difference.X ) > 0.000001f ) + { + return true; + } + + if ( Mathf.Abs( difference.Y ) > 0.000001f ) + { + return true; + } + + if ( Mathf.Abs( difference.Z ) > 0.000001f ) + { + return true; + } + } + + return false; + } + +} diff --git a/Runtime/VFX/LineVFX/LinePoint/AutoLine/AutoLinePointList.cs.uid b/Runtime/VFX/LineVFX/LinePoint/AutoLine/AutoLinePointList.cs.uid new file mode 100644 index 0000000..d19449a --- /dev/null +++ b/Runtime/VFX/LineVFX/LinePoint/AutoLine/AutoLinePointList.cs.uid @@ -0,0 +1 @@ +uid://60gdng6n54wb diff --git a/Runtime/VFX/LineVFX/LinePoint/AutoLine/AutoLineVFXData.cs b/Runtime/VFX/LineVFX/LinePoint/AutoLine/AutoLineVFXData.cs new file mode 100644 index 0000000..4a7b15b --- /dev/null +++ b/Runtime/VFX/LineVFX/LinePoint/AutoLine/AutoLineVFXData.cs @@ -0,0 +1,29 @@ +using Godot; +using System.Collections.Generic; + +namespace Rokojori; + +public class AutoLineVFXData:LineVFXData +{ + public AutoLinePointData[] points; + public List pointsCacheList = []; + + public int customUpdateID = -1; + + public override int GetUpdateID(){ return customUpdateID; } + public override IEnumerable GetPointData(){ return points; } + public override int GetNumSegments() + { + return points == null ? 0 : points.Length - 1; + } + + public override void SetSegmentData( MeshInstance3D mi, int segmentIndex ) + { + + } + + public override Vector3 GetPositionAt( int i ) + { + return points == null ? Vector3.Zero : points[ i ].position; + } +} diff --git a/Runtime/VFX/LineVFX/LinePoint/AutoLine/AutoLineVFXData.cs.uid b/Runtime/VFX/LineVFX/LinePoint/AutoLine/AutoLineVFXData.cs.uid new file mode 100644 index 0000000..c94c463 --- /dev/null +++ b/Runtime/VFX/LineVFX/LinePoint/AutoLine/AutoLineVFXData.cs.uid @@ -0,0 +1 @@ +uid://8efughuiclqb diff --git a/Runtime/VFX/LineVFX/LinePoint/ChildPositionsAutoLine/ChildPositionsAutoLine.cs b/Runtime/VFX/LineVFX/LinePoint/ChildPositionsAutoLine/ChildPositionsAutoLine.cs new file mode 100644 index 0000000..ef5b018 --- /dev/null +++ b/Runtime/VFX/LineVFX/LinePoint/ChildPositionsAutoLine/ChildPositionsAutoLine.cs @@ -0,0 +1,114 @@ +using Godot; +using System.Collections.Generic; + +namespace Rokojori; + +[Tool] +[GlobalClass ] +public partial class ChildPositionsAutoLine:AutoLinePointList +{ + [Export] + public bool useGlobalPositions = true; + + protected override void _UpdatePoints( LineVFX lineVFX, double delta ) + { + UpdatePointsFromParent( lineVFX ); + } + + void UpdatePointsFromParent( LineVFX lineVFX ) + { + if ( lineVFX.childPositionsParent == null ) + { + return; + } + + var data = lineVFX.GetData() as AutoLineVFXData; + + var points = data.points; + var pointsCacheList = data.pointsCacheList; + + if ( splitLargeDistances ) + { + pointsCacheList.Clear(); + + var isGlobal = useGlobalPositions; + + lineVFX.childPositionsParent.ForEachDirectChild( + n3D => + { + + if ( pointsCacheList.Count == 0 ) + { + var p = new AutoLinePointData(); + p.position = n3D.GetPosition( isGlobal ); + pointsCacheList.Add( p ); + } + else + { + var last = pointsCacheList[ pointsCacheList.Count - 1 ] .position; + var current = n3D.GetPosition( isGlobal ); + var dir = current - last; + var length = dir.Length(); + + if ( length < splitTreshold ) + { + var p = new AutoLinePointData(); + p.position = n3D.GetPosition( isGlobal ); + pointsCacheList.Add( p ); + + return; + } + + var splits = Mathf.CeilToInt( length / splitLength ); + var normalizeSplit = 1f / ( splits - 1 ); + // 2 ns => 1 / ( 2 - 1 ); + // 0 x, 1 + // 4 ns => 1 / ( 4 - 1 ); + // 0 x, 1/3, 2/3, 3/3 + + for ( int i = 1; i < splits; i++ ) + { + var t = i * normalizeSplit; + + var sp = new AutoLinePointData(); + sp.position = last.Lerp( current, t ); + pointsCacheList.Add( sp ); + } + } + + } + ); + + points = pointsCacheList.ToArray(); + + } + else + { + var childCount = lineVFX.childPositionsParent.GetChildCountOfType(); + + if ( points.Length != childCount ) + { + points = new AutoLinePointData[ childCount ]; + + for ( int i = 0; i < points.Length; i++ ) + { + points[ i ] = new AutoLinePointData(); + } + } + + var index = 0; + var isGlobal = useGlobalPositions; + + lineVFX.childPositionsParent.ForEachDirectChild( + n3D => + { + // this.LogInfo( "index:", index, points.Length, childCount ); + points[ index ].position = n3D.GetPosition( isGlobal ); + index ++; + } + ); + } + } + + +} diff --git a/Runtime/VFX/LineVFX/LinePoint/ChildPositionsAutoLine/ChildPositionsAutoLine.cs.uid b/Runtime/VFX/LineVFX/LinePoint/ChildPositionsAutoLine/ChildPositionsAutoLine.cs.uid new file mode 100644 index 0000000..775974c --- /dev/null +++ b/Runtime/VFX/LineVFX/LinePoint/ChildPositionsAutoLine/ChildPositionsAutoLine.cs.uid @@ -0,0 +1 @@ +uid://cr7hfwd1ki6yu diff --git a/Runtime/VFX/LineVFX/LinePoint/CustomLine/CustomLinePointData.cs b/Runtime/VFX/LineVFX/LinePoint/CustomLine/CustomLinePointData.cs new file mode 100644 index 0000000..8f1617b --- /dev/null +++ b/Runtime/VFX/LineVFX/LinePoint/CustomLine/CustomLinePointData.cs @@ -0,0 +1,25 @@ +using Godot; +using System.Collections.Generic; + +namespace Rokojori; + +[Tool,GlobalClass] +public partial class CustomLinePointData:LinePointData +{ + [Export] + public Vector3 position; + public override Vector3 GetPosition(){ return position; } + + [Export] + public Vector3 forward; + public override Vector3 GetForward(){ return forward; } + + [Export] + public Vector3 up; + public override Vector3 GetUp(){ return up; } + + [Export] + public float normalizedDistance = 0f; + public override float GetNormalizedDistance(){ return normalizedDistance; } + +} diff --git a/Runtime/VFX/LineVFX/LinePoint/CustomLine/CustomLinePointData.cs.uid b/Runtime/VFX/LineVFX/LinePoint/CustomLine/CustomLinePointData.cs.uid new file mode 100644 index 0000000..e8eef6b --- /dev/null +++ b/Runtime/VFX/LineVFX/LinePoint/CustomLine/CustomLinePointData.cs.uid @@ -0,0 +1 @@ +uid://y615w3e7yj3o diff --git a/Runtime/VFX/LineVFX/LinePoint/CustomLine/CustomLinePointList.cs b/Runtime/VFX/LineVFX/LinePoint/CustomLine/CustomLinePointList.cs new file mode 100644 index 0000000..4902317 --- /dev/null +++ b/Runtime/VFX/LineVFX/LinePoint/CustomLine/CustomLinePointList.cs @@ -0,0 +1,31 @@ +using Godot; +using System.Collections.Generic; + +namespace Rokojori; + +[Tool] +[GlobalClass ] +public partial class CustomLinePointList:LinePointDataGenerator +{ + [Export] + public CustomLinePointData[] points; + + [Export] + public int customUpdateID = -1; + + public override void Update( LineVFX lineVFX, double delta ) + { + var data = lineVFX.GetData(); + + if ( data == null || ! ( data is CustomLineVFXData ) ) + { + lineVFX.SetData( new CustomLineVFXData() ); + } + + var cd = lineVFX.GetData() as CustomLineVFXData; + + cd.points = points; + cd.customUpdateID = customUpdateID; + } + +} diff --git a/Runtime/VFX/LineVFX/LinePoint/CustomLine/CustomLinePointList.cs.uid b/Runtime/VFX/LineVFX/LinePoint/CustomLine/CustomLinePointList.cs.uid new file mode 100644 index 0000000..8f27d49 --- /dev/null +++ b/Runtime/VFX/LineVFX/LinePoint/CustomLine/CustomLinePointList.cs.uid @@ -0,0 +1 @@ +uid://vt0juqpb0khg diff --git a/Runtime/VFX/LineVFX/LinePoint/CustomLine/CustomLineVFXData.cs b/Runtime/VFX/LineVFX/LinePoint/CustomLine/CustomLineVFXData.cs new file mode 100644 index 0000000..74a9e7d --- /dev/null +++ b/Runtime/VFX/LineVFX/LinePoint/CustomLine/CustomLineVFXData.cs @@ -0,0 +1,28 @@ +using Godot; +using System.Collections.Generic; + +namespace Rokojori; + +public class CustomLineVFXData:LineVFXData +{ + public CustomLinePointData[] points; + + public int customUpdateID = -1; + + public override int GetUpdateID(){ return customUpdateID; } + public override IEnumerable GetPointData(){ return points; } + public override int GetNumSegments() + { + return points.Length - 1; + } + + public override void SetSegmentData( MeshInstance3D mi, int segmentIndex ) + { + + } + + public override Vector3 GetPositionAt( int i ) + { + return points == null ? Vector3.Zero : points[ i ].position; + } +} diff --git a/Runtime/VFX/LineVFX/LinePoint/CustomLine/CustomLineVFXData.cs.uid b/Runtime/VFX/LineVFX/LinePoint/CustomLine/CustomLineVFXData.cs.uid new file mode 100644 index 0000000..b25ef20 --- /dev/null +++ b/Runtime/VFX/LineVFX/LinePoint/CustomLine/CustomLineVFXData.cs.uid @@ -0,0 +1 @@ +uid://4cvlhbo7vh62 diff --git a/Runtime/VFX/LineVFX/LinePoint/FollowAutoLine/FollowAutoLine.cs b/Runtime/VFX/LineVFX/LinePoint/FollowAutoLine/FollowAutoLine.cs new file mode 100644 index 0000000..89899c1 --- /dev/null +++ b/Runtime/VFX/LineVFX/LinePoint/FollowAutoLine/FollowAutoLine.cs @@ -0,0 +1,87 @@ +using Godot; +using System.Collections.Generic; + +namespace Rokojori; + +[Tool] +[GlobalClass ] +public partial class FollowAutoLine:AutoLinePointList +{ + [Export] + public float distanceTreshold = 1f; + + [Export] + public int maxPoints = 100; + + [Export] + public bool following = false; + + + protected override void _UpdatePoints( LineVFX lineVFX, double delta ) + { + if ( ! following ) + { + return; + } + + var data = lineVFX.GetData() as AutoLineVFXData; + + var points = data.points; + + + var newPosition = lineVFX.followSource.GlobalPosition; + var needsNewPoint = NotEnoughPoints( points ) || Moved( newPosition, points ); + + if ( ! needsNewPoint ) + { + + points[ points.Length -1 ].position = newPosition + Vector3.One * 0.00001f; + return; + } + + if ( points == null || points.Length < 2) + { + var p1 = new AutoLinePointData(); + var p2 = new AutoLinePointData(); + p1.position = newPosition; + p2.position = newPosition + Vector3.One * 0.00001f; + + data.points = [ p1, p2 ]; + + return; + } + + var p = new AutoLinePointData(); + p.position = newPosition; + + var pos2 = points[ points.Length - 2 ].position; + + var dir = newPosition - pos2; + + points[ points.Length - 1 ].position = pos2 + dir.Normalized() * distanceTreshold; + + if ( points.Length == maxPoints ) + { + points = points.RemoveIndex( 0 ); + } + + + data.points = points.Add( p ); + } + + bool NotEnoughPoints( AutoLinePointData[] _points ) + { + return _points == null || _points.Length < 2; + } + + + bool Moved( Vector3 current, AutoLinePointData[] _points ) + { + var lastPoint = _points[ _points.Length - 2 ].position; + + var dir = current - lastPoint; + var length = dir.Length(); + + return length > distanceTreshold; + } +} diff --git a/Runtime/VFX/LineVFX/LinePoint/FollowAutoLine/FollowAutoLine.cs.uid b/Runtime/VFX/LineVFX/LinePoint/FollowAutoLine/FollowAutoLine.cs.uid new file mode 100644 index 0000000..bc2b4b7 --- /dev/null +++ b/Runtime/VFX/LineVFX/LinePoint/FollowAutoLine/FollowAutoLine.cs.uid @@ -0,0 +1 @@ +uid://cylph4wxm4xme diff --git a/Runtime/VFX/LineVFX/LinePoint/FollowAutoLine/SetFollowAutoLine.cs b/Runtime/VFX/LineVFX/LinePoint/FollowAutoLine/SetFollowAutoLine.cs new file mode 100644 index 0000000..cab1f02 --- /dev/null +++ b/Runtime/VFX/LineVFX/LinePoint/FollowAutoLine/SetFollowAutoLine.cs @@ -0,0 +1,38 @@ +using Godot; +using System.Collections.Generic; + +namespace Rokojori; + +[Tool] +[GlobalClass ] +public partial class SetFollowAutoLine:Action +{ + [Export] + public LineVFX line; + + [Export] + public bool following = true; + + [Export] + public bool clearLine = false; + + protected override void _OnTrigger() + { + var followAutoLine = line?.preset?.pointGenerator as FollowAutoLine; + + if ( followAutoLine == null ) + { + return; + } + + followAutoLine.following = following; + + if ( clearLine ) + { + line.ClearLine(); + } + + + + } +} diff --git a/Runtime/VFX/LineVFX/LinePoint/FollowAutoLine/SetFollowAutoLine.cs.uid b/Runtime/VFX/LineVFX/LinePoint/FollowAutoLine/SetFollowAutoLine.cs.uid new file mode 100644 index 0000000..59ff40a --- /dev/null +++ b/Runtime/VFX/LineVFX/LinePoint/FollowAutoLine/SetFollowAutoLine.cs.uid @@ -0,0 +1 @@ +uid://boxi854yskurg diff --git a/Runtime/VFX/LineVFX/LinePoint/LinePointData.cs b/Runtime/VFX/LineVFX/LinePoint/LinePointData.cs new file mode 100644 index 0000000..8ff24ba --- /dev/null +++ b/Runtime/VFX/LineVFX/LinePoint/LinePointData.cs @@ -0,0 +1,16 @@ +using Godot; +using System.Collections.Generic; + +namespace Rokojori; + +[Tool,GlobalClass] +public abstract partial class LinePointData:Resource +{ + public abstract Vector3 GetPosition(); + + public abstract Vector3 GetForward(); + + public abstract Vector3 GetUp(); + + public abstract float GetNormalizedDistance(); +} diff --git a/Runtime/VFX/LineVFX/LinePoint/LinePointData.cs.uid b/Runtime/VFX/LineVFX/LinePoint/LinePointData.cs.uid new file mode 100644 index 0000000..cacd5c4 --- /dev/null +++ b/Runtime/VFX/LineVFX/LinePoint/LinePointData.cs.uid @@ -0,0 +1 @@ +uid://cd1xxx2nwnefa diff --git a/Runtime/VFX/LineVFX/LinePoint/LinePointDataGenerator.cs b/Runtime/VFX/LineVFX/LinePoint/LinePointDataGenerator.cs new file mode 100644 index 0000000..34435dd --- /dev/null +++ b/Runtime/VFX/LineVFX/LinePoint/LinePointDataGenerator.cs @@ -0,0 +1,12 @@ +using Godot; +using System.Collections.Generic; + +namespace Rokojori; + +[Tool] +[GlobalClass ] +public abstract partial class LinePointDataGenerator:Resource +{ + public abstract void Update( LineVFX lineVFX, double delta ); + +} diff --git a/Runtime/VFX/LineVFX/LinePoint/LinePointDataGenerator.cs.uid b/Runtime/VFX/LineVFX/LinePoint/LinePointDataGenerator.cs.uid new file mode 100644 index 0000000..ad0c65f --- /dev/null +++ b/Runtime/VFX/LineVFX/LinePoint/LinePointDataGenerator.cs.uid @@ -0,0 +1 @@ +uid://633vouxuraxf diff --git a/Runtime/VFX/LineVFX/LinePoint/LineVFXPointData.cs b/Runtime/VFX/LineVFX/LinePoint/LineVFXPointData.cs new file mode 100644 index 0000000..04295de --- /dev/null +++ b/Runtime/VFX/LineVFX/LinePoint/LineVFXPointData.cs @@ -0,0 +1,50 @@ +using Godot; +using System.Collections.Generic; + +namespace Rokojori; + +public abstract class LineVFXData +{ + public abstract int GetUpdateID(); + public abstract IEnumerable GetPointData(); + public abstract int GetNumSegments(); + public abstract void SetSegmentData( MeshInstance3D mi, int segmentIndex ); + public virtual int GetNumPoints() + { + return GetNumSegments() + 1; + } + + public abstract Vector3 GetPositionAt( int index ); + public Vector3 LerpPositionAt( float normalizedIndex ) + { + if ( GetNumPoints() == 0 ) + { + return Vector3.Zero; + } + + if ( GetNumPoints() == 1 ) + { + return GetPositionAt( 0 ); + } + + var pointIndex = normalizedIndex * GetNumPoints(); + + if ( pointIndex <= 0 ) + { + return GetPositionAt( 0 ); + } + + if ( pointIndex >= GetNumPoints() - 1 ) + { + return GetPositionAt( GetNumPoints() - 1 ); + } + + var lowerIndex = Mathf.FloorToInt( pointIndex ); + var higherIndex = Mathf.CeilToInt( pointIndex ); + + var p0 = GetPositionAt( lowerIndex ); + var p1 = GetPositionAt( higherIndex ); + + return p0.Lerp( p1, pointIndex - lowerIndex ); + } +} diff --git a/Runtime/VFX/LineVFX/LinePoint/LineVFXPointData.cs.uid b/Runtime/VFX/LineVFX/LinePoint/LineVFXPointData.cs.uid new file mode 100644 index 0000000..54c2b5a --- /dev/null +++ b/Runtime/VFX/LineVFX/LinePoint/LineVFXPointData.cs.uid @@ -0,0 +1 @@ +uid://dsa3wvnj2ukom diff --git a/Runtime/VFX/LineVFX/LinePoint/ManualAutoLine/ManualAutoLine.cs b/Runtime/VFX/LineVFX/LinePoint/ManualAutoLine/ManualAutoLine.cs new file mode 100644 index 0000000..b6f590c --- /dev/null +++ b/Runtime/VFX/LineVFX/LinePoint/ManualAutoLine/ManualAutoLine.cs @@ -0,0 +1,19 @@ +using Godot; +using System.Collections.Generic; + +namespace Rokojori; + +[Tool] +[GlobalClass ] +public partial class ManualAutoLine:AutoLinePointList +{ + [Export] + public AutoLinePointData[] points; + + protected override void _UpdatePoints( LineVFX lineVFX, double delta ) + { + var data = lineVFX.GetData() as AutoLineVFXData; + + data.points = points; + } +} diff --git a/Runtime/VFX/LineVFX/LinePoint/ManualAutoLine/ManualAutoLine.cs.uid b/Runtime/VFX/LineVFX/LinePoint/ManualAutoLine/ManualAutoLine.cs.uid new file mode 100644 index 0000000..0eedf3a --- /dev/null +++ b/Runtime/VFX/LineVFX/LinePoint/ManualAutoLine/ManualAutoLine.cs.uid @@ -0,0 +1 @@ +uid://qu0grxbx4sda diff --git a/Runtime/VFX/LineVFX/LinePreset.cs b/Runtime/VFX/LineVFX/LinePreset.cs new file mode 100644 index 0000000..ddba66e --- /dev/null +++ b/Runtime/VFX/LineVFX/LinePreset.cs @@ -0,0 +1,29 @@ +using Godot; +using System.Collections.Generic; + +namespace Rokojori; + +[Tool] +[GlobalClass ] +public partial class LinePreset:Resource +{ + [Export] + public LinePointDataGenerator pointGenerator; + + [Export] + public LineMeshGenerator meshGenerator; + + [Export] + public LineMaterialPreset materialPreset; + + public void Update( LineVFX lineVFX, double delta ) + { + if ( pointGenerator == null ) + { + return; + } + + pointGenerator.Update( lineVFX, delta ); + } + +} diff --git a/Runtime/VFX/LineVFX/LinePreset.cs.uid b/Runtime/VFX/LineVFX/LinePreset.cs.uid new file mode 100644 index 0000000..7a35173 --- /dev/null +++ b/Runtime/VFX/LineVFX/LinePreset.cs.uid @@ -0,0 +1 @@ +uid://bt72ncr1j6ybq diff --git a/Runtime/VFX/LineVFX/LineVFX.cs b/Runtime/VFX/LineVFX/LineVFX.cs new file mode 100644 index 0000000..f1334d0 --- /dev/null +++ b/Runtime/VFX/LineVFX/LineVFX.cs @@ -0,0 +1,169 @@ +using Godot; +using System.Collections.Generic; + +namespace Rokojori; + +[Tool] +[GlobalClass ] +public partial class LineVFX:Node3D +{ + [ExportToolButton( "Force Update")] + public Callable forceUpdateButton => Callable.From( + () => + { + ClearLine(); + } + ); + + public void ClearLine() + { + _lastUpdateID = -1; + _data = null; + this.DestroyChildren(); + } + + [Export] + public LinePreset preset; + + [ExportGroup("References")] + [Export] + public Node3D followSource; + + [Export] + public Node3D childPositionsParent; + + [ExportGroup("Shader Setup")] + [Export] + public Vector3PropertyName startPositionName; + + [Export] + public Vector3PropertyName startForwardName; + + [Export] + public Vector3PropertyName startUpName; + + [Export] + public Vector3PropertyName endPositionName; + + [Export] + public Vector3PropertyName endForwardName; + + [Export] + public Vector3PropertyName endUpName; + + + + + LineVFXData _data; + int _lastUpdateID = -1; + + public void SetData( LineVFXData data ) + { + _data = data; + } + + public LineVFXData GetData() + { + return _data; + } + + public override void _Process( double delta ) + { + if ( preset == null ) + { + return; + } + + preset.Update( this, delta ); + + if ( _data == null || _lastUpdateID == _data.GetUpdateID() ) + { + return; + } + + _lastUpdateID = _data.GetUpdateID(); + UpdateSegments(); + + + } + + public Vector3 GetLerpedLinePositionAt( float t ) + { + return _data == null ? Vector3.Zero : _data.LerpPositionAt( t ); + } + + void UpdateSegments() + { + var segments = Mathf.Max( 0, _data.GetNumSegments() ); + + + this.EnsureChildCount( segments, + ( mi )=> + { + mi.Mesh = preset.meshGenerator.GetMesh( this, mi ); + preset.materialPreset.CreateMaterial( this, mi ); + } + ); + + + var points = _data.GetPointData(); + + LinePointData start = null; + var segmentIndex = 0; + + foreach ( var p in points ) + { + if ( start == null ) + { + start = p; + + // if ( lineStart != null ) + // { + // lineStart.GlobalPosition = start.GetPosition(); + // lineStart.LookAt( start.GetPosition() + start.GetForward(), start.GetUp() ); + // } + + continue; + } + + var end = p; + var mi = GetChild( segmentIndex ) as MeshInstance3D; + segmentIndex++; + + preset.materialPreset.SetPointData( this, mi, start, true ); + preset.materialPreset.SetPointData( this, mi, end, false ); + // AssignPointData( mi, start, startPositionName, startForwardName, startUpName ); + // AssignPointData( mi, end, endPositionName, endForwardName, endUpName ); + + var startPosition = start.GetPosition(); + var endPosition = end.GetPosition(); + + var bounds = Box3.Create( startPosition, endPosition ); + bounds.Extend( 1 + ( endPosition - startPosition ).Length() ); + mi.CustomAabb = bounds; + + start = end; + } + + + // if ( lineEnd != null ) + // { + // lineEnd.GlobalPosition = start.GetPosition(); + // lineEnd.LookAt( start.GetPosition() + start.GetForward(), start.GetUp() ); + // } + + // for ( int i = 0; i < segments; i++ ) + // { + // var mi = GetChild( i ) as MeshInstance3D; + + // } + } + + // void AssignPointData( GeometryInstance3D gi, LinePointData lp, + // Vector3PropertyName p, Vector3PropertyName f, Vector3PropertyName u ) + // { + // p.SetInstance( gi, lp.GetPosition() ); + // f.SetInstance( gi, lp.GetForward() ); + // u.SetInstance( gi, lp.GetUp() ); + // } +} diff --git a/Runtime/VFX/LineVFX/LineVFX.cs.uid b/Runtime/VFX/LineVFX/LineVFX.cs.uid new file mode 100644 index 0000000..37c5261 --- /dev/null +++ b/Runtime/VFX/LineVFX/LineVFX.cs.uid @@ -0,0 +1 @@ +uid://sf08iwoga2ba diff --git a/Runtime/VFX/LineVFX/SetPositionOnLineVFX.cs b/Runtime/VFX/LineVFX/SetPositionOnLineVFX.cs new file mode 100644 index 0000000..ecc033e --- /dev/null +++ b/Runtime/VFX/LineVFX/SetPositionOnLineVFX.cs @@ -0,0 +1,38 @@ +using Godot; +using System.Collections.Generic; + +namespace Rokojori; + +[Tool] +[GlobalClass ] +public partial class SetPositionOnLineVFX:Action +{ + [Export] + public Node3D target; + + [Export] + public LineVFX lineVFX; + + [Export( PropertyHint.Range, "0,1" ) ] + public float normalizedPosition = 0.5f; + + [Export( PropertyHint.Range, "0,1" ) ] + public float normalizedRange = 0.5f; + + protected override void _OnTrigger() + { + var random = GodotRandom.Get(); + + var min = normalizedPosition - normalizedRange; + var max = normalizedPosition + normalizedRange; + + var t = random.Range( min, max ); + t = MathX.Clamp01( t ); + + // this.LogInfo( t, normalizedPosition, normalizedRange, min, max ); + + var p = lineVFX.GetLerpedLinePositionAt( t ); + + target.GlobalPosition = p; + } +} diff --git a/Runtime/VFX/LineVFX/SetPositionOnLineVFX.cs.uid b/Runtime/VFX/LineVFX/SetPositionOnLineVFX.cs.uid new file mode 100644 index 0000000..4c03b2a --- /dev/null +++ b/Runtime/VFX/LineVFX/SetPositionOnLineVFX.cs.uid @@ -0,0 +1 @@ +uid://bsuqbg0trgspl diff --git a/Tools/Messages/Message Background.tres b/Tools/Messages/Message Background.tres index b87e9de..354cc48 100644 --- a/Tools/Messages/Message Background.tres +++ b/Tools/Messages/Message Background.tres @@ -2,7 +2,7 @@ [ext_resource type="Script" uid="uid://cnkyynboxg1qg" path="res://addons/rokojori_action_library/Runtime/UI/Styling/UINumber.cs" id="1_4fcac"] [ext_resource type="Script" uid="uid://drqb0pm5ub64g" path="res://addons/rokojori_action_library/Runtime/UI/Styling/UIColor.cs" id="2_m58tc"] -[ext_resource type="Script" uid="uid://dwuimn03cvh3" path="res://addons/rokojori_action_library/Runtime/UI/Nodes/UIImageTypes/RoundedRectangleUIImageType.cs" id="3_uxf5k"] +[ext_resource type="Script" uid="uid://dwuimn03cvh3" path="res://addons/rokojori_action_library/Runtime/UI/Nodes/Image/UIImageTypes/RoundedRectangleUIImageType.cs" id="3_uxf5k"] [sub_resource type="Resource" id="Resource_yp323"] script = ExtResource("1_4fcac") diff --git a/Tools/Messages/Message.tscn b/Tools/Messages/Message.tscn index 21a8073..6a8e792 100644 --- a/Tools/Messages/Message.tscn +++ b/Tools/Messages/Message.tscn @@ -9,14 +9,14 @@ [ext_resource type="Script" uid="uid://dlu21piejg7w0" path="res://addons/rokojori_action_library/Runtime/UI/Shaders/RoundedRectangle/RoundedRectangleMaterial.cs" id="6_wmt7q"] [ext_resource type="Shader" uid="uid://x1a008jxt3ej" path="res://addons/rokojori_action_library/Runtime/UI/Shaders/RoundedRectangle/RoundedRectangle.gdshader" id="7_aeebn"] [ext_resource type="Script" uid="uid://bvaltw071whox" path="res://addons/rokojori_action_library/Tools/Messages/Message.cs" id="7_wmt7q"] -[ext_resource type="Script" uid="uid://bx0bk663u3hj5" path="res://addons/rokojori_action_library/Runtime/UI/Nodes/UIImage.cs" id="8_gyhi8"] +[ext_resource type="Script" uid="uid://bx0bk663u3hj5" path="res://addons/rokojori_action_library/Runtime/UI/Nodes/Image/UIImage.cs" id="8_gyhi8"] [ext_resource type="Resource" uid="uid://bliw5flmiq30c" path="res://addons/rokojori_action_library/Tools/Messages/Message Background.tres" id="9_wmt7q"] [ext_resource type="Script" uid="uid://y2p0r8c5rs45" path="res://addons/rokojori_action_library/Runtime/Shading/Properties/ColorPropertyName.cs" id="10_btdid"] [ext_resource type="Script" uid="uid://f7s137m6egkj" path="res://addons/rokojori_action_library/Runtime/UI/ShaderProperties/ShaderUIColor.cs" id="11_x3h2c"] [ext_resource type="Script" uid="uid://jqgdm3r2u8xq" path="res://addons/rokojori_action_library/Runtime/Shading/Properties/FloatPropertyName.cs" id="12_xevu7"] [ext_resource type="Script" uid="uid://j3mk8vwv56ui" path="res://addons/rokojori_action_library/Runtime/UI/ShaderProperties/ShaderUINumber.cs" id="13_1jemv"] -[ext_resource type="Script" uid="uid://ce5eo6r5jqilt" path="res://addons/rokojori_action_library/Runtime/UI/Nodes/UIImageTypes/UIImageType.cs" id="14_1hp7s"] -[ext_resource type="SystemFont" uid="uid://s1pi67tbxu24" path="res://3rdPerson/Inputs/Jost-Font.tres" id="15_nro64"] +[ext_resource type="Script" uid="uid://ce5eo6r5jqilt" path="res://addons/rokojori_action_library/Runtime/UI/Nodes/Image/UIImageTypes/UIImageType.cs" id="14_1hp7s"] +[ext_resource type="SystemFont" path="res://3rdPerson/Inputs/Jost-Font.tres" id="15_nro64"] [ext_resource type="Script" uid="uid://rqs2m0u6yvvf" path="res://addons/rokojori_action_library/Runtime/UI/Nodes/UIText.cs" id="16_0e03u"] [ext_resource type="Resource" uid="uid://c0hm8flp73453" path="res://addons/rokojori_action_library/Tools/Messages/Message Icon.tres" id="16_1tota"] [ext_resource type="Script" uid="uid://bvj322mokkq63" path="res://addons/rokojori_action_library/Runtime/Localization/LocaleText.cs" id="17_illef"] @@ -29,7 +29,7 @@ [ext_resource type="Resource" uid="uid://bilueedl68o8b" path="res://addons/rokojori_action_library/Tools/Messages/Message Time Stamp.tres" id="24_jm3cb"] [ext_resource type="Resource" uid="uid://3l4054xmleyf" path="res://addons/rokojori_action_library/Tools/Messages/Message Resource Link.tres" id="27_gyhi8"] [ext_resource type="Resource" uid="uid://c4x06404fxbq2" path="res://addons/rokojori_action_library/Tools/Messages/Message Web Link.tres" id="28_jm3cb"] -[ext_resource type="Script" uid="uid://dwuimn03cvh3" path="res://addons/rokojori_action_library/Runtime/UI/Nodes/UIImageTypes/RoundedRectangleUIImageType.cs" id="30_btdid"] +[ext_resource type="Script" uid="uid://dwuimn03cvh3" path="res://addons/rokojori_action_library/Runtime/UI/Nodes/Image/UIImageTypes/RoundedRectangleUIImageType.cs" id="30_btdid"] [sub_resource type="Resource" id="Resource_8aipl"] script = ExtResource("2_3bqvc") diff --git a/Tools/Messages/Messages.tscn b/Tools/Messages/Messages.tscn index 33e2c54..9ae12b6 100644 --- a/Tools/Messages/Messages.tscn +++ b/Tools/Messages/Messages.tscn @@ -9,15 +9,15 @@ [ext_resource type="Script" uid="uid://drqb0pm5ub64g" path="res://addons/rokojori_action_library/Runtime/UI/Styling/UIColor.cs" id="6_j2i2l"] [ext_resource type="Script" uid="uid://dlu21piejg7w0" path="res://addons/rokojori_action_library/Runtime/UI/Shaders/RoundedRectangle/RoundedRectangleMaterial.cs" id="9_a81dy"] [ext_resource type="Shader" uid="uid://x1a008jxt3ej" path="res://addons/rokojori_action_library/Runtime/UI/Shaders/RoundedRectangle/RoundedRectangle.gdshader" id="10_fbdhv"] -[ext_resource type="Script" uid="uid://dwuimn03cvh3" path="res://addons/rokojori_action_library/Runtime/UI/Nodes/UIImageTypes/RoundedRectangleUIImageType.cs" id="12_8waa8"] -[ext_resource type="Script" uid="uid://bx0bk663u3hj5" path="res://addons/rokojori_action_library/Runtime/UI/Nodes/UIImage.cs" id="12_kfok7"] +[ext_resource type="Script" uid="uid://dwuimn03cvh3" path="res://addons/rokojori_action_library/Runtime/UI/Nodes/Image/UIImageTypes/RoundedRectangleUIImageType.cs" id="12_8waa8"] +[ext_resource type="Script" uid="uid://bx0bk663u3hj5" path="res://addons/rokojori_action_library/Runtime/UI/Nodes/Image/UIImage.cs" id="12_kfok7"] [ext_resource type="Script" uid="uid://y2p0r8c5rs45" path="res://addons/rokojori_action_library/Runtime/Shading/Properties/ColorPropertyName.cs" id="14_pugir"] [ext_resource type="Script" uid="uid://f7s137m6egkj" path="res://addons/rokojori_action_library/Runtime/UI/ShaderProperties/ShaderUIColor.cs" id="15_ojjyv"] [ext_resource type="Script" uid="uid://jqgdm3r2u8xq" path="res://addons/rokojori_action_library/Runtime/Shading/Properties/FloatPropertyName.cs" id="16_bjurn"] [ext_resource type="Script" uid="uid://j3mk8vwv56ui" path="res://addons/rokojori_action_library/Runtime/UI/ShaderProperties/ShaderUINumber.cs" id="17_pyi7r"] [ext_resource type="Script" uid="uid://3bymmno3avag" path="res://addons/rokojori_action_library/Runtime/UI/Transitions/TransitionSettingsAll.cs" id="22_fbdhv"] [ext_resource type="Resource" uid="uid://vbvri2ltruat" path="res://addons/rokojori_action_library/Tools/Messages/Vertical-Slider.tres" id="24_8aipl"] -[ext_resource type="Script" uid="uid://btwjt483gljv7" path="res://addons/rokojori_action_library/Runtime/UI/Components/UISlider.cs" id="25_8waa8"] +[ext_resource type="Script" uid="uid://btwjt483gljv7" path="res://addons/rokojori_action_library/Runtime/UI/Components/OldUISlider.cs" id="25_8waa8"] [ext_resource type="Script" uid="uid://lhuuedx87rem" path="res://addons/rokojori_action_library/Runtime/Animation/Smoothing/FrameSmoothing.cs" id="26_pugir"] [sub_resource type="Resource" id="Resource_bjurn"]