diff --git a/Icons/RemoveVirtualCamera3D.svg b/Icons/RemoveVirtualCamera3D.svg new file mode 100644 index 0000000..cac7800 --- /dev/null +++ b/Icons/RemoveVirtualCamera3D.svg @@ -0,0 +1,97 @@ + + diff --git a/Icons/RemoveVirtualCamera3D.svg.import b/Icons/RemoveVirtualCamera3D.svg.import new file mode 100644 index 0000000..c2ed1a8 --- /dev/null +++ b/Icons/RemoveVirtualCamera3D.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://beh11ebwsi3nj" +path="res://.godot/imported/RemoveVirtualCamera3D.svg-b229129ca4dd411d22a781c703e04259.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/rokojori_action_library/Icons/RemoveVirtualCamera3D.svg" +dest_files=["res://.godot/imported/RemoveVirtualCamera3D.svg-b229129ca4dd411d22a781c703e04259.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/Icons/SetActiveVirtualCamera3D.svg b/Icons/SetActiveVirtualCamera3D.svg new file mode 100644 index 0000000..8f78ce1 --- /dev/null +++ b/Icons/SetActiveVirtualCamera3D.svg @@ -0,0 +1,101 @@ + + diff --git a/Icons/SetActiveVirtualCamera3D.svg.import b/Icons/SetActiveVirtualCamera3D.svg.import new file mode 100644 index 0000000..df7cdda --- /dev/null +++ b/Icons/SetActiveVirtualCamera3D.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cwtmomxhbrhh4" +path="res://.godot/imported/SetActiveVirtualCamera3D.svg-daa089c09a78ae1c001e1e1ec4c40af0.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/rokojori_action_library/Icons/SetActiveVirtualCamera3D.svg" +dest_files=["res://.godot/imported/SetActiveVirtualCamera3D.svg-daa089c09a78ae1c001e1e1ec4c40af0.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/Icons/VirtualCamera3D.svg b/Icons/VirtualCamera3D.svg index a254aa7..d9e08cb 100644 --- a/Icons/VirtualCamera3D.svg +++ b/Icons/VirtualCamera3D.svg @@ -66,8 +66,8 @@ inkscape:deskcolor="#505050" showgrid="false" inkscape:zoom="22.627418" - inkscape:cx="8.1538247" - inkscape:cy="2.320194" + inkscape:cx="12.308077" + inkscape:cy="11.203223" inkscape:window-width="1920" inkscape:window-height="1017" inkscape:window-x="-8" @@ -76,7 +76,7 @@ inkscape:current-layer="g2210" /> + style="fill:#f78500;fill-opacity:1;stroke:none;stroke-width:1.72262;stroke-opacity:1" /> diff --git a/Runtime/Actions/ActionReference.cs b/Runtime/Actions/ActionReference.cs index a60de5d..4abb6f6 100644 --- a/Runtime/Actions/ActionReference.cs +++ b/Runtime/Actions/ActionReference.cs @@ -4,7 +4,7 @@ using Godot; namespace Rokojori { - [GlobalClass ] + [Tool][GlobalClass ] public partial class ActionReference : Action { [Export] diff --git a/Runtime/Actions/Conditional/Once.cs b/Runtime/Actions/Conditional/Once.cs new file mode 100644 index 0000000..de5c2c1 --- /dev/null +++ b/Runtime/Actions/Conditional/Once.cs @@ -0,0 +1,30 @@ + +using Godot; +using System.Collections.Generic; + + +namespace Rokojori +{ + [Tool] + [GlobalClass, Icon("res://addons/rokojori_action_library/Icons/ConditionalAction.svg")] + public partial class Once : Action + { + [Export] + public Action action; + + [Export] + public bool canTrigger = true; + + protected override void _OnTrigger() + { + if ( ! canTrigger ) + { + return; + } + + canTrigger = false; + Action.Trigger( action ); + + } + } +} \ No newline at end of file diff --git a/Runtime/Actions/Conditional/Once.cs.uid b/Runtime/Actions/Conditional/Once.cs.uid new file mode 100644 index 0000000..a209203 --- /dev/null +++ b/Runtime/Actions/Conditional/Once.cs.uid @@ -0,0 +1 @@ +uid://crm7o7w0gumhn diff --git a/Runtime/Actions/IterateActions.cs b/Runtime/Actions/IterateActions.cs index 813a11d..1192fc3 100644 --- a/Runtime/Actions/IterateActions.cs +++ b/Runtime/Actions/IterateActions.cs @@ -4,7 +4,7 @@ using Godot; namespace Rokojori { - [GlobalClass ] + [Tool][GlobalClass ] public partial class IterateActions : Action { [ExportGroup( "Read Only")] diff --git a/Runtime/Actions/LoadScene.cs b/Runtime/Actions/LoadScene.cs index be40cc5..b34dfcd 100644 --- a/Runtime/Actions/LoadScene.cs +++ b/Runtime/Actions/LoadScene.cs @@ -4,7 +4,7 @@ using System.Collections.Generic; namespace Rokojori { - [GlobalClass] + [Tool][GlobalClass] public partial class LoadScene : SequenceAction { [Export] diff --git a/Runtime/Actions/Node/SetNodeState.cs b/Runtime/Actions/Node/SetNodeState.cs index 93e5743..8a067ce 100644 --- a/Runtime/Actions/Node/SetNodeState.cs +++ b/Runtime/Actions/Node/SetNodeState.cs @@ -4,7 +4,7 @@ using Godot; namespace Rokojori { - [GlobalClass ] + [Tool][GlobalClass ] public partial class SetNodeState : Action { [Export] diff --git a/Runtime/Actions/Node3D/CopyMousePosition.cs b/Runtime/Actions/Node3D/CopyMousePosition.cs index 903a479..d474a4b 100644 --- a/Runtime/Actions/Node3D/CopyMousePosition.cs +++ b/Runtime/Actions/Node3D/CopyMousePosition.cs @@ -4,7 +4,7 @@ using Godot; namespace Rokojori { - [GlobalClass ] + [Tool][GlobalClass ] public partial class CopyMousePosition : Action { [Export] diff --git a/Runtime/Actions/Node3D/CopyPose.cs b/Runtime/Actions/Node3D/CopyPose.cs index ef40782..0e560a4 100644 --- a/Runtime/Actions/Node3D/CopyPose.cs +++ b/Runtime/Actions/Node3D/CopyPose.cs @@ -4,7 +4,7 @@ using Godot; namespace Rokojori { - [GlobalClass, Tool ] + [Tool][GlobalClass ] public partial class CopyPose : Action { [Export] diff --git a/Runtime/Actions/Node3D/LerpPosition.cs b/Runtime/Actions/Node3D/LerpPosition.cs index 14df5b6..ace1046 100644 --- a/Runtime/Actions/Node3D/LerpPosition.cs +++ b/Runtime/Actions/Node3D/LerpPosition.cs @@ -3,7 +3,7 @@ using Godot; namespace Rokojori { - [GlobalClass ] + [Tool][GlobalClass ] public partial class LerpPosition : Action { [Export] diff --git a/Runtime/Actions/Node3D/PlayParticles.cs b/Runtime/Actions/Node3D/PlayParticles.cs index 67c93af..9f4a46b 100644 --- a/Runtime/Actions/Node3D/PlayParticles.cs +++ b/Runtime/Actions/Node3D/PlayParticles.cs @@ -3,7 +3,7 @@ using Godot; namespace Rokojori { - [GlobalClass] + [Tool][GlobalClass] public partial class PlayParticles:Action { [Export] diff --git a/Runtime/Actions/Node3D/PlaySound.cs b/Runtime/Actions/Node3D/PlaySound.cs index 212fee9..5196fd3 100644 --- a/Runtime/Actions/Node3D/PlaySound.cs +++ b/Runtime/Actions/Node3D/PlaySound.cs @@ -3,7 +3,7 @@ using Godot; namespace Rokojori { - [GlobalClass] + [Tool][GlobalClass] public partial class PlaySound:Action { [Export] diff --git a/Runtime/Actions/OnPhysicsProcess.cs b/Runtime/Actions/OnPhysicsProcess.cs index 9340f2e..715522c 100644 --- a/Runtime/Actions/OnPhysicsProcess.cs +++ b/Runtime/Actions/OnPhysicsProcess.cs @@ -4,7 +4,7 @@ using Godot; namespace Rokojori { - [GlobalClass, Icon("res://addons/rokojori_action_library/Icons/OnEvent.svg") ] + [Tool][GlobalClass, Icon("res://addons/rokojori_action_library/Icons/OnEvent.svg") ] public partial class OnPhysicsProcess : Node { /** Actions to execute*/ diff --git a/Runtime/Actions/OnReady.cs b/Runtime/Actions/OnReady.cs index 28fe0c1..5d2194b 100644 --- a/Runtime/Actions/OnReady.cs +++ b/Runtime/Actions/OnReady.cs @@ -4,7 +4,7 @@ using Godot; namespace Rokojori { - [GlobalClass, Icon("res://addons/rokojori_action_library/Icons/OnEvent.svg") ] + [Tool][GlobalClass, Icon("res://addons/rokojori_action_library/Icons/OnEvent.svg") ] public partial class OnReady : Node { /** Actions to execute*/ diff --git a/Runtime/Actions/Sequence/Parallel.cs b/Runtime/Actions/Sequence/Parallel.cs index 148eb94..0b49668 100644 --- a/Runtime/Actions/Sequence/Parallel.cs +++ b/Runtime/Actions/Sequence/Parallel.cs @@ -4,7 +4,7 @@ using System.Collections.Generic; namespace Rokojori { - [GlobalClass, Icon("res://addons/rokojori_action_library/Icons/Parallel.svg") ] + [Tool][GlobalClass, Icon("res://addons/rokojori_action_library/Icons/Parallel.svg") ] public partial class Parallel : SequenceAction { public enum Mode diff --git a/Runtime/Actions/Sequence/RepeatSequence.cs b/Runtime/Actions/Sequence/RepeatSequence.cs new file mode 100644 index 0000000..ca60e05 --- /dev/null +++ b/Runtime/Actions/Sequence/RepeatSequence.cs @@ -0,0 +1,87 @@ + +using Godot; +using System.Collections.Generic; + +namespace Rokojori +{ + [Tool][GlobalClass, Icon("res://addons/rokojori_action_library/Icons/Parallel.svg") ] + public partial class RepeatSequence : SequenceAction + { + [Export] + public Action action; + + + [Export] + public int maxNumRepeats = 3; + + [Export] + public float maxRepeatDuration = 60; + + [Export] + public TimeLine timeLine; + + + protected override void _OnTrigger() + { + + var id = DispatchStart(); + + if ( ! ( action is SequenceAction ) ) + { + Trigger( action ); + DispatchEnd( id ); + return; + } + + var sa = (SequenceAction) action; + + var executed = 0; + + System.Action callBack = null; + + var tl = TimeLineManager.Ensure( timeLine ); + + if ( maxNumRepeats <= 0 && ( tl == null || maxRepeatDuration <= 0 ) ) + { + return; + } + + var startTime = tl.position; + var endTime = tl.position + maxRepeatDuration; + + callBack = ( a )=> + { + if ( ! a.success ) + { + DispatchCancelled( id ); + sa.onSequenceDone.RemoveAction( callBack ); + return; + } + + executed ++; + + var finished = ( maxNumRepeats > 0 && executed >= maxNumRepeats ) || + ( tl != null && tl.position >= endTime ); + + if ( finished ) + { + DispatchEnd( id ); + sa.onSequenceDone.RemoveAction( callBack ); + return; + } + else + { + Trigger( action ); + } + + }; + + + sa.onSequenceDone.AddAction( callBack ); + + + Trigger( action ); + + } + } +} \ No newline at end of file diff --git a/Runtime/Actions/Sequence/RepeatSequence.cs.uid b/Runtime/Actions/Sequence/RepeatSequence.cs.uid new file mode 100644 index 0000000..a33483e --- /dev/null +++ b/Runtime/Actions/Sequence/RepeatSequence.cs.uid @@ -0,0 +1 @@ +uid://j41ppn275x8i diff --git a/Runtime/Actions/Time/Delay.cs b/Runtime/Actions/Time/Delay.cs index b2a5cb1..d50e47b 100644 --- a/Runtime/Actions/Time/Delay.cs +++ b/Runtime/Actions/Time/Delay.cs @@ -4,7 +4,7 @@ using Godot; namespace Rokojori { - [GlobalClass] + [Tool][GlobalClass] public partial class Delay : SequenceAction { [Export] diff --git a/Runtime/Actions/Time/TweenTimeLineSpeed.cs b/Runtime/Actions/Time/TweenTimeLineSpeed.cs new file mode 100644 index 0000000..d51e1f7 --- /dev/null +++ b/Runtime/Actions/Time/TweenTimeLineSpeed.cs @@ -0,0 +1,77 @@ + +using System; +using Godot; + + +namespace Rokojori +{ + [Tool] + [GlobalClass ] + public partial class TweenTimeLineSpeed:SequenceAction + { + [Export] + public TimeLine targetTimeLine; + + [Export] + public float timeLineSpeed; + + [Export] + public TweenType tweenType = new TweenTimeCurve(); + + [Export] + public bool cacheSpeedOnStart = true; + + [Export] + public TimeLine tweenTimeLine; + + protected override void _OnTrigger() + { + if ( targetTimeLine == null ) + { + return; + } + + var tl = tweenTimeLine == null ? TimeLineManager.Get().realtimeTimeline : tweenTimeLine; + + var start = targetTimeLine.position; + + var fromSpeed = targetTimeLine.runner.speed; + var toSpeed = timeLineSpeed; + + + var sequenceID = DispatchStart(); + + var tweenType = this.tweenType; + + if ( tweenType == null ) + { + tweenType = TweenTimeCurve.defaultCurve; + } + + TimeLineManager.ScheduleSpanIn( tl, 0, tweenType.GetTweenDuration(), + ( span, type )=> + { + var timeNow = tl.position; + var elapsed = timeNow - start; + + var state = tweenType.GetTweenPhaseForPhase( span.phase ); + + if ( ! cacheSpeedOnStart ) + { + toSpeed = timeLineSpeed; + } + + var lerpedSpeed = Mathf.Lerp( fromSpeed, toSpeed, state ); + + targetTimeLine.runner.speed = lerpedSpeed; + + if ( type == TimeLineSpanUpdateType.End ) + { + DispatchEnd( sequenceID ); + } + } + ); + } + + } +} \ No newline at end of file diff --git a/Runtime/Actions/Time/TweenTimeLineSpeed.cs.uid b/Runtime/Actions/Time/TweenTimeLineSpeed.cs.uid new file mode 100644 index 0000000..76b62a4 --- /dev/null +++ b/Runtime/Actions/Time/TweenTimeLineSpeed.cs.uid @@ -0,0 +1 @@ +uid://b33s5utxleah2 diff --git a/Runtime/Actions/Visual/TweenParticles.cs b/Runtime/Actions/Visual/TweenParticles.cs new file mode 100644 index 0000000..7e08917 --- /dev/null +++ b/Runtime/Actions/Visual/TweenParticles.cs @@ -0,0 +1,70 @@ + +using System; +using Godot; + + +namespace Rokojori +{ + [Tool] + [GlobalClass ] + public partial class TweenParticles:SequenceAction + { + [Export] + public GpuParticles3D particles3D; + + [Export] + public TweenParticlesData tweenParticlesData; + + [Export] + public TweenType tweenType = new TweenTimeCurve(); + + [Export] + public TimeLine timeLine; + + + protected override void _OnTrigger() + { + if ( particles3D == null ) + { + return; + } + + var tl = TimeLineManager.Ensure( timeLine ); + + var start = tl.position; + + var fromData = new TweenParticlesData(); + fromData.CopyFrom( particles3D ); + var lerpData = tweenParticlesData.Clone( true ); + + var sequenceID = DispatchStart(); + + var tweenType = this.tweenType; + + if ( tweenType == null ) + { + tweenType = TweenTimeCurve.defaultCurve; + } + + TimeLineManager.ScheduleSpanIn( tl, 0, tweenType.GetTweenDuration(), + ( span, type )=> + { + var timeNow = tl.position; + var elapsed = timeNow - start; + + var state = tweenType.GetTweenPhaseForPhase( span.phase ); + + TweenParticlesData.LerpTo( fromData, tweenParticlesData, state, lerpData ); + + lerpData.CopyTo( particles3D ); + + if ( type == TimeLineSpanUpdateType.End ) + { + DispatchEnd( sequenceID ); + } + } + ); + } + + } +} \ No newline at end of file diff --git a/Runtime/Actions/Visual/TweenParticles.cs.uid b/Runtime/Actions/Visual/TweenParticles.cs.uid new file mode 100644 index 0000000..7757eea --- /dev/null +++ b/Runtime/Actions/Visual/TweenParticles.cs.uid @@ -0,0 +1 @@ +uid://seym2gxpvk7j diff --git a/Runtime/Actions/Visual/TweenParticlesData.cs b/Runtime/Actions/Visual/TweenParticlesData.cs new file mode 100644 index 0000000..cf6c36f --- /dev/null +++ b/Runtime/Actions/Visual/TweenParticlesData.cs @@ -0,0 +1,120 @@ +using System; +using Godot; + + +namespace Rokojori +{ + [Tool] + [GlobalClass ] + public partial class TweenParticlesData:Resource + { + + [Export] + public FloatValue amount; + + [Export] + public FloatValue amountRatio; + + [ExportGroup("Time")] + [Export] + public FloatValue lifeTime; + + [Export] + public FloatValue speedScale; + + [Export] + public FloatValue explosiveness; + + [Export] + public FloatValue randomness; + + + public virtual TweenParticlesData Clone( bool deepClone ) + { + var clone = new TweenParticlesData(); + + clone.amount = FloatValue.Clone( amount, deepClone ); + clone.amountRatio = FloatValue.Clone( amountRatio, deepClone ); + clone.lifeTime = FloatValue.Clone( lifeTime, deepClone ); + + clone.speedScale = FloatValue.Clone( speedScale, deepClone ); + clone.explosiveness = FloatValue.Clone( explosiveness, deepClone ); + clone.randomness = FloatValue.Clone( randomness, deepClone ); + + return clone; + + } + + public virtual void CopyFrom( GpuParticles3D particles ) + { + amount = FloatValue.Create( particles.Amount ); + amountRatio = FloatValue.Create( particles.AmountRatio ); + lifeTime = FloatValue.Create( particles.Lifetime ); + + speedScale = FloatValue.Create( particles.SpeedScale ); + explosiveness = FloatValue.Create( particles.Explosiveness ); + randomness = FloatValue.Create( particles.Randomness ); + } + + + public virtual void CopyFrom( TweenParticlesData tweenLightData ) + { + amount = tweenLightData.amount; + amountRatio = tweenLightData.amountRatio; + lifeTime = tweenLightData.lifeTime; + + speedScale = tweenLightData.speedScale; + explosiveness = tweenLightData.explosiveness; + randomness = tweenLightData.randomness; + } + + public virtual void CopyTo( GpuParticles3D particles ) + { + if ( amount != null ) + { + particles.Amount = Mathf.RoundToInt( amount.value ); + + } + + if ( amountRatio != null ) + { + particles.AmountRatio = amountRatio.value; + particles.Emitting = amountRatio.value > 0; + } + + if ( lifeTime != null ) + { + particles.Lifetime = lifeTime.value; + } + + + if ( speedScale != null ) + { + particles.SpeedScale = speedScale.value; + } + + if ( explosiveness != null ) + { + particles.Explosiveness = explosiveness.value; + } + + if ( randomness != null ) + { + particles.Randomness = randomness.value; + } + + } + + public static void LerpTo( TweenParticlesData a, TweenParticlesData b, float lerpAmount, TweenParticlesData output ) + { + FloatValue.Lerp( a.amount, b.amount, lerpAmount, output.amount ); + FloatValue.Lerp( a.amountRatio, b.amountRatio, lerpAmount, output.amountRatio ); + FloatValue.Lerp( a.lifeTime, b.lifeTime, lerpAmount, output.lifeTime ); + + FloatValue.Lerp( a.speedScale, b.speedScale, lerpAmount, output.speedScale ); + FloatValue.Lerp( a.explosiveness, b.explosiveness, lerpAmount, output.explosiveness ); + FloatValue.Lerp( a.randomness, b.randomness, lerpAmount, output.randomness ); + } + + } +} \ No newline at end of file diff --git a/Runtime/Actions/Visual/TweenParticlesData.cs.uid b/Runtime/Actions/Visual/TweenParticlesData.cs.uid new file mode 100644 index 0000000..56e4c0b --- /dev/null +++ b/Runtime/Actions/Visual/TweenParticlesData.cs.uid @@ -0,0 +1 @@ +uid://bvrtvo7tdhft6 diff --git a/Runtime/Actions/Visual/TweenPosition.cs b/Runtime/Actions/Visual/TweenPosition.cs new file mode 100644 index 0000000..7926e85 --- /dev/null +++ b/Runtime/Actions/Visual/TweenPosition.cs @@ -0,0 +1,91 @@ + +using System; +using Godot; + + +namespace Rokojori +{ + [Tool] + [GlobalClass ] + public partial class TweenPosition:SequenceAction + { + [Export] + public Node3D target; + + [Export] + public Node3D endPosition; + + [Export] + public Vector3 endOffset; + + [Export] + public TweenType tweenType = new TweenTimeCurve(); + + + [Export] + public bool cacheEndPositionOnStart = true; + + [Export] + public TimeLine timeLine; + + + protected override void _OnTrigger() + { + if ( target == null ) + { + return; + } + + var tl = TimeLineManager.Ensure( timeLine ); + + var start = tl.position; + + var fromPosition = target.GlobalPosition; + var toPosition = endOffset; + + if ( endPosition != null ) + { + toPosition += endPosition.GlobalPosition; + } + + var sequenceID = DispatchStart(); + + var tweenType = this.tweenType; + + if ( tweenType == null ) + { + tweenType = TweenTimeCurve.defaultCurve; + } + + TimeLineManager.ScheduleSpanIn( tl, 0, tweenType.GetTweenDuration(), + ( span, type )=> + { + var timeNow = tl.position; + var elapsed = timeNow - start; + + var state = tweenType.GetTweenPhaseForPhase( span.phase ); + + if ( ! cacheEndPositionOnStart ) + { + toPosition = endOffset; + + if ( endPosition != null ) + { + toPosition += endPosition.GlobalPosition; + } + } + + var lerpedPosition = fromPosition.Lerp( toPosition, state ); + + target.GlobalPosition = lerpedPosition; + + if ( type == TimeLineSpanUpdateType.End ) + { + DispatchEnd( sequenceID ); + } + } + ); + } + + } +} \ No newline at end of file diff --git a/Runtime/Actions/Visual/TweenPosition.cs.uid b/Runtime/Actions/Visual/TweenPosition.cs.uid new file mode 100644 index 0000000..41f3ae2 --- /dev/null +++ b/Runtime/Actions/Visual/TweenPosition.cs.uid @@ -0,0 +1 @@ +uid://n4etptbiekhq diff --git a/Runtime/Animation/Tweens/TweenType.cs b/Runtime/Animation/Tweens/TweenType.cs index eac6f28..b0a7d9b 100644 --- a/Runtime/Animation/Tweens/TweenType.cs +++ b/Runtime/Animation/Tweens/TweenType.cs @@ -8,6 +8,11 @@ namespace Rokojori [GlobalClass ] public partial class TweenType : Resource { + public virtual void SetFromAndTo( object a, object b ) + { + + } + public virtual float GetTweenDuration() { return 0.5f; diff --git a/Runtime/Audio/AudioGraph/Test/SineWaveTest.cs b/Runtime/Audio/AudioGraph/Test/SineWaveTest.cs index 2e3ac9c..0f5afbe 100644 --- a/Runtime/Audio/AudioGraph/Test/SineWaveTest.cs +++ b/Runtime/Audio/AudioGraph/Test/SineWaveTest.cs @@ -5,7 +5,7 @@ using System.Text; namespace Rokojori { - [GlobalClass] + [Tool][GlobalClass] public partial class SineWaveTest: Node { [Export] diff --git a/Runtime/Bits/Bytes.cs b/Runtime/Bits/Bytes.cs index 0b1b006..6b7ee67 100644 --- a/Runtime/Bits/Bytes.cs +++ b/Runtime/Bits/Bytes.cs @@ -66,5 +66,20 @@ namespace Rokojori ints.ForEach( i => list.AddRange( BitConverter.GetBytes( i ) ) ); return list; } + + public static List Convert( List v ) + { + var list = new List(); + v.ForEach( + f => + { + list.AddRange( BitConverter.GetBytes( f.X ) ); + list.AddRange( BitConverter.GetBytes( f.Y ) ); + list.AddRange( BitConverter.GetBytes( f.Z ) ); + list.AddRange( BitConverter.GetBytes( f.W ) ); + } + ); + return list; + } } } \ No newline at end of file diff --git a/Runtime/Colors/ColorX.cs b/Runtime/Colors/ColorX.cs index 261964a..100dddf 100644 --- a/Runtime/Colors/ColorX.cs +++ b/Runtime/Colors/ColorX.cs @@ -1,9 +1,47 @@ using Godot; +using System.Collections.Generic; namespace Rokojori { public static class ColorX { + public static Color From( List floats, float basis = 1.0f ) + { + if ( floats.Count == 1 ) + { + var grey = floats[ 0 ] / basis; + return new Color( grey, grey, grey, 1 ); + } + + if ( floats.Count == 2 ) + { + var grey = floats[ 0 ] / basis; + var alpha = floats[ 1 ] / basis; + return new Color( grey, grey, grey, alpha ); + } + + if ( floats.Count == 3 ) + { + var r = floats[ 0 ] / basis; + var g = floats[ 1 ] / basis; + var b = floats[ 2 ] / basis; + + return new Color( r, g, b, 1 ); + } + + if ( floats.Count == 4 ) + { + var r = floats[ 0 ] / basis; + var g = floats[ 1 ] / basis; + var b = floats[ 2 ] / basis; + var alpha = floats[ 3 ] / basis; + + return new Color( r, g, b, alpha ); + } + + return new Color( 0, 0, 0, 0 ); + } + public static Color UnblendBlack( this Color c, float treshold = 0 ) { if ( c.A <= treshold ) @@ -62,6 +100,83 @@ namespace Rokojori return color.Gamma( 2.2f ); } + public static Vector3 ToVector3( this Color color ) + { + return new Vector3( color.R, color.G, color.B ); + } + + public static Vector4 ToVector4( this Color color ) + { + return new Vector4( color.R, color.G, color.B, color.A ); + } + + public static Color ToColor( this Vector4 color ) + { + return new Color( color.X, color.Y, color.Z, color.W ); + } + + public static Color ToColor( this Vector3 color ) + { + return new Color( color.X, color.Y, color.Z, 1f ); + } + + public static Color ToColor( this Vector3 vec, float alpha = 1 ) + { + return new Color( vec.X, vec.Y, vec.Z, alpha); + } + + public static Color ToColor( this Vector2 vec, float b = 0, float alpha = 1 ) + { + return new Color( vec.X, vec.Y, b, alpha); + } + + public enum EdgeMode + { + Clamp, + Repeat, + TransparentBlack, + } + + + public static Color GetPixel( this Image image, int x, int y, EdgeMode mode ) + { + if ( x < 0 || y < 0 || x >= image.GetSize().X || y >= image.GetSize().Y ) + { + if ( mode == EdgeMode.TransparentBlack ) + { + return new Color( 0, 0, 0, 0 ); + } + + if ( mode == EdgeMode.Repeat ) + { + x = MathX.Repeat( x, image.GetSize().X ); + y = MathX.Repeat( y, image.GetSize().Y ); + } + + if ( mode == EdgeMode.Clamp ) + { + x = Mathf.Clamp( x, 0, image.GetSize().X ); + y = Mathf.Clamp( y, 0, image.GetSize().Y ); + } + } + + return image.GetPixel( x, y ); + } + + + public static Color Sample( this Image image, Vector2 uv, EdgeMode mode ) + { + var pixelUV = uv * image.GetSize(); + var lowUV = pixelUV.FloorToInt().Max( 0 ); + var highUV = ( lowUV + Vector2I.One ).Min( image.GetSize() - Vector2I.One ); + + var mix = pixelUV - lowUV; + + var xTop = Lerp( image.GetPixel( lowUV.X, lowUV.Y, mode ), image.GetPixel( highUV.X, lowUV.Y, mode ), mix.X ); + var xLow = Lerp( image.GetPixel( highUV.X, lowUV.Y, mode ), image.GetPixel( highUV.X, highUV.Y, mode ), mix.X ); + + return Lerp( xTop, xLow, mix.Y ); + } public static Color Blend( Color bottom, Color top ) { @@ -151,10 +266,10 @@ namespace Rokojori public static Color BlendColor( Color bottom, Color top ) { - var hslA = HSLColor.FromRGBA( bottom ); - var hslB = HSLColor.FromRGBA( top ); + var hslBottom = HSLColor.FromRGBA( bottom ); + var hslTop = HSLColor.FromRGBA( top ); - var combined = bottom.A == 0 ? bottom : (Color)( new HSLColor( hslB.h, hslB.s, hslA.l, top.A ) ); + var combined = bottom.A == 0 ? bottom : (Color)( new HSLColor( hslTop.h, hslTop.s, hslBottom.l, top.A ) ); return ColorX.Blend( bottom, combined ); } @@ -211,11 +326,6 @@ namespace Rokojori return new Color( rgb.X, rgb.Y, rgb.Z, a ); } - public static Vector4 ToVector4( Color c ) - { - return new Vector4( c.R, c.G, c.B, c.A ); - } - public static Color FromVector4( Vector4 c ) { return new Color( c.X, c.Y, c.Z, c.W ); diff --git a/Runtime/Colors/HSLColor.cs b/Runtime/Colors/HSLColor.cs index 6145329..13184b6 100644 --- a/Runtime/Colors/HSLColor.cs +++ b/Runtime/Colors/HSLColor.cs @@ -81,8 +81,11 @@ namespace Rokojori public static HSLColor FromRGBA( Color c ) { - float h, s, l, a; - a = c.A; + float h = 0; + float s = 0; + float l = 0; + float a = c.A; + float cmin = Mathf.Min( Mathf.Min( c.R, c.G ), c.B ); float cmax = Mathf.Max( Mathf.Max( c.R, c.G ), c.B ); diff --git a/Runtime/Godot/Cameras.cs b/Runtime/Godot/Cameras.cs index 6db2411..22ab686 100644 --- a/Runtime/Godot/Cameras.cs +++ b/Runtime/Godot/Cameras.cs @@ -33,5 +33,87 @@ namespace Rokojori return Mathf.RadToDeg( rads ); } + public static float ComputePixelDensityVertical( float fovDegrees, float distance, Vector2 screenSize ) + { + float fovRadians = Mathf.DegToRad( fovDegrees ); + + float verticalViewSize = 2.0f * distance * Mathf.Tan( fovRadians / 2.0f ); + + float screenHeightPixels = screenSize.Y; + + float pixelDensity = screenHeightPixels / verticalViewSize; + + return pixelDensity; + } + + public static float ComputeSizeOfPixelVertical( float fovDegrees, float distance, Vector2 screenSize ) + { + return ComputePixelDensityVertical( fovDegrees, distance, screenSize ); + } + + + public static float ComputePixelDistanceForSizeVertical( float fovDegrees, float size, Vector2 screenSize ) + { + float fovRadians = Mathf.DegToRad(fovDegrees); + float screenHeightPixels = screenSize.Y; + + float pixelDensity = 1.0f / size; + + float distance = screenHeightPixels / (2.0f * pixelDensity * Mathf.Tan(fovRadians / 2.0f)); + + return distance; + + } + + public static float ComputePixelDensityHorizontal(float fovDegrees, float distance, Vector2 screenSize) + { + float aspectRatio = screenSize.X / screenSize.Y; + + float verticalFovRad = Mathf.DegToRad( fovDegrees ); + + float horizontalFovRad = 2.0f * Mathf.Atan(Mathf.Tan( verticalFovRad / 2.0f ) * aspectRatio); + + float horizontalViewSize = 2.0f * distance * Mathf.Tan( horizontalFovRad / 2.0f ); + + float pixelDensity = screenSize.X / horizontalViewSize; + + return pixelDensity; + } + + public static Vector3 GlobalToView( Transform3D transform, Vector3 globalPosition ) + { + return globalPosition * transform; + } + + public static Vector3 ViewToClip( Projection cameraProjection, Vector3 viewPosition ) + { + var clip = cameraProjection * viewPosition; + return clip; + } + + public static Vector2 ClipToScreen( Vector3 clipPosition ) + { + var size = Vector2.One; + var clip = clipPosition.XY() * 0.5f + new Vector2( 0.5f, 0.5f ); + return clip * size; + } + + public static Vector2 ClipToScreen( Vector3 clipPosition, Vector2 screenPixelSize ) + { + var clip = clipPosition.XY() * 0.5f + new Vector2( 0.5f, 0.5f ); + return clip * screenPixelSize; + } + + + public static Vector2 GlobalToScreen( Vector3 globalPosition, Transform3D cameraTransform, Projection cameraProjection, Vector2 screenPixelSize ) + { + var view = GlobalToView( cameraTransform, globalPosition ); + var clip = ViewToClip( cameraProjection, view ); + var screen = ClipToScreen( clip, screenPixelSize ); + + return screen; + } + + } } \ No newline at end of file diff --git a/Runtime/Godot/Generated/Classes/RJAnimatableBody3D.cs b/Runtime/Godot/Generated/Classes/RJAnimatableBody3D.cs index 3a81a69..4d45c19 100644 --- a/Runtime/Godot/Generated/Classes/RJAnimatableBody3D.cs +++ b/Runtime/Godot/Generated/Classes/RJAnimatableBody3D.cs @@ -3,7 +3,7 @@ using Godot; namespace Rokojori { - [GlobalClass] + [Tool][GlobalClass] public partial class RJAnimatableBody3D:AnimatableBody3D { diff --git a/Runtime/Godot/Generated/Classes/RJCharacterBody3D.cs b/Runtime/Godot/Generated/Classes/RJCharacterBody3D.cs index 103f2d2..2e2c140 100644 --- a/Runtime/Godot/Generated/Classes/RJCharacterBody3D.cs +++ b/Runtime/Godot/Generated/Classes/RJCharacterBody3D.cs @@ -3,7 +3,7 @@ using Godot; namespace Rokojori { - [GlobalClass] + [Tool][GlobalClass] public partial class RJCharacterBody3D:CharacterBody3D { diff --git a/Runtime/Godot/GodotEditorHelper.cs b/Runtime/Godot/GodotEditorHelper.cs new file mode 100644 index 0000000..9274c04 --- /dev/null +++ b/Runtime/Godot/GodotEditorHelper.cs @@ -0,0 +1,45 @@ +using Godot; +using System.Text; +using System.Collections.Generic; + +namespace Rokojori +{ + public class GodotEditorHelper + { + public static string AbsoluteToResourcePath( string path ) + { + #if TOOLS + + if ( path != null ) + { + return ProjectSettings.LocalizePath( path ); + } + + #endif + + return path; + } + + public static bool IsProjectPath( string path ) + { + return path.StartsWith( "res://" ) || path.StartsWith( "user://" ); + } + + public static void UpdateFile( string path ) + { + #if TOOLS + + if ( ! IsProjectPath( path ) ) + { + var pathBefore = path; + path = AbsoluteToResourcePath( path ); + RJLog.Log( "Converted path", pathBefore, ">>", path ); + } + + var filesystem = EditorInterface.Singleton.GetResourceFilesystem(); + filesystem.ReimportFiles( [ path ] ); + + #endif + } + } +} \ No newline at end of file diff --git a/Runtime/Godot/GodotEditorHelper.cs.uid b/Runtime/Godot/GodotEditorHelper.cs.uid new file mode 100644 index 0000000..894ba18 --- /dev/null +++ b/Runtime/Godot/GodotEditorHelper.cs.uid @@ -0,0 +1 @@ +uid://c8ypyibkyf0ms diff --git a/Runtime/Godot/Nodes.cs b/Runtime/Godot/Nodes.cs index a0900d1..67ba546 100644 --- a/Runtime/Godot/Nodes.cs +++ b/Runtime/Godot/Nodes.cs @@ -29,6 +29,18 @@ namespace Rokojori } + public static T FindSibling( this Node node, Func evaluater = null ) where T:Node + { + if ( node == null ) + { + return null; + } + + var sibling = NodesWalker.Get().FindSibling( node, n => n as T != null ); + + return sibling as T; + } + public static T Find( Node root, NodePathLocatorType type = NodePathLocatorType.DirectChildren, int parentOffset = 0 ) where T:Node { var it = root; @@ -245,6 +257,17 @@ namespace Rokojori return; } + public static double StartAsyncTimer( this Node node ) + { + return Async.StartTimer(); + } + + public static async Task WaitForAsyncTimer( this Node node, double time ) + { + time = await Async.WaitIfExceeded( time, node ); + return time; + } + public static T CreateChild( this Node parent, string name = null ) where T:Node,new() { return CreateChildIn( parent, name ); diff --git a/Runtime/Godot/NodesWalker.cs b/Runtime/Godot/NodesWalker.cs index d84a848..bac5ac6 100644 --- a/Runtime/Godot/NodesWalker.cs +++ b/Runtime/Godot/NodesWalker.cs @@ -40,5 +40,7 @@ namespace Rokojori return n.GetChildCount(); } + + } } \ No newline at end of file diff --git a/Runtime/Godot/Scenes/SceneFileReader.cs b/Runtime/Godot/Scenes/SceneFileReader.cs index 6e37257..36bd16b 100644 --- a/Runtime/Godot/Scenes/SceneFileReader.cs +++ b/Runtime/Godot/Scenes/SceneFileReader.cs @@ -12,12 +12,13 @@ namespace Rokojori [Export] public string path = ""; - [Export] - public bool load - { - get => false; - set { if ( value ) LoadScene(); } - } + [ExportToolButton( "Read" )] + public Callable ReadButton => Callable.From( + ()=> + { + LoadScene(); + } + ); [Export] public bool exportJSON = false; diff --git a/Runtime/Graphs/Trees/TreeWalker.cs b/Runtime/Graphs/Trees/TreeWalker.cs index d0fd564..8a127e2 100644 --- a/Runtime/Graphs/Trees/TreeWalker.cs +++ b/Runtime/Graphs/Trees/TreeWalker.cs @@ -50,7 +50,7 @@ namespace Rokojori { var p = Parent( node ); - if ( p == null || index<0 || index >= NumChildren( p ) ) + if ( p == null || index < 0 || index >= NumChildren( p ) ) { return null; } return ChildAt( p, index ); @@ -74,11 +74,97 @@ namespace Rokojori public bool HasSiblingAt( N node, int index ) { var p = Parent( node ); - if ( p == null || index<0 || index >= NumChildren( p ) ) - { return false; } + if ( p == null || index < 0 || index >= NumChildren( p ) ) + { + return false; + } return true; } - + + public int NumSiblings( N node ) + { + if ( node == null ) + { + return 0; + } + + var p = Parent( node ); + + if ( p == null ) + { + return 0; + } + + return NumChildren( p ) - 1; + } + + public void IterateSiblings( N node, Action action ) + { + if ( node == null ) + { + return; + } + + var p = Parent( node ); + + if ( p == null ) + { + return; + } + + var numChildren = NumChildren( p ); + + for ( int i = 0; i < numChildren; i++ ) + { + var child = ChildAt( p, i ); + + if ( child == node ) + { + continue; + } + + action( child ); + } + + + + } + + public N FindSibling( N node, Func evaluater ) + { + if ( node == null ) + { + return null; + } + + var p = Parent( node ); + + if ( p == null ) + { + return null ; + } + + var numChildren = NumChildren( p ); + + for ( int i = 0; i < numChildren; i++ ) + { + var child = ChildAt( p, i ); + + if ( child == node ) + { + continue; + } + + var result = evaluater( child ); + + if ( result ) + { + return child; + } + } + + return null; + } public N FirstChild( N node ) { diff --git a/Runtime/Interactions/Grabbable.cs b/Runtime/Interactions/Grabbable.cs index 9b89fa2..85f1346 100644 --- a/Runtime/Interactions/Grabbable.cs +++ b/Runtime/Interactions/Grabbable.cs @@ -2,13 +2,21 @@ using Godot; using System.Collections; using System.Collections.Generic; using Godot.Collections; +using System.Drawing; namespace Rokojori { - + [Tool] [GlobalClass,Icon("res://addons/rokojori_action_library/Icons/Grabbable.svg")] - public partial class Grabbable:Node3D + public partial class Grabbable:Node3D, iEnablable { + + [Export] + public bool enabled = true; + public bool IsEnabled() => enabled; + public void SetEnabled( bool enabled ) { this.enabled = enabled; } + + [Export] public Action onGrab; @@ -21,14 +29,46 @@ namespace Rokojori [Export] public RigidBody3D rigidBody3D; + [Export] Pointable pointable; + + [Export] + public bool disablePointableDuringGrab = true; + [ExportGroup("Read Only")] [Export] public Grabber grabber; + protected bool enablePointableOnRelease = false; + public void SetGrabber( Grabber grabber ) { this.grabber = grabber; + + if ( grabber != null && ( disablePointableDuringGrab || grabber.disablePointableDuringGrab ) ) + { + if ( pointable == null ) + { + pointable = this.FindSibling(); + } + + if ( pointable != null ) + { + pointable.enabled = false; + enablePointableOnRelease = true; + } + } + + if ( grabber == null ) + { + if ( pointable != null && enablePointableOnRelease ) + { + pointable.enabled = true; + } + + enablePointableOnRelease = false; + } + if ( this.grabber != null ) { Action.Trigger( onGrab ); diff --git a/Runtime/Interactions/Grabber.cs b/Runtime/Interactions/Grabber.cs index a570637..a079411 100644 --- a/Runtime/Interactions/Grabber.cs +++ b/Runtime/Interactions/Grabber.cs @@ -5,7 +5,7 @@ using Godot.Collections; namespace Rokojori { - + [Tool] [GlobalClass,Icon("res://addons/rokojori_action_library/Icons/Grabber.svg")] public partial class Grabber:Node3D, SensorInputHandler { @@ -27,6 +27,9 @@ namespace Rokojori [Export] public Node3D grabOffset; + [Export] + public bool disablePointableDuringGrab = true; + [Export] public Smoothing positionSmoothing; @@ -37,6 +40,7 @@ namespace Rokojori [Export] public Grabbable grabbable; + public override void _Ready() diff --git a/Runtime/Interactions/Interactable.cs b/Runtime/Interactions/Interactable.cs index 22b8500..b251dda 100644 --- a/Runtime/Interactions/Interactable.cs +++ b/Runtime/Interactions/Interactable.cs @@ -5,10 +5,15 @@ using Godot.Collections; namespace Rokojori { - - [GlobalClass,Icon("res://addons/rokojori_action_library/Icons/Interactable.svg")] - public partial class Interactable:Node3D + [Tool] + [GlobalClass,Icon("res://addons/rokojori_action_library/Icons/Interactable.svg")] + public partial class Interactable:Node3D, iEnablable { + [Export] + public bool enabled = true; + public bool IsEnabled() => enabled; + public void SetEnabled( bool enabled ) { this.enabled = enabled; } + [Export] public Action onInteraction; } diff --git a/Runtime/Interactions/Interactor.cs b/Runtime/Interactions/Interactor.cs index 89fd29d..fe3684a 100644 --- a/Runtime/Interactions/Interactor.cs +++ b/Runtime/Interactions/Interactor.cs @@ -5,7 +5,7 @@ using Godot.Collections; namespace Rokojori { - + [Tool] [GlobalClass,Icon("res://addons/rokojori_action_library/Icons/Interactor.svg")] public partial class Interactor:Node3D, SensorInputHandler { diff --git a/Runtime/Interactions/Pointable.cs b/Runtime/Interactions/Pointable.cs index 3f0d59c..afec0b7 100644 --- a/Runtime/Interactions/Pointable.cs +++ b/Runtime/Interactions/Pointable.cs @@ -5,10 +5,18 @@ using Godot.Collections; namespace Rokojori { - + [Tool] [GlobalClass,Icon("res://addons/rokojori_action_library/Icons/Pointable.svg")] - public partial class Pointable:Node3D + public partial class Pointable:Node3D, iEnablable { + [Export] + public bool enabled = true; + + public bool IsEnabled() => enabled; + public void SetEnabled( bool enabled ) { this.enabled = enabled; } + + + [Export] public int pointingPriority; diff --git a/Runtime/Interactions/Selectors/InteractiveSelector.cs b/Runtime/Interactions/Selectors/InteractiveSelector.cs new file mode 100644 index 0000000..1368d7b --- /dev/null +++ b/Runtime/Interactions/Selectors/InteractiveSelector.cs @@ -0,0 +1,71 @@ +using Godot; +using System.Collections; +using System.Collections.Generic; +using Godot.Collections; +using System.Drawing; + +namespace Rokojori +{ + [Tool] + [GlobalClass] + public partial class InteractiveSelector:Selector + { + [Export] + public Trillean isPointable = Trillean.Any; + + [Export] + public Trillean pointableEnabled = Trillean.Any; + + [Export] + public Trillean isGrabbable = Trillean.Any; + + [Export] + public Trillean grabbableEnabled = Trillean.Any; + + [Export] + public Trillean isInteractable = Trillean.Any; + + [Export] + public Trillean interactableEnabled = Trillean.Any; + + + public override bool Selects( Node node ) + { + if ( ! Matches( node, isPointable, pointableEnabled ) ) + { + return false; + } + + if ( ! Matches( node, isGrabbable, grabbableEnabled ) ) + { + return false; + } + + if ( ! Matches( node, isInteractable, interactableEnabled ) ) + { + return false; + } + + return true; + } + + bool Matches( Node node, Trillean isType, Trillean isEnabled ) where T:Node,iEnablable + { + var childNode = Nodes.Find( node ); + + if ( ! TrilleanLogic.Matches( isType, childNode != null ) ) + { + return false; + } + + + if ( ! TrilleanLogic.Matches( isEnabled, childNode != null && childNode.IsEnabled() ) ) + { + return false; + } + + return true; + } + + } +} \ No newline at end of file diff --git a/Runtime/Interactions/Selectors/InteractiveSelector.cs.uid b/Runtime/Interactions/Selectors/InteractiveSelector.cs.uid new file mode 100644 index 0000000..60855a6 --- /dev/null +++ b/Runtime/Interactions/Selectors/InteractiveSelector.cs.uid @@ -0,0 +1 @@ +uid://bcqxkle5dxw3c diff --git a/Runtime/Interactions/SetPointableEnabled.cs b/Runtime/Interactions/SetPointableEnabled.cs new file mode 100644 index 0000000..41b2e90 --- /dev/null +++ b/Runtime/Interactions/SetPointableEnabled.cs @@ -0,0 +1,23 @@ +using Godot; +using System.Collections; +using System.Collections.Generic; +using Godot.Collections; + +namespace Rokojori +{ + [Tool] + [GlobalClass] + public partial class SetPointableEnabled:Action + { + [Export] + public Pointable pointable; + + [Export] + public bool enabled = true; + + protected override void _OnTrigger() + { + pointable.enabled = enabled; + } + } +} \ No newline at end of file diff --git a/Runtime/Interactions/SetPointableEnabled.cs.uid b/Runtime/Interactions/SetPointableEnabled.cs.uid new file mode 100644 index 0000000..84365cb --- /dev/null +++ b/Runtime/Interactions/SetPointableEnabled.cs.uid @@ -0,0 +1 @@ +uid://vfc8utojwc0b diff --git a/Runtime/Interactions/iEnablable.cs b/Runtime/Interactions/iEnablable.cs new file mode 100644 index 0000000..e348f1c --- /dev/null +++ b/Runtime/Interactions/iEnablable.cs @@ -0,0 +1,14 @@ +using Godot; +using System.Collections; +using System.Collections.Generic; +using Godot.Collections; + +namespace Rokojori +{ + + public interface iEnablable + { + public bool IsEnabled(); + public void SetEnabled( bool enabled ); + } +} \ No newline at end of file diff --git a/Runtime/Interactions/iEnablable.cs.uid b/Runtime/Interactions/iEnablable.cs.uid new file mode 100644 index 0000000..031c686 --- /dev/null +++ b/Runtime/Interactions/iEnablable.cs.uid @@ -0,0 +1 @@ +uid://do5nirsv6cj67 diff --git a/Runtime/LOD/LODBuilder.cs b/Runtime/LOD/LODBuilder.cs new file mode 100644 index 0000000..51ecac9 --- /dev/null +++ b/Runtime/LOD/LODBuilder.cs @@ -0,0 +1,104 @@ +using Godot; +using System.Collections; +using System.Collections.Generic; + +namespace Rokojori +{ + public class LODCameraDistanceLevel + { + public Mesh mesh; + public Material material; + public float distance; + } + + public class LODBuilder + { + public enum Mode + { + CameraDistance + } + + Mode mode = Mode.CameraDistance; + + public static LODBuilder ByCameraDistance() + { + var builder = new LODBuilder(); + + builder.mode = Mode.CameraDistance; + + return builder; + } + + List levels = new List(); + + Material material; + + public LODBuilder SetMaterial( Material material ) + { + this.material = material; + + return this; + } + + public LODBuilder Add( float distance, Mesh mesh, Material material = null ) + { + var level = new LODCameraDistanceLevel + { + mesh = mesh, + distance = distance, + material = material + }; + + levels.Add( level ); + return this; + } + + public LODNode Create( Node parent, string name = "LOD" ) + { + var lodNode = parent.CreateChild( name ); + + var arrangement = new LODArrangement(); + + levels.Sort( ( a, b ) => Mathf.Sign( a.distance - b.distance ) ); + + var maxMap = new Dictionary(); + + for ( int i = 0; i < levels.Count; i++ ) + { + if ( ( i + 1 ) < levels.Count ) + { + maxMap[ levels[ i ] ] = levels[ i + 1 ].distance; + } + else + { + maxMap[ levels[ i ] ] = 10000f; + } + } + + levels[ 0 ].distance = 0; + + levels.ForEach( + ( l )=> + { + var level = new LODLevel(); + var distanceRule = new LODCameraDistanceRule(); + distanceRule.minDistance = l.distance; + distanceRule.maxDistance = maxMap[ l ]; + + level.visibilityRules = [ distanceRule ]; + level.mesh = l.mesh; + level.material = l.material != null ? l.material : material; + arrangement.levels = arrangement.levels.Add( level ); + } + ); + + lodNode.arrangement = arrangement; + + + return lodNode; + } + + + } + +} \ No newline at end of file diff --git a/Runtime/LOD/LODBuilder.cs.uid b/Runtime/LOD/LODBuilder.cs.uid new file mode 100644 index 0000000..9487b57 --- /dev/null +++ b/Runtime/LOD/LODBuilder.cs.uid @@ -0,0 +1 @@ +uid://c6bp7sk6mtglv diff --git a/Runtime/LOD/LODCameraDistanceRule.cs b/Runtime/LOD/LODCameraDistanceRule.cs index bf15ce0..5f3a822 100644 --- a/Runtime/LOD/LODCameraDistanceRule.cs +++ b/Runtime/LOD/LODCameraDistanceRule.cs @@ -15,7 +15,7 @@ namespace Rokojori public override bool Evaluate( LODNode lodNode ) { - return false; + return Range.Contains( minDistance, maxDistance, lodNode.distance ); } } diff --git a/Runtime/LOD/LODMeshCreator.cs b/Runtime/LOD/LODMeshCreator.cs new file mode 100644 index 0000000..9662eac --- /dev/null +++ b/Runtime/LOD/LODMeshCreator.cs @@ -0,0 +1,61 @@ +using Godot; +using System.Collections; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace Rokojori +{ + [Tool] + [GlobalClass] + public partial class LODMeshCreator:Node + { + [Export] + public MeshInstance3D[] meshes; + + [Export] + public float[] distances; + + [Export] + public Mesh.PrimitiveType primitiveType = Mesh.PrimitiveType.Triangles; + + [Export] + public bool generateTangents = true; + + [ExportToolButton("Create")] + public Callable CreateButton => Callable.From( ()=>{ Create(); } ); + + [ExportGroup("Output")] + [Export] + public MeshInstance3D lodMesh; + + public async Task Create() + { + var list = new List(); + + var index = 0; + + foreach ( var m in meshes ) + { + var mg = MeshGeometry.From( m.Mesh as ArrayMesh ); + mg.lodEdgeLength = distances[ index ]; + index++; + + await this.RequestNextFrame(); + } + + var mesh = MeshGeometry.GenerateLODMesh( list, primitiveType, null, generateTangents ); + + await this.RequestNextFrame(); + + this.DestroyChildren(); + + await this.RequestNextFrame(); + + lodMesh = this.CreateChild( "LODMesh" ); + lodMesh.Mesh = mesh; + lodMesh.Mesh.SurfaceSetMaterial( 0, MaterialSurfaceContainer.GetActiveFrom( meshes[ 0 ] ) ); + + } + + } +} \ No newline at end of file diff --git a/Runtime/LOD/LODMeshCreator.cs.uid b/Runtime/LOD/LODMeshCreator.cs.uid new file mode 100644 index 0000000..ba975fb --- /dev/null +++ b/Runtime/LOD/LODMeshCreator.cs.uid @@ -0,0 +1 @@ +uid://cmvumubfr1hvu diff --git a/Runtime/LOD/LODNode.cs b/Runtime/LOD/LODNode.cs index 4d670bd..a3ec591 100644 --- a/Runtime/LOD/LODNode.cs +++ b/Runtime/LOD/LODNode.cs @@ -1,7 +1,6 @@ using Godot; using System.Collections; using System.Collections.Generic; -using Godot.Collections; namespace Rokojori { @@ -9,9 +8,22 @@ namespace Rokojori [GlobalClass] public partial class LODNode:MeshInstance3D { + [Export] public LODArrangement arrangement; + [Export] + public int currentLevelIndex = -1; + + [Export] + public int drawElements = 0; + + [Export] + public float distanceScale = 1; + + [Export] + public MeshInstance3D lod0; + LODLevel _currentLevel; public override void _Process( double delta ) @@ -33,10 +45,34 @@ namespace Rokojori return; } + currentLevelIndex = arrangement.levels.IndexOf( level ); + + if ( lod0 != null ) + { + lod0.Visible = currentLevelIndex == 0; + } + + if ( ! faceCount.ContainsKey( level.mesh ) ) + { + if ( level.mesh is ArrayMesh am ) + { + faceCount[ level.mesh ] = am.SurfaceGetArrayIndexLen( 0 ); + } + else + { + faceCount[ level.mesh ] = level.mesh.GetFaces().Length; + } + + + } + + drawElements = faceCount[ level.mesh ]; Mesh = level.mesh; MaterialOverride = level.material; } + Dictionary faceCount = new Dictionary(); + public Camera3D camera { @@ -73,6 +109,8 @@ namespace Rokojori _cameraDirection = ( GlobalPosition - camera.GlobalPosition ); + _hasCameraDirection = true; + return _cameraDirection; } } @@ -86,12 +124,14 @@ namespace Rokojori { if ( _hasDistance ) { - return _distance; + return _distance * distanceScale; } _distance = cameraDirection.Length(); - return _distance; + _hasDistance = true; + + return _distance * distanceScale; } } @@ -109,6 +149,8 @@ namespace Rokojori _pitch = Math3D.GlobalPitch( cameraDirection ); + _hasPitch = true; + return _pitch; } } @@ -127,6 +169,8 @@ namespace Rokojori _yaw = Math3D.GlobalYaw( cameraDirection ); + _hasYaw = true; + return _yaw; } } diff --git a/Runtime/LOD/NTree/OcTree/OcTree.cs b/Runtime/LOD/NTree/OcTree/OcTree.cs new file mode 100644 index 0000000..a8643c9 --- /dev/null +++ b/Runtime/LOD/NTree/OcTree/OcTree.cs @@ -0,0 +1,262 @@ +using System.Collections; +using System.Collections.Generic; +using Godot; +using System; +using System.Linq; + + + +namespace Rokojori +{ + public class OcTree:OcTreeNode + { + protected Func _getPosition; + protected Func,List> _combinePoints; + protected Func,List, float,List> _smoothPoints; + + protected Vector3 _min; + protected Vector3 _max; + protected float _rootCellSize; + + protected int _maxDepth = 64; + public int maxDepth => _maxDepth; + + public OcTree( Func getPosition, Vector3 min, Vector3 max, float rootCellSize, int maxDepth ) + { + this._getPosition = getPosition; + this._min = min; + this._max = max; + this._rootCellSize = rootCellSize; + this._maxDepth = maxDepth; + + CreateRootCells(); + + } + + public void SetCombiner( Func,List> combinePoints ) + { + this._combinePoints = combinePoints; + } + + public void SetSmoother( Func,List,float,List> smoothPoints ) + { + this._smoothPoints = smoothPoints; + } + + + public List CombinePoints( List values ) + { + return _combinePoints( values ); + } + + public List SmoothPoints( List targetValues, List sourceSmoothing, float amount ) + { + return _smoothPoints( targetValues, sourceSmoothing, amount ); + } + + + + + List> _rootCells = new List>(); + public List> rootCells => _rootCells; + + public bool Insert( List data ) + { + var result = true; + + data.ForEach( + ( d )=> + { + result = result && Insert( d ); + } + ); + + return result; + } + + public bool Insert( T data ) + { + var rootCell = GetRootCell( _getPosition( data ) ); + + if ( rootCell == null ) + { + return false; + } + + if ( ! rootCell.box.ContainsPoint( GetPosition( data ) ) ) + { + RJLog.Log( "Box not containing point", rootCell.rootCellIndex ); + } + + return rootCell.Insert( data ); + } + + public int GetLevelForSize( float size ) + { + var level = 0; + var it = _rootCellSize; + + while ( it > size ) + { + level ++; + it /= 2f; + } + + return level; + } + + public float GetSizeForLevel( int level ) + { + var it = 0; + var size = _rootCellSize; + + while ( it < level ) + { + size /= 2f; + it ++; + } + + return size; + } + + public void CombineUntilSize( float size ) + { + CombineUntilLevel( GetLevelForSize( size ) ); + } + + + public void CombineUntilLevel( int minLevel, float smoothDown = 0.2f ) + { + var levelMap = GetLevelMap(); + var levels = levelMap.Keys.ToList(); + levels.Sort(); + var maxLevel = levels.Last(); + + for ( int i = maxLevel - 1; i > minLevel; i-- ) + { + levelMap[ i ].ForEach( + ( c )=> + { + c.Combine(); + } + ); + } + + if ( smoothDown > 0 ) + { + for ( int i = minLevel + 1; i < maxLevel - 1; i++ ) + { + levelMap[ i ].ForEach( + ( c )=> + { + c.SmoothDown( smoothDown ); + } + ); + } + } + } + + public MapList> GetLevelMap() + { + var walker = new OcTreeWalker(); + + var levelMap = new MapList>(); + + walker.Iterate( + this, + ( n )=> + { + if ( n is OcTree tree ) + { + return; + } + + var c = n as OcTreeCell; + + levelMap.Add( c.depth, c ); + } + ); + + return levelMap; + } + + Vector3 _startOffset = Vector3.Zero; + Vector3I _rootCellDimensions = Vector3I.Zero; + + public Vector3I PositionToRootIndex( Vector3 position ) + { + position -= _startOffset; + + var index = ( position / ( Vector3.One * _rootCellSize ) ).FloorToInt(); + + return index; + } + + public Vector3 GetPosition( T data ) + { + return _getPosition( data ); + } + + public OcTreeCell GetRootCell( Vector3 position ) + { + var rootIndex = PositionToRootIndex( position ); + return GetRootCellByRootIndex( rootIndex ); + } + + public OcTreeCell GetRootCellByRootIndex( Vector3I rootCellIndex ) + { + var rootCellFlatIndex = MathX.MultiIndexToFlatIndex( rootCellIndex, _rootCellDimensions ); + + if ( rootCellFlatIndex < 0 || rootCellFlatIndex >= _rootCells.Count ) + { + return null; + } + + return _rootCells[ rootCellFlatIndex ]; + } + + + void CreateRootCells() + { + var rootCellSize3 = Vector3.One * _rootCellSize; + var start = _min.SnapFloored( rootCellSize3 ); + var end = _max.SnapCeiled( rootCellSize3 ); + + var num = ( ( end - start ) / rootCellSize3 ).RoundToInt(); + + _rootCellDimensions = num; + _startOffset = start; + + for ( int x = 0; x < num.X ; x ++ ) + { + for ( int y = 0; y < num.Y; y++ ) + { + for ( int z = 0; z < num.Z; z++ ) + { + var rootIndex = new Vector3I( x, y, z ); + var min = rootIndex * rootCellSize3 + start; + var max = min + rootCellSize3; + + var cell = OcTreeCell.Create( this, min, max, _rootCells.Count ); + + _rootCells.Add( cell ); + + // var positionRootIndex = PositionToRootIndex( cell.center ); + + // RJLog.Log( + // "Creating root cell", + // "Roots Index:", _rootCells.Count - 1, + // "Cell Index:", cell.rootCellIndex, + // "Center:", cell.center, + // "RootIndex:", rootIndex, + // "Get Self ByRootIndex:", GetRootCellByRootIndex( rootIndex ) == cell, + // "RootIndex From Position: ", positionRootIndex, + // "Get Self ByRootIndex From Position:", GetRootCellByRootIndex( positionRootIndex ) == cell + // ); + } + } + } + } + + } +} \ No newline at end of file diff --git a/Runtime/LOD/NTree/OcTree/OcTree.cs.uid b/Runtime/LOD/NTree/OcTree/OcTree.cs.uid new file mode 100644 index 0000000..69870dd --- /dev/null +++ b/Runtime/LOD/NTree/OcTree/OcTree.cs.uid @@ -0,0 +1 @@ +uid://byv0j4gqliwii diff --git a/Runtime/LOD/NTree/OcTree/OcTreeCell.cs b/Runtime/LOD/NTree/OcTree/OcTreeCell.cs new file mode 100644 index 0000000..7d27467 --- /dev/null +++ b/Runtime/LOD/NTree/OcTree/OcTreeCell.cs @@ -0,0 +1,202 @@ +using System.Collections; +using System.Collections.Generic; +using Godot; +using System; + + + +namespace Rokojori +{ + public class OcTreeCell:OcTreeNode + { + OcTreeCell _parent; + public OcTreeCell parent => _parent; + + OcTree _tree; + public OcTree tree => _tree; + + List> _cells; + public List> cells => _cells; + + + public int numCells => _cells == null ? 0 : cells.Count; + + List _values; + public List values => _values; + + int _depth; + public int depth => _depth; + + Vector3 _center; + public Vector3 center => _center; + + Vector3 _size; + public Vector3 size => _size; + + bool _isCombined = false; + public bool isCombined => _isCombined; + public bool canBeCombined => ! isLeaf && ! isCombined && numCells > 0; + + + public bool isRoot => _parent == null; + public bool isEmpty => _cells == null || _cells.Count == 0; + public bool isLeaf => _depth == tree.maxDepth; + + Box3 _box; + public Box3 box => _box; + + int _rootCellIndex = -1; + public int rootCellIndex => _rootCellIndex; + + + public static OcTreeCell Create( OcTree tree, Vector3 min, Vector3 max, int rootIndex ) + { + var cell = new OcTreeCell(); + cell._tree = tree; + cell._center = (max + min ) / 2f; + cell._size = ( max - min ); + cell._depth = 0; + cell._box = Box3.Create( min, max ); + cell._rootCellIndex = rootIndex; + + return cell; + } + + public static OcTreeCell Create( OcTreeCell parent, int depth, Vector3 min, Vector3 max ) + { + var cell = new OcTreeCell(); + cell._parent = parent; + cell._tree = parent.tree; + cell._center = (max + min ) / 2f; + cell._size = ( max - min ); + cell._depth = depth; + cell._box = Box3.Create( min, max ); + cell._rootCellIndex = parent.rootCellIndex; + + return cell; + } + + public Vector3 GetPointWithPolarUVW( Vector3 polarUVW ) + { + var halfSize = _size / 2f; + + return _center + halfSize * polarUVW; + } + + public bool Insert( T data ) + { + if ( isLeaf ) + { + if ( _values == null ) + { + _values = new List(); + } + + values.Add( data ); + return true; + } + + Nest(); + + var position = tree.GetPosition( data ); + + var cell = GetChildCellFor( position ); + + if ( cell == null ) + { + RJLog.Log( "No cell found in:", this.depth, this.center, ">> for: ", position ); + + return false; + } + + return cell.Insert( data ); + } + + public void SmoothDown( float amount ) + { + if ( isLeaf || cells == null ) + { + return; + } + + cells.ForEach( + ( c )=> + { + c._values = tree.SmoothPoints( c.values, values, amount ); + } + ); + + + + } + + public void Combine() + { + if ( isLeaf || isCombined ) + { + return; + } + + if ( numCells == 0 ) + { + _isCombined = true; + return; + } + + var cellPoints = new List(); + cells.ForEach( + c => + { + if ( c.values == null ) + { + return; + } + + cellPoints.AddRange( c.values ); + } + ); + + _values = tree.CombinePoints( cellPoints ); + _isCombined = true; + } + + public OcTreeCell GetChildCellFor( Vector3 position ) + { + return _cells.Find( c => c.box.ContainsPoint( position ) ); + } + + + public void Nest() + { + if ( _cells != null && _cells.Count == 8 ) + { + return; + } + + _cells = new List>(); + + for ( int x = -1; x < 1; x ++ ) + { + var x0 = x; + var x1 = x + 1; + + for ( int y = -1; y < 1; y ++ ) + { + var y0 = y; + var y1 = y + 1; + + for ( int z = -1; z < 1; z ++ ) + { + var z0 = z; + var z1 = z + 1; + + var min = GetPointWithPolarUVW( new Vector3( x0, y0, z0 ) ); + var max = GetPointWithPolarUVW( new Vector3( x1, y1, z1 ) ); + + _cells.Add( Create( this, depth + 1, min, max ) ); + } + } + } + } + } +} \ No newline at end of file diff --git a/Runtime/LOD/NTree/OcTree/OcTreeCell.cs.uid b/Runtime/LOD/NTree/OcTree/OcTreeCell.cs.uid new file mode 100644 index 0000000..7191008 --- /dev/null +++ b/Runtime/LOD/NTree/OcTree/OcTreeCell.cs.uid @@ -0,0 +1 @@ +uid://bkg701bcjl3nu diff --git a/Runtime/LOD/NTree/OcTree/OcTreeNode.cs b/Runtime/LOD/NTree/OcTree/OcTreeNode.cs new file mode 100644 index 0000000..fbd7db7 --- /dev/null +++ b/Runtime/LOD/NTree/OcTree/OcTreeNode.cs @@ -0,0 +1,14 @@ +using System.Collections; +using System.Collections.Generic; +using Godot; +using System; + + + +namespace Rokojori +{ + public class OcTreeNode + { + + } +} \ No newline at end of file diff --git a/Runtime/LOD/NTree/OcTree/OcTreeNode.cs.uid b/Runtime/LOD/NTree/OcTree/OcTreeNode.cs.uid new file mode 100644 index 0000000..99c7887 --- /dev/null +++ b/Runtime/LOD/NTree/OcTree/OcTreeNode.cs.uid @@ -0,0 +1 @@ +uid://dyyollc58p3l6 diff --git a/Runtime/LOD/NTree/OcTree/OcTreeWalker.cs b/Runtime/LOD/NTree/OcTree/OcTreeWalker.cs new file mode 100644 index 0000000..35a176e --- /dev/null +++ b/Runtime/LOD/NTree/OcTree/OcTreeWalker.cs @@ -0,0 +1,53 @@ +using System.Collections; +using System.Collections.Generic; +using Godot; +using System; + + + +namespace Rokojori +{ + public class OcTreeWalker:TreeWalker> + { + public override OcTreeNode Parent( OcTreeNode node ) + { + if ( node is OcTree ) + { + return null; + } + + var cell = node as OcTreeCell; + + return cell.isRoot ? cell.tree : cell.parent; + } + + public override int NumChildren( OcTreeNode node ) + { + if ( node is OcTree tree ) + { + return tree.rootCells.Count; + } + + var cell = node as OcTreeCell; + + return cell.numCells; + } + + public override OcTreeNode ChildAt( OcTreeNode node, int index ) + { + if ( index < 0 || index >= NumChildren( node ) ) + { + return null; + } + + if ( node is OcTree tree ) + { + return tree.rootCells[ index ]; + } + + var cell = node as OcTreeCell; + + return cell.cells[ index ]; + } + } +} \ No newline at end of file diff --git a/Runtime/LOD/NTree/OcTree/OcTreeWalker.cs.uid b/Runtime/LOD/NTree/OcTree/OcTreeWalker.cs.uid new file mode 100644 index 0000000..cefb67e --- /dev/null +++ b/Runtime/LOD/NTree/OcTree/OcTreeWalker.cs.uid @@ -0,0 +1 @@ +uid://u5ybxjw7q03t diff --git a/Runtime/LOD/PointClouds/Point.cs b/Runtime/LOD/PointClouds/Point.cs new file mode 100644 index 0000000..bbf7982 --- /dev/null +++ b/Runtime/LOD/PointClouds/Point.cs @@ -0,0 +1,51 @@ +using System.Collections; +using System.Collections.Generic; +using Godot; +using System; + + + +namespace Rokojori.PointClouds +{ + public class Point + { + public Vector3 position; + public Color color; + public Vector3 normal; + public Vector2 uv; + + public Point Lerp( Point point, float amount ) + { + var p = new Point(); + + p.position = position.Lerp( point.position, amount ); + p.normal = normal.Lerp( point.normal, amount ).Normalized(); + p.uv = uv.Lerp( point.uv, amount ); + p.color = color.ToVector4().Lerp( point.color.ToVector4(), amount ).ToColor(); + + return p; + } + + + public static Point AsAverage( List points ) + { + var p = new Point(); + + var color = new Vector4(); + + for ( int i = 0; i < points.Count; i++ ) + { + var d = 1f / ( i + 1 ); + p.position += d * ( points[ i ].position - p.position ); + p.normal += d * ( points[ i ].normal - p.normal ); + p.uv += d * ( points[ i ].uv - p.uv ); + color += d * ( points[ i ].color.ToVector4() - color ); + } + + p.normal = p.normal.Normalized(); + p.color = color.ToColor(); + + return p; + } + } +} \ No newline at end of file diff --git a/Runtime/LOD/PointClouds/Point.cs.uid b/Runtime/LOD/PointClouds/Point.cs.uid new file mode 100644 index 0000000..2e9696d --- /dev/null +++ b/Runtime/LOD/PointClouds/Point.cs.uid @@ -0,0 +1 @@ +uid://cwoel0qagkx5l diff --git a/Runtime/LOD/PointClouds/PointCloud.cs b/Runtime/LOD/PointClouds/PointCloud.cs new file mode 100644 index 0000000..291cfae --- /dev/null +++ b/Runtime/LOD/PointClouds/PointCloud.cs @@ -0,0 +1,66 @@ +using System.Collections; +using System.Collections.Generic; +using Godot; +using System; + +using System.Threading.Tasks; + +namespace Rokojori.PointClouds +{ + public class PointCloud + { + public List points = new List(); + + public Vector3 center; + + public void ComputeCenter() + { + center = Math3D.ComputeAverage( points, p => p.position ); + } + + public Box3 boundingBox; + + public void ComputeBoundingBox() + { + boundingBox = Box3.Create( points, p => p.position ); + } + + public void SortByDistanceToCenter() + { + ComputeCenter(); + + points.Sort( + ( a, b ) => + { + var dA = ( a.position - center ).LengthSquared(); + var dB = ( b.position - center ).LengthSquared(); + + return Mathf.Sign( dB - dA ); + } + ); + } + + public ArrayMesh GenerateMesh( float normalOffset = 0f ) + { + var mg = GenerateMeshGeometry( normalOffset ); + return mg.GenerateMesh( Mesh.PrimitiveType.Points, null, false ); + } + + public MeshGeometry GenerateMeshGeometry( float normalOffset = 0f ) + { + var mg = new MeshGeometry( true, false, true, false ); + mg.customMeshAttributes.Add( new MeshAttributeVector4List( 0 ) ); + mg.customMeshAttributes.Add( new MeshAttributeVector4List( 1 ) ); + + points.ForEach( + ( p ) => + { + mg.AddPoint( p.position + p.normal * normalOffset, p.color.srgbToLinear(), p.normal, 0, p.uv, 1 ); + } + ); + + return mg; + } + + } +} \ No newline at end of file diff --git a/Runtime/LOD/PointClouds/PointCloud.cs.uid b/Runtime/LOD/PointClouds/PointCloud.cs.uid new file mode 100644 index 0000000..d229241 --- /dev/null +++ b/Runtime/LOD/PointClouds/PointCloud.cs.uid @@ -0,0 +1 @@ +uid://box2fnynegqik diff --git a/Runtime/LOD/PointClouds/PointCloudGenerator.cs b/Runtime/LOD/PointClouds/PointCloudGenerator.cs new file mode 100644 index 0000000..4043210 --- /dev/null +++ b/Runtime/LOD/PointClouds/PointCloudGenerator.cs @@ -0,0 +1,258 @@ +using System.Collections; +using System.Collections.Generic; +using Godot; +using System; +using System.Threading.Tasks; + + +namespace Rokojori.PointClouds +{ + [Tool] + [GlobalClass] + public partial class PointCloudGenerator:Node3D + { + [Export] + public MeshInstance3D mesh; + + [Export] + public PointCloudSampler.SampleMode sampleMode = PointCloudSampler.SampleMode.Center; + + [Export] + public float samplingPixelDensity = 0.01f; + + [Export] + public float outputPixelDensity = 0.5f; + + [Export] + + public int numPoints = 0; + + [Export] + public int squareTexture; + + [Export] + public Material material; + + [Export] + public bool createOutputs = false; + + [Export] + public MeshInstance3D[] outputs; + + [ExportGroup("Lerping")] + [Export] + public Curve lowerLerp; + + [Export] + public Curve higherLerp; + + [Export] + public int lerpSteps; + + [ExportGroup("")] + + [Export] + public LODNode lod; + + + [Export] + bool working = false; + + [Export] + public string[] outputInfos = []; + + [ExportToolButton( "Generate")] + public Callable GenerateButton => Callable.From( + () => + { + GeneratePointCloud(); + } + ); + + public async void GeneratePointCloud() + { + if ( working ) + { + return; + } + + working = true; + numPoints = -1; + this.LogInfo( "Generating Point Cloud" ); + + + var sampler = new PointCloudSampler(); + + if ( samplingPixelDensity > 0 ) + { + sampler.densityResolution = samplingPixelDensity; + } + + sampler.materials = Materials.GetAll( mesh ); + sampler.albedoTexture = sampler.materials.Map( m => Texture2DPropertyName.albedoTexture ); + sampler.albedo = sampler.materials.Map( m => ColorPropertyName.albedo ); ; + + var cloud = await sampler.SampleFromMesh( sampleMode, (ArrayMesh) mesh.Mesh, this ); + + this.LogInfo( "Sampled mesh" ); + + var time = Async.GetTimeMS(); + // cloud.ComputeBoundingBox(); + + time = Async.PrintAndUpdateMS( time ); + + var longestCM = cloud.boundingBox.size.MaxDimension() * 100f; + var nextP2CM = MathX.NextPowerOfTwo( longestCM ); + var rootSize = nextP2CM / 100f; + var ocMin = cloud.boundingBox.center - Vector3.One * rootSize; + var ocMax = cloud.boundingBox.center + Vector3.One * rootSize; + var depth = Mathf.CeilToInt( MathX.Exponent( 2, rootSize/ samplingPixelDensity ) ); + + var ocTree = new PointCloudOcTree( ocMin, ocMax, rootSize, depth ); + + var minSize = ocTree.GetSizeForLevel( depth ); + + this.LogInfo( "OcTree MinDepth", minSize._CM() ); + + this.RequestNextFrame(); + time = Async.PrintAndUpdateMS( time, "Inserting to octree" ); + ocTree.Insert( cloud.points ); + time = Async.PrintAndUpdateMS( time, "Inserting to octree Done" ); + var level = ocTree.GetLevelForSize( outputPixelDensity ); + + this.LogInfo( "Combining" ); + this.RequestNextFrame(); + time = Async.PrintAndUpdateMS( time, "Combining" ); + + ocTree.normalSeperation = false; + ocTree.CombineUntilLevel( level ); + + time = Async.PrintAndUpdateMS( time, "Combining Done" ); + + this.LogInfo( "Combining level", level, "Max Level", depth ); + + + + this.LogInfo( "Cloud Points:", cloud.points.Count ); + + if ( outputs != null ) + { + outputs = []; + } + + + + this.DestroyChildren(); + + + var levelMap = ocTree.GetLevelMap(); + + var levelInstances = new List(); + + var lodBuilder = LODBuilder.ByCameraDistance(); + + lodBuilder.SetMaterial( material ); + + // lodBuilder.Add( 0, mesh.Mesh, mesh.GetSurfaceOverrideMaterial( 0 ) ); + + var meshGeometries = new List(); + + var infos = new List(); + + for ( int i = level + 1; i < depth; i++ ) + { + var filledLevels = levelMap[ i ].Filter( l => l.values != null ); + var points = new List(); + + filledLevels.ForEach( + l => + { + points.AddRange( l.values ); + } + ); + + var pc = new PointCloud(); + pc.points = points; + pc.ComputeCenter(); + pc.SortByDistanceToCenter(); + + var levelSize = ocTree.GetSizeForLevel( i ); + var distance = Cameras.ComputePixelDistanceForSizeVertical( 60, levelSize, new Vector2( 1920, 1080 ) ) * 4; + + // this.LogInfo( + // "Level", i, + // "Points", pc.points.Count, + // "Size", RegexUtility._CM( levelSize ), + // "Distance", RegexUtility._M( distance ) + // ); + + var mg = pc.GenerateMeshGeometry( levelSize/2f ); + meshGeometries.Add( mg ); + + + infos.Add( + RJLog.Stringify( + "Level", i, + "Points", pc.points.Count, + "Size", levelSize._CM(), + "Vertices", mg.numVertices, + "Normals", mg.numNormals, + "UVs", mg.numUV2s, + "Colors", mg.numColors + ) + ); + + var t = MathX.Map( i, level + 1, depth - 1, 1, 0 ); + mg.lodEdgeLength = levelSize; + // mg.ApplyTranslation( new Vector3( 100 * t, 0, 0 ) ); + + var mesh = pc.GenerateMesh( levelSize / 2f ); + + lodBuilder.Add( levelSize, mesh ); + + if ( createOutputs ) + { + var meshInstance = this.CreateChild(); + meshInstance.Mesh = mesh; + meshInstance.MaterialOverride = material; + + levelInstances.Add( meshInstance ); + } + } + + if ( createOutputs ) + { + outputs = levelInstances.ToArray(); + } + + outputInfos = infos.ToArray(); + + var lodMesh = this.CreateChild( "LOD Mesh" ); + meshGeometries.Reverse(); + var mainGeometry = meshGeometries[ 0 ]; + var lerpingData = new LODLerpingData(); + lerpingData.lowerLevelWeights = lowerLerp; + lerpingData.higherLevelWeights = higherLerp; + lerpingData.lerpSteps = lerpSteps; + lodMesh.Mesh = MeshGeometry.GeneratePointsLODMesh( meshGeometries, lerpingData, false ); + + lodMesh.SetSurfaceOverrideMaterial( 0, material ); + + lod = lodBuilder.Create( this, "LOD" ); + lod.lod0 = lod.CreateChild(); + lod.lod0.Mesh = mesh.Mesh; + lod.lod0.MaterialOverride = mesh.GetSurfaceOverrideMaterial( 0 ); + lod.distanceScale = 4; + + + // cloud.SortByDistanceToCenter(); + + // numPoints = cloud.points.Count; + // squareTexture = (int)Mathf.Pow( numPoints, 0.5f ); + // output.Mesh = cloud.GenerateMesh(); + + working = false; + + } + } +} \ No newline at end of file diff --git a/Runtime/LOD/PointClouds/PointCloudGenerator.cs.uid b/Runtime/LOD/PointClouds/PointCloudGenerator.cs.uid new file mode 100644 index 0000000..74a6ad1 --- /dev/null +++ b/Runtime/LOD/PointClouds/PointCloudGenerator.cs.uid @@ -0,0 +1 @@ +uid://v88dkcabl6kd diff --git a/Runtime/LOD/PointClouds/PointCloudOcTree.cs b/Runtime/LOD/PointClouds/PointCloudOcTree.cs new file mode 100644 index 0000000..a4891bb --- /dev/null +++ b/Runtime/LOD/PointClouds/PointCloudOcTree.cs @@ -0,0 +1,94 @@ +using System.Collections; +using System.Collections.Generic; +using Godot; +using System; + +using System.Threading.Tasks; + +namespace Rokojori.PointClouds +{ + public class PointCloudOcTree:OcTree + { + List compressedNormals = new List() + { + Vector3.Up, + Vector3.Down, + Vector3.Forward, + Vector3.Back, + Vector3.Right, + Vector3.Left + }; + + public bool normalSeperation = false; + + public PointCloudOcTree( Vector3 min, Vector3 max, float rootCellSize, int maxDepth ) + :base( null, min, max, rootCellSize, maxDepth ) + { + this._getPosition = GetPointPosition; + this._combinePoints = CombinePoints; + this._smoothPoints = SmoothPoints; + } + + protected Vector3 GetPointPosition( Point p ) + { + return p.position; + } + + protected int GetNormalIndex( Vector3 normal ) + { + var closest = -1; + var closestDistance = 100f; + + for ( int i = 0; i < compressedNormals.Count; i++ ) + { + var d = compressedNormals[ i ].DistanceSquaredTo( normal ); + + if ( d < closestDistance ) + { + closestDistance = d; + closest = i; + } + + } + + return closest; + + } + + protected List CombinePoints( List points ) + { + if ( normalSeperation ) + { + var lists = compressedNormals.Map( c => new List() ); + + points.ForEach( + ( p )=> + { + var normalIndex = GetNormalIndex( p.normal ); + lists[ normalIndex ].Add( p ); + } + ); + + lists = lists.Filter( n => n.Count > 0 ); + + + return lists.Map( l => Point.AsAverage( l ) ); + } + + return new List(){ Point.AsAverage( points ) }; + } + + protected List SmoothPoints( List targets, List points, float amount ) + { + if ( targets == null || points == null ) + { + return targets; + } + + var average = Point.AsAverage( points ); + return targets.Map( t => t.Lerp( average, amount ) );; + } + + + } +} \ No newline at end of file diff --git a/Runtime/LOD/PointClouds/PointCloudOcTree.cs.uid b/Runtime/LOD/PointClouds/PointCloudOcTree.cs.uid new file mode 100644 index 0000000..793e79f --- /dev/null +++ b/Runtime/LOD/PointClouds/PointCloudOcTree.cs.uid @@ -0,0 +1 @@ +uid://dhn11j8cvbexf diff --git a/Runtime/LOD/PointClouds/PointCloudSampler.cs b/Runtime/LOD/PointClouds/PointCloudSampler.cs new file mode 100644 index 0000000..77826b1 --- /dev/null +++ b/Runtime/LOD/PointClouds/PointCloudSampler.cs @@ -0,0 +1,406 @@ +using System.Collections; +using System.Collections.Generic; +using Godot; +using System; + +using System.Threading.Tasks; + +namespace Rokojori.PointClouds +{ + + public class PointCloudSampler + { + public enum SampleMode + { + Center, + Vertices, + CenterAndVertices, + Density + } + + public List materials; + public List albedoTexture; + public List albedo; + public float densityResolution = 0.2f; + + List albedoTextureImages; + + SampleMode mode; + + ArrayMesh mesh; + Node worker; + + PointCloud pointCloud; + + + + public PointCloud SampleFromMeshSync( SampleMode sampleMode, ArrayMesh mesh, Node worker ) + { + this.mode = sampleMode; + this.mesh = mesh; + this.worker = worker; + + pointCloud = new PointCloud(); + + GrabTextureImages(); + + for ( int i = 0; i < mesh.GetSurfaceCount(); i++ ) + { + SampleSurfaceSync( mesh, i ); + } + + return pointCloud; + + } + + public async Task SampleFromMesh( SampleMode sampleMode, ArrayMesh mesh, Node worker ) + { + + this.mode = sampleMode; + this.mesh = mesh; + this.worker = worker; + + pointCloud = new PointCloud(); + + try + { + + + GrabTextureImages(); + + for ( int i = 0; i < mesh.GetSurfaceCount(); i++ ) + { + await SampleSurface( mesh, i ); + } + + } + catch ( System.Exception e ) + { + worker.LogError( e ); + } + + return pointCloud; + + } + + + + void GrabTextureImages() + { + var index = -1; + + albedoTextureImages = new List(); + + albedoTexture.ForEach( + ( at )=> + { + index++; + + if ( at == null ) + { + albedoTextureImages.Add( null ); + } + + var material = materials[ index ]; + var texture = at.Get( material ); + + if ( texture == null ) + { + albedoTextureImages.Add( null ); + + return; + + } + + var image = texture.GetImage(); + + albedoTextureImages.Add( image ); + } + ); + + // worker.LogInfo( "Added image:", albedoTextureImages.Count ); + } + + + + public void SampleSurfaceSync( ArrayMesh mesh, int surface ) + { + if ( SampleMode.Density == mode ) + { + SampleDensitySync( mesh, surface ); + return; + } + + SampleSimpleSync( mesh, surface ); + + return; + } + + + + void SampleDensitySync( ArrayMesh mesh, int surface ) + { + var mdt = new MeshDataTool(); + mdt.CreateFromSurface( mesh, surface ); + + var nullTriangles = 0; + var numFaces = mdt.GetFaceCount(); + var subDivs = 0; + + + for ( int i = 0; i < mdt.GetFaceCount(); i++ ) + { + // time = await Async.WaitIfExceeded( time, worker ); + + var positions = new List(); + var normals = new List(); + var uvs = new List(); + + for ( int j = 0; j < 3; j++ ) + { + var index = mdt.GetFaceVertex( i, j ); + + var p = mdt.GetVertex( index ); + var uv = mdt.GetVertexUV( index ); + var n = mdt.GetVertexNormal( index ); + + positions.Add( p ); + uvs.Add( uv ); + normals.Add( n ); + } + + var triangle = Triangle3.CreateFrom( positions ); + + AddPoints( positions, uvs, normals ); + + var minArea = densityResolution; + + var points = new List(); + triangle.GetSubdivisionPoints( points, minArea ); + + + // worker.LogInfo( triangle.area, points.Count ); + + + points.ForEach( + ( p )=> + { + var uv = (Vector2) triangle.Lerp( p, uvs[ 0 ], uvs[ 1 ], uvs[ 2 ] ); + var n = (Vector3) triangle.Lerp( p, normals[ 0 ], normals[ 1 ], normals[ 2 ] ); + + AddPoint( p, uv, n ); + subDivs ++; + } + ); + + // if ( triangle.area > minArea || triangle.longestEdgeLength > densityResolution ) + // { + // worker.LogInfo( area ); + // subDivs++; + // } + + // triangle = triangle.Shrink( densityResolution ); + + // if ( triangle == null ) + // { + // nullTriangles++; + // } + + + // var maxIterations = 1000; + // var iteration = 0; + + // while ( iteration < maxIterations && triangle != null && ( triangle.area > minArea || triangle.longestEdgeLength > densityResolution ) ) + // { + // var newUVs = positions.Map( p => (Vector2) triangle.Lerp( p, uvs[ 0 ], uvs[ 1 ], uvs[ 2 ] ) ); + // var newNormals = positions.Map( p => (Vector3) triangle.Lerp( p, normals[ 0 ], normals[ 1 ], normals[ 2 ] ) ); + + // positions = triangle.points; + // uvs = newUVs; + // normals = newNormals; + + // AddPoints( positions, uvs, normals ); + + // triangle = triangle.Shrink( densityResolution ); + + // iteration ++; + // } + } + + worker.LogInfo( "Tris:", numFaces, "Nulls:", nullTriangles, "Subs:", subDivs ); + } + + void AddPoints( List p, List u, List n ) + { + for ( int i = 0; i < p.Count; i++ ) + { + AddPoint( p[ i ], u[ i ], n[ i ] ); + } + } + + void AddPoint( Vector3 p, Vector2 u, Vector3 n ) + { + var point = new Point(); + point.color = Colors.White; + point.position = p; + point.normal = n; + point.uv = u; + pointCloud.points.Add( point ); + } + + public async Task SampleSurface( ArrayMesh mesh, int surface ) + { + await SampleSimple( mesh, surface ); + + return; + } + + void SampleSimpleSync( ArrayMesh mesh, int surface ) + { + var mdt = new MeshDataTool(); + mdt.CreateFromSurface( mesh, surface ); + + + var sampleVertices = SampleMode.Vertices == mode || SampleMode.CenterAndVertices == mode; + var sampleCenter = SampleMode.Center == mode || SampleMode.CenterAndVertices == mode; + + for ( int i = 0; i < mdt.GetFaceCount(); i++ ) + { + // time = await Async.WaitIfExceeded( time, worker ); + + var center = new Vector3( 0, 0, 0 ); + var centerColor = new Vector4( 0, 0, 0, 0 ); + var centerNormal = new Vector3( 0, 0, 0 ); + var centerUV = new Vector2( 0, 0 ); + + for ( int j = 0; j < 3; j++ ) + { + var index = mdt.GetFaceVertex( i, j ); + + var p = mdt.GetVertex( index ); + var uv = mdt.GetVertexUV( index ); + var n = mdt.GetVertexNormal( index ); + var color = Colors.White; + + var image = albedoTextureImages[ surface ]; + + if ( image != null ) + { + color = image.Sample( uv, ColorX.EdgeMode.Repeat ); + } + + + + center += p; + centerColor += color.ToVector4(); + centerNormal += n; + centerUV += uv; + + if ( sampleVertices ) + { + var point = new Point(); + point.color = color; + point.position = p; + point.normal = n; + point.uv = uv; + pointCloud.points.Add( point ); + } + + } + + if ( sampleCenter ) + { + var point = new Point(); + point.color = ( centerColor / 3.0f ).ToColor(); + point.position = center / 3.0f; + point.normal = centerNormal / 3.0f; + point.uv = centerUV / 3.0f; + pointCloud.points.Add( point ); + } + } + } + + async Task SampleSimple( ArrayMesh mesh, int surface ) + { + var mdt = new MeshDataTool(); + mdt.CreateFromSurface( mesh, surface ); + + + var sampleVertices = SampleMode.Vertices == mode || SampleMode.CenterAndVertices == mode; + var sampleCenter = SampleMode.Center == mode || SampleMode.CenterAndVertices == mode; + + var time = Async.StartTimer(); + + var faces = mdt.GetFaceCount(); + + for ( int i = 0; i < faces; i++ ) + { + time = await Async.WaitIfExceeded( time, worker ); + + if ( i % 10000 == 0 ) + { + worker.LogInfo( "Tris:", i + "/" + faces, RegexUtility._FFF( ( 100f * i ) / (float)faces ) ); + } + + var center = new Vector3( 0, 0, 0 ); + var centerColor = new Vector4( 0, 0, 0, 0 ); + var centerNormal = new Vector3( 0, 0, 0 ); + var centerUV = new Vector2( 0, 0 ); + + for ( int j = 0; j < 3; j++ ) + { + var index = mdt.GetFaceVertex( i, j ); + + var p = mdt.GetVertex( index ); + var uv = mdt.GetVertexUV( index ); + var n = mdt.GetVertexNormal( index ); + var color = Colors.White; + + var image = albedoTextureImages[ surface ]; + + if ( image != null ) + { + color = image.Sample( uv, ColorX.EdgeMode.Repeat ); + } + + + + center += p; + centerColor += color.ToVector4(); + centerNormal += n; + centerUV += uv; + + if ( sampleVertices ) + { + var point = new Point(); + point.color = color; + point.position = p; + point.normal = n; + point.uv = uv; + pointCloud.points.Add( point ); + } + + } + + if ( sampleCenter ) + { + var point = new Point(); + point.color = ( centerColor / 3.0f ).ToColor(); + point.position = center / 3.0f; + point.normal = centerNormal / 3.0f; + point.uv = centerUV / 3.0f; + pointCloud.points.Add( point ); + } + + if ( i == 0 ) + { + pointCloud.boundingBox = Box3.Create( center, center ); + } + else + { + pointCloud.boundingBox.IncludePoint( center ); + } + } + } + } +} \ No newline at end of file diff --git a/Runtime/LOD/PointClouds/PointCloudSampler.cs.uid b/Runtime/LOD/PointClouds/PointCloudSampler.cs.uid new file mode 100644 index 0000000..db921ec --- /dev/null +++ b/Runtime/LOD/PointClouds/PointCloudSampler.cs.uid @@ -0,0 +1 @@ +uid://dfksgo3wn58ts diff --git a/Runtime/Math/Geometry/Box3.cs b/Runtime/Math/Geometry/Box3.cs index 7d3ce8b..7c4e9f0 100644 --- a/Runtime/Math/Geometry/Box3.cs +++ b/Runtime/Math/Geometry/Box3.cs @@ -44,6 +44,21 @@ namespace Rokojori return b; } + public static Box3 Create( List data, System.Func getPosition ) + { + var min = new Vector3( float.MaxValue, float.MaxValue, float.MaxValue ); + var max = new Vector3( -float.MaxValue, -float.MaxValue, -float.MaxValue ); + + for ( int i = 0; i < data.Count; i++ ) + { + var p = getPosition( data[ i ] ); + min = min.Min( p ); + max = max.Max( p ); + } + + return Create( min, max ); + } + public Vector3 size => max - min; public void IncludePoint( Vector3 p ) diff --git a/Runtime/Math/Geometry/Triangle2.cs b/Runtime/Math/Geometry/Triangle2.cs index 188fea7..66608f2 100644 --- a/Runtime/Math/Geometry/Triangle2.cs +++ b/Runtime/Math/Geometry/Triangle2.cs @@ -114,7 +114,7 @@ namespace Rokojori if ( i01 == null || ! ContainsPoint( (Vector2) i01 ) ) { - RJLog.Log( "i01", i01, i01 != null ? ContainsPoint( (Vector2) i01 ) : false ); + // RJLog.Log( "i01", i01, i01 != null ? ContainsPoint( (Vector2) i01 ) : false ); return null; } @@ -122,7 +122,7 @@ namespace Rokojori if ( i12 == null || ! ContainsPoint( (Vector2) i12 ) ) { - RJLog.Log( "i12", i12, i12 != null ? ContainsPoint( (Vector2) i12 ) : false ); + // RJLog.Log( "i12", i12, i12 != null ? ContainsPoint( (Vector2) i12 ) : false ); return null; } @@ -130,7 +130,7 @@ namespace Rokojori if ( i20 == null || ! ContainsPoint( (Vector2) i20 ) ) { - RJLog.Log( "i20", i20, i20 != null ? ContainsPoint( (Vector2) i20 ) : false ); + // RJLog.Log( "i20", i20, i20 != null ? ContainsPoint( (Vector2) i20 ) : false ); return null; } diff --git a/Runtime/Math/Geometry/Triangle3.cs b/Runtime/Math/Geometry/Triangle3.cs index ea666a4..16fc06b 100644 --- a/Runtime/Math/Geometry/Triangle3.cs +++ b/Runtime/Math/Geometry/Triangle3.cs @@ -30,6 +30,17 @@ namespace Rokojori _needsUpdate = true; } + public static Triangle3 CreateFrom( List points, int offset = 0 ) + { + var t = new Triangle3( + points[ 0 ], + points[ 1 ], + points[ 2 ] + ); + + return t; + } + public static Triangle3 CreateFrom( MeshGeometry mg, int a, int b, int c ) { var t = new Triangle3( @@ -144,6 +155,7 @@ namespace Rokojori } public float area => ComputeTriangleArea( a, b, c ); + public bool Intersects( Line3 line ) { @@ -268,6 +280,11 @@ namespace Rokojori return LerpCurve3.FromPoints( GetPoint( 0 ), GetPoint( 1 ), GetPoint( 2 ) ); } + public List points => new List(){ a, b, c }; + + + + public Vector3 GetPoint( int i ) { if ( i == 0 ) @@ -286,6 +303,22 @@ namespace Rokojori return a; } + public Line3 GetEdge( int i ) + { + var p0 = GetPoint( i ); + var p1 = GetPoint( i % 3 ); + + return Line3.Create( p0, p1 ); + } + + public float GetEdgeLength( int i ) + { + return GetEdge( i ).length; + } + + public float longestEdgeLength => MathX.Min( GetEdgeLength( 0 ), GetEdgeLength( 1 ), GetEdgeLength( 2 ) ); + public float shortestEdgeLength => MathX.Max( GetEdgeLength( 0 ), GetEdgeLength( 1 ), GetEdgeLength( 2 ) ); + void SetPointsToLine( Line3 line, int index ) { line.Set( GetPoint( index ), GetPoint( ( index + 1 ) % 3 ) ); @@ -484,8 +517,50 @@ namespace Rokojori return new Triangle3( Math3D.XYasXZ( t.a ), Math3D.XYasXZ( t.b ), Math3D.XYasXZ( t.c ) ); } + public List CenterSplit() + { + var m = center; + + var subs = new List + { + new Triangle3( a, b, m ), + new Triangle3( b, c, m ), + new Triangle3( c, a, m ) + }; + + return subs; + } + + public void GetSubdivisionPoints( List output, float minArea ) + { + var processingList = new List(); + + processingList.Add( this ); + + while ( processingList.Count > 0 ) + { + var tri = processingList.Shift(); + output.Add( tri.center ); + + var subs = tri.CenterSplit(); + + subs.ForEach( + st => + { + if ( st.area > minArea ) + { + processingList.Add( st ); + } + } + ); + + } + + + + } + - public static bool InsideTriangle( Vector3 point, Vector3 a, Vector3 b, Vector3 c ) { var bary = GetBaryCentricCoordinate( point, a, b, c ); @@ -533,7 +608,66 @@ namespace Rokojori return new Vector3( 1f - u - v, v, u ); } - + public Vector3? GetBaryCentricCoordinate( Vector3 point ) + { + return GetBaryCentricCoordinate( point, a, b, c ); + } + + public Vector4? Lerp( Vector3 p, Vector4 x, Vector4 y, Vector4 z ) + { + var bary = GetBaryCentricCoordinate( p ); + + if ( bary == null ) + { + return null; + } + + var w = ( Vector3 ) bary; + + return w.Lerp( x, y, z ); + } + + public Vector3? Lerp( Vector3 p, Vector3 x, Vector3 y, Vector3 z ) + { + var bary = GetBaryCentricCoordinate( p ); + + if ( bary == null ) + { + return null; + } + + var w = ( Vector3 ) bary; + + return w.Lerp( x, y, z ); + } + + public Vector2? Lerp( Vector3 p, Vector2 x, Vector2 y, Vector2 z ) + { + var bary = GetBaryCentricCoordinate( p ); + + if ( bary == null ) + { + return null; + } + + var w = ( Vector3 ) bary; + + return w.Lerp( x, y, z ); + } + + public float? Lerp( Vector3 p, float x, float y, float z ) + { + var bary = GetBaryCentricCoordinate( p ); + + if ( bary == null ) + { + return null; + } + + var w = ( Vector3 ) bary; + + return w.Lerp( x, y, z ); + } } } \ No newline at end of file diff --git a/Runtime/Math/Math2D.cs b/Runtime/Math/Math2D.cs index 37392af..c2f8f88 100644 --- a/Runtime/Math/Math2D.cs +++ b/Runtime/Math/Math2D.cs @@ -6,8 +6,23 @@ using System; namespace Rokojori { - public class Math2D + public static class Math2D { + public static Vector2I RoundToInt( this Vector2 v ) + { + return new Vector2I( Mathf.RoundToInt( v.X ), Mathf.RoundToInt( v.Y ) ); + } + + public static Vector2I FloorToInt( this Vector2 v ) + { + return new Vector2I( Mathf.FloorToInt( v.X ), Mathf.FloorToInt( v.Y ) ); + } + + public static Vector2I CeilToInt( this Vector2 v ) + { + return new Vector2I( Mathf.CeilToInt( v.X ), Mathf.CeilToInt( v.Y ) ); + } + public static float LookingAtEachOtherAngle( Vector2 lookDirectionA, Vector2 lookDirectionB ) { return Dot( lookDirectionA, lookDirectionB ); @@ -90,5 +105,40 @@ namespace Rokojori { return clockwise ? Rotate90DegreesRight( v ) : Rotate90DegreesLeft( v ); } + + public static Vector2 ComputeAverage( List points ) + { + if ( points == null || points.Count == 0 ) + { + return Vector2.Zero; + } + + var mean = Vector2.Zero; + + for ( int i = 0; i < points.Count; i++ ) + { + mean += ( points[ i ] - mean ) / ( i + 1 ); + } + + return mean; + + } + + public static Vector2 ComputeAverage( List containers, Func getPoint ) + { + if ( containers == null || containers.Count == 0 ) + { + return Vector2.Zero; + } + + var mean = Vector2.Zero; + + for ( int i = 0; i < containers.Count; i++ ) + { + mean += ( getPoint( containers[ i ] ) - mean ) / ( i + 1 ); + } + + return mean; + } } } \ No newline at end of file diff --git a/Runtime/Math/Math3D.cs b/Runtime/Math/Math3D.cs index e04d704..358ca58 100644 --- a/Runtime/Math/Math3D.cs +++ b/Runtime/Math/Math3D.cs @@ -28,6 +28,98 @@ namespace Rokojori return LookingAtEachOther( fromDirection, to - from ); } + public static Vector4 Lerp( this Vector3 w, Vector4 x, Vector4 y, Vector4 z ) + { + return w.X * x + w.Y * y + w.Z * z; + } + + public static Vector3 Lerp( this Vector3 w, Vector3 x, Vector3 y, Vector3 z ) + { + return w.X * x + w.Y * y + w.Z * z; + } + + + public static Vector2 Lerp( this Vector3 w, Vector2 x, Vector2 y, Vector2 z ) + { + return w.X * x + w.Y * y + w.Z * z; + } + + public static float Lerp( this Vector3 w, float x, float y, float z ) + { + return w.X * x + w.Y * y + w.Z * z; + } + + + public static Vector3 ComputeAverage( List points ) + { + if ( points == null || points.Count == 0 ) + { + return Vector3.Zero; + } + + var mean = Vector3.Zero; + + for ( int i = 0; i < points.Count; i++ ) + { + mean += ( points[ i ] - mean ) / ( i + 1 ); + } + + return mean; + + } + + + public static Vector3 ComputeAverage( List containers, Func getPoint ) + { + if ( containers == null || containers.Count == 0 ) + { + return Vector3.Zero; + } + + var mean = Vector3.Zero; + + for ( int i = 0; i < containers.Count; i++ ) + { + mean += ( getPoint( containers[ i ] ) - mean ) / ( i + 1 ); + } + + return mean; + } + + public static Vector4 ComputeAverage( List points ) + { + if ( points == null || points.Count == 0 ) + { + return Vector4.Zero; + } + + var mean = Vector4.Zero; + + for ( int i = 0; i < points.Count; i++ ) + { + mean += ( points[ i ] - mean ) / ( i + 1 ); + } + + return mean; + + } + + public static Vector4 ComputeAverage( List containers, Func getPoint ) + { + if ( containers == null || containers.Count == 0 ) + { + return Vector4.Zero; + } + + var mean = Vector4.Zero; + + for ( int i = 0; i < containers.Count; i++ ) + { + mean += ( getPoint( containers[ i ] ) - mean ) / ( i + 1 ); + } + + return mean; + } public static Transform3D TRS( Vector3 translation, Quaternion rotation, Vector3 scale ) { @@ -267,6 +359,40 @@ namespace Rokojori return quaternion; } + public static Vector3 GetMin( List data, Func getPosition ) + { + var min = new Vector3( float.MaxValue, float.MaxValue, float.MaxValue ); + + for ( int i = 0; i < data.Count; i++ ) + { + min = min.Min( getPosition( data[ i ] ) ); + } + + return min; + } + + public static Vector3 GetMax( List data, Func getPosition ) + { + var max = new Vector3( -float.MaxValue, -float.MaxValue, -float.MaxValue ); + + for ( int i = 0; i < data.Count; i++ ) + { + max = max.Max( getPosition( data[ i ] ) ); + } + + return max; + } + + public static float MaxDimension( this Vector3 v ) + { + return MathX.Max( v.X, v.Y, v.Z ); + } + + public static float MinDimension( this Vector3 v ) + { + return MathX.Min( v.X, v.Y, v.Z ); + } + public static Vector3 MinGlobalPosition( Node3D a, Node3D b ) { return a.GlobalPosition.Min( b.GlobalPosition ); @@ -287,7 +413,7 @@ namespace Rokojori return a.Position.Max( b.Position ); } - public static Vector3 SnapRounded( Vector3 v, Vector3 snapping ) + public static Vector3 SnapRounded( this Vector3 v, Vector3 snapping ) { v.X = MathX.SnapRounded( v.X, snapping.X ); v.Y = MathX.SnapRounded( v.Y, snapping.Y ); @@ -296,7 +422,7 @@ namespace Rokojori return v; } - public static Vector3 SnapRoundedXZ( Vector3 v, float snapX, float snapZ ) + public static Vector3 SnapRoundedXZ( this Vector3 v, float snapX, float snapZ ) { v.X = MathX.SnapRounded( v.X, snapX ); v.Z = MathX.SnapRounded( v.Z, snapZ ); @@ -304,7 +430,7 @@ namespace Rokojori return v; } - public static Vector3 SnapCeiled( Vector3 v, Vector3 snapping ) + public static Vector3 SnapCeiled( this Vector3 v, Vector3 snapping ) { v.X = MathX.SnapCeiled( v.X, snapping.X ); v.Y = MathX.SnapCeiled( v.Y, snapping.Y ); @@ -313,7 +439,7 @@ namespace Rokojori return v; } - public static Vector3 SnapFloored( Vector3 v, Vector3 snapping ) + public static Vector3 SnapFloored( this Vector3 v, Vector3 snapping ) { v.X = MathX.SnapFloored( v.X, snapping.X ); v.Y = MathX.SnapFloored( v.Y, snapping.Y ); @@ -322,12 +448,58 @@ namespace Rokojori return v; } + public static Vector3I RoundToInt( this Vector3 v ) + { + return new Vector3I( Mathf.RoundToInt( v.X ) , Mathf.RoundToInt( v.Y ), Mathf.RoundToInt( v.Z ) ); + } + + public static Vector3I FloorToInt( this Vector3 v ) + { + return new Vector3I( Mathf.FloorToInt( v.X ) , Mathf.FloorToInt( v.Y ), Mathf.FloorToInt( v.Z ) ); + } + + public static Vector3I CeilToInt( this Vector3 v ) + { + return new Vector3I( Mathf.CeilToInt( v.X ) , Mathf.CeilToInt( v.Y ), Mathf.CeilToInt( v.Z ) ); + } + + public static Vector2 XY( this Vector3 v ) + { + return new Vector2( v.X, v.Y ); + } + + public static Vector2 YX( this Vector3 v ) + { + return new Vector2( v.Y, v.X ); + } + + public static Vector2 XZ( this Vector3 v ) + { + return new Vector2( v.X, v.Z ); + } + + public static Vector2 ZX( this Vector3 v ) + { + return new Vector2( v.Z, v.X ); + } + + public static Vector2 YZ( this Vector3 v ) + { + return new Vector2( v.Y, v.Z ); + } + + public static Vector2 ZY( this Vector3 v ) + { + return new Vector2( v.Y, v.Z ); + } + public static Basis AlignUp( Basis basis, Vector3 upDirection ) { basis.Y = upDirection; basis.X = - basis.Z.Cross( upDirection ); return basis.Orthonormalized(); } + public static Quaternion AlignUp( Quaternion rotation, Vector3 upDirection ) { diff --git a/Runtime/Math/MathX.cs b/Runtime/Math/MathX.cs index b446df8..092e974 100644 --- a/Runtime/Math/MathX.cs +++ b/Runtime/Math/MathX.cs @@ -6,7 +6,7 @@ using System; namespace Rokojori { - public class MathX + public static class MathX { public const float fps120Delta = 1/120f; @@ -143,6 +143,60 @@ namespace Rokojori return Mathf.Atan2( circle.Y, circle.X ); } + + + public static int MultiIndexToFlatIndex( List indices, List sizes ) + { + var index = 0; + var scale = 1; + + for ( int i = sizes.Count - 1; i >= 0; i-- ) + { + index += indices[ i ] * scale; + scale *= sizes[ i ]; + } + + return index; + } + + public static int MultiIndexToFlatIndex( Vector3I indices, Vector3I sizes ) + { + var index = 0; + + index += indices.Z; + index += indices.Y * sizes.Z; + index += indices.X * sizes.Z * sizes.Y; + return index; + } + + public static List FlatIndexToMultiIndex( int index, List sizes, List multiIndex = null ) + { + multiIndex = multiIndex == null ? new List( new int[ sizes.Count ] ) : multiIndex; + + for ( int i = sizes.Count - 1; i >= 0; i-- ) + { + multiIndex[ i ] = index % sizes[ i ]; + index /= sizes[i]; + } + + return multiIndex; + } + + public static Vector3I FlatIndexToMultiIndex( int index, Vector3I sizes ) + { + var multiIndex = Vector3I.Zero; + + multiIndex.Z = index % sizes.Z; + index /= sizes.Z; + + multiIndex.Y = index % sizes.Y; + index /= sizes.Y; + + multiIndex.X = index % sizes.X; + + return multiIndex; + } + public const float DegreesToRadians = Mathf.Pi / 180f; public const float RadiansToDegrees = 180f / Mathf.Pi; @@ -428,6 +482,23 @@ namespace Rokojori return max; } + public static float CurveAverage( this Curve c, int numSamples = 20 ) + { + if ( c == null ) + { + return 0; + } + + var value = 0f; + + for ( int i = 0; i < numSamples; i++ ) + { + value += c.Sample( (float) i / ( numSamples - 1 ) ); + } + + return value / numSamples; + } + public static List GetCurveWeights( Curve curve, int num, bool normalize = true ) { var sum = 0f; diff --git a/Runtime/Networking/Backends/LAN/LANNetworkingBackend.cs b/Runtime/Networking/Backends/LAN/LANNetworkingBackend.cs index 92776c2..c0f2b32 100644 --- a/Runtime/Networking/Backends/LAN/LANNetworkingBackend.cs +++ b/Runtime/Networking/Backends/LAN/LANNetworkingBackend.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; namespace Rokojori { - [GlobalClass] + [Tool][GlobalClass] public partial class LANNetworkBackend:NetworkBackend { SceneMultiplayer multiplayer; diff --git a/Runtime/Networking/NetworkManager.cs b/Runtime/Networking/NetworkManager.cs index 6c2e91b..df070d8 100644 --- a/Runtime/Networking/NetworkManager.cs +++ b/Runtime/Networking/NetworkManager.cs @@ -3,7 +3,7 @@ using Godot; namespace Rokojori { - [GlobalClass,Icon("res://addons/rokojori_action_library/Icons/NetworkManager.svg")] + [Tool][GlobalClass,Icon("res://addons/rokojori_action_library/Icons/NetworkManager.svg")] public partial class NetworkManager:Node { [Export] diff --git a/Runtime/Networking/Nodes/AddNetworkingNodes.cs b/Runtime/Networking/Nodes/AddNetworkingNodes.cs index 0daf5dc..efcb31d 100644 --- a/Runtime/Networking/Nodes/AddNetworkingNodes.cs +++ b/Runtime/Networking/Nodes/AddNetworkingNodes.cs @@ -4,7 +4,7 @@ using System.Collections.Generic; namespace Rokojori { - [GlobalClass] + [Tool][GlobalClass] public partial class AddNetworkNodes:Action { [Export] diff --git a/Runtime/Networking/Session/JoinSession.cs b/Runtime/Networking/Session/JoinSession.cs index 02e15d5..17384e2 100644 --- a/Runtime/Networking/Session/JoinSession.cs +++ b/Runtime/Networking/Session/JoinSession.cs @@ -4,7 +4,7 @@ using System.Collections.Generic; namespace Rokojori { - [GlobalClass] + [Tool][GlobalClass] public partial class JoinSession:Action { [Export] diff --git a/Runtime/Networking/Session/NetworkSessionRequest.cs b/Runtime/Networking/Session/NetworkSessionRequest.cs index fc28ca4..43ed557 100644 --- a/Runtime/Networking/Session/NetworkSessionRequest.cs +++ b/Runtime/Networking/Session/NetworkSessionRequest.cs @@ -4,7 +4,7 @@ using System.Collections.Generic; namespace Rokojori { - [GlobalClass] + [Tool][GlobalClass] public partial class NetworkSessionRequest:Resource { [Export] diff --git a/Runtime/Networking/Session/StartSession.cs b/Runtime/Networking/Session/StartSession.cs index 34fb0d4..d0ee747 100644 --- a/Runtime/Networking/Session/StartSession.cs +++ b/Runtime/Networking/Session/StartSession.cs @@ -4,7 +4,7 @@ using System.Collections.Generic; namespace Rokojori { - [GlobalClass] + [Tool][GlobalClass] public partial class StartSession:Action { [Export] diff --git a/Runtime/Networking/Transforms/NetworkTransform3D.cs b/Runtime/Networking/Transforms/NetworkTransform3D.cs index 66fbe4c..c34b79e 100644 --- a/Runtime/Networking/Transforms/NetworkTransform3D.cs +++ b/Runtime/Networking/Transforms/NetworkTransform3D.cs @@ -4,7 +4,7 @@ using System.Collections.Generic; namespace Rokojori { - [GlobalClass] + [Tool][GlobalClass] public partial class NetworkTransform3D:NetworkNode { [Export] diff --git a/Runtime/Networking/Transforms/NetworkTransform3DType.cs b/Runtime/Networking/Transforms/NetworkTransform3DType.cs index 4545853..cfc00a1 100644 --- a/Runtime/Networking/Transforms/NetworkTransform3DType.cs +++ b/Runtime/Networking/Transforms/NetworkTransform3DType.cs @@ -4,7 +4,7 @@ using System.Collections.Generic; namespace Rokojori { - [GlobalClass] + [Tool][GlobalClass] public partial class NetworkTransform3DType:Resource { [ExportCategory("Position")] diff --git a/Runtime/Procedural/Assets/Grass/GrassPatch.cs b/Runtime/Procedural/Assets/Grass/GrassPatch.cs index 8ab4424..89a0f1b 100644 --- a/Runtime/Procedural/Assets/Grass/GrassPatch.cs +++ b/Runtime/Procedural/Assets/Grass/GrassPatch.cs @@ -2,6 +2,7 @@ using System.Collections; using System.Collections.Generic; using Godot; using System; +using System.Threading.Tasks; @@ -24,6 +25,9 @@ namespace Rokojori [Export] public bool updateAlways; + [Export] + public Material material; + [ExportGroup( "Patch")] [Export] public float patchSize = 2; @@ -233,6 +237,21 @@ namespace Rokojori [Export] public int currentLODLevel = -1; + [Export] + public bool generateLODMesh = false; + + [Export] + public float customLODEdgeLength = 0; + + [Export] + public int lodLerpSteps = 2; + + [Export] + public Curve lowCurve = MathX.Curve( 0, 1 ); + + [Export] + public Curve highCurve = MathX.Curve( 0, 1 ); + // SerializedGodotObject _cached; public override void _Process( double delta ) @@ -287,7 +306,7 @@ namespace Rokojori return bladeSegments * 2 * ComputeNumBlades(); } - public void CreatePatch() + public async Task CreatePatch() { if ( blades == 0 && bladesX == 0 && bladesZ == 0) { @@ -311,18 +330,12 @@ namespace Rokojori lodLevels = new GrassPatchLODLevel[]{}; } - if ( output == null ) - { - this.output = this.CreateChild( "Grass Patch Mesh" ); - } - - var mg = new MeshGeometry(); + this.DestroyChildren(); + this.output = this.CreateChild( "Grass Patch Mesh" ); + - var cellSizeX = ( patchSizeX + patchSize ) / ( bladesX + blades ); - var cellSizeZ = ( patchSizeZ + patchSize ) / ( bladesZ + blades ); - var random = new LCG(); random.SetSeed( 1712 + seed ); @@ -330,7 +343,97 @@ namespace Rokojori _maxWidth = MathX.CurveMaximum( bladeWidth ); - X_numBlades = 0; + X_numBlades = 0; + + if ( ! generateLODMesh ) + { + var mg = CreatePatchGeometry(); + X_numTriangles = mg.indices.Count / 3; + output.Mesh = mg.GenerateMesh(); + output.Mesh.SurfaceSetMaterial( 0, material ); + } + else + { + var cachedCurrentLODLevel = currentLODLevel; + + try + { + var mgs = new List(); + + var numTris = 0; + + var time = this.StartAsyncTimer(); + var edgeLength = ( MathX.CurveAverage( bladeHeight ) * MathX.CurveAverage( bladeScale ) ) / bladeSegments; + + if ( customLODEdgeLength > 0 ) + { + edgeLength = customLODEdgeLength; + } + + this.LogInfo( "Edge Length", edgeLength ); + + for ( int i = 0; i < lodLevels.Length + 1; i++ ) + { + time = await this.WaitForAsyncTimer( time ); + + var lodIndex = i - 1; + currentLODLevel = lodIndex; + + var lodEdgeLengthScale = 1f; + + if ( lodIndex >= 0 ) + { + lodEdgeLengthScale = lodLevels[ lodIndex ].lodEdgeLengthScale; + } + + var lodMG = CreatePatchGeometry(); + lodMG.lodEdgeLength = edgeLength * lodEdgeLengthScale; + numTris += lodMG.vertices.Count; + + lodMG.ApplyTranslation( new Vector3( 0, 0, 0 ) ) ; + mgs.Add( lodMG ); + } + + X_numTriangles = numTris; + + LODLerpingData lerpingData = null; + + if ( lodLerpSteps > 0 ) + { + lerpingData = new LODLerpingData(); + lerpingData.lowerLevelWeights = lowCurve; + lerpingData.higherLevelWeights = highCurve; + lerpingData.lerpSteps = lodLerpSteps; + } + + output.Mesh = MeshGeometry.GenerateTrianglesLODMesh( mgs, lerpingData, false ); + output.Mesh.SurfaceSetMaterial( 0, material ); + + + } + catch ( System.Exception e ) + { + this.LogError( e ); + } + + currentLODLevel = cachedCurrentLODLevel; + } + + + } + + bool debugBlade = false; + + MeshGeometry CreatePatchGeometry() + { + var random = new LCG(); + random.SetSeed( 1712 + seed ); + + var mg = new MeshGeometry(); + + var cellSizeX = ( patchSizeX + patchSize ) / ( bladesX + blades ); + var cellSizeZ = ( patchSizeZ + patchSize ) / ( bladesZ + blades ); + var allBladesX = bladesX + blades; var allBladesZ = bladesZ + blades; @@ -368,6 +471,11 @@ namespace Rokojori var bladeMG = CreateBlade( random, worldPosition ); + + if ( bladeMG.numNormals == 0 || bladeMG.numUVs == 0 ) + { + this.LogInfo( "Invalid mg" ); + } if ( filterValue > filterTreshold ) { @@ -417,6 +525,11 @@ namespace Rokojori } } + if ( mg.numNormals == 0 || mg.numUVs == 0 ) + { + this.LogInfo( "Invalid mg" ); + } + if ( centerPatch ) { @@ -431,6 +544,11 @@ namespace Rokojori var turbulenceAmount = random.Sample( vertexTurbulenceAmount ); var turbulenceScale = Vector3.One * ( vertexTurbulenceScale == null ? 1 : random.Sample( vertexTurbulenceScale ) ); + if ( currentLODLevel != -1 ) + { + turbulenceAmount *= lodLevels[ currentLODLevel ].turbulenceScale; + } + if ( vertexTurbulenceScaleX != null ) { turbulenceScale.X *= random.Sample( vertexTurbulenceScaleX ); @@ -479,16 +597,10 @@ namespace Rokojori mg.ScaleZForY( scaleZForY ); } - - - X_numTriangles = mg.indices.Count / 3; + return mg; - - output.Mesh = mg.GenerateMesh(); } - bool debugBlade = false; - MeshGeometry CreateBlade( RandomEngine random, Vector3 position ) { // if ( debugBlade ) diff --git a/Runtime/Procedural/Assets/Grass/GrassPatchLODLevel.cs b/Runtime/Procedural/Assets/Grass/GrassPatchLODLevel.cs index e073509..fdfb4d6 100644 --- a/Runtime/Procedural/Assets/Grass/GrassPatchLODLevel.cs +++ b/Runtime/Procedural/Assets/Grass/GrassPatchLODLevel.cs @@ -23,8 +23,14 @@ namespace Rokojori [Export( PropertyHint.Range, "0,1")] public float filter = 1; + [Export] + public float turbulenceScale = 0f; + [Export] public Trillean allowTrianglesOnEnd; + [Export] + public float lodEdgeLengthScale = 1; + } } \ No newline at end of file diff --git a/Runtime/Procedural/Assets/Grass/Windy Grass Shader.gdshader b/Runtime/Procedural/Assets/Grass/Windy Grass Shader.gdshader index 31a7e9b..efa6746 100644 --- a/Runtime/Procedural/Assets/Grass/Windy Grass Shader.gdshader +++ b/Runtime/Procedural/Assets/Grass/Windy Grass Shader.gdshader @@ -5,7 +5,6 @@ render_mode blend_mix, depth_draw_opaque, cull_back, diffuse_burley, specular_sc #include "res://addons/rokojori_action_library/Runtime/Shading/Library/Math.gdshaderinc" #include "res://addons/rokojori_action_library/Runtime/Shading/Library/Transform.gdshaderinc" -#include "res://addons/rokojori_action_library/Runtime/Shading/Library/Noise.gdshaderinc" #include "res://addons/rokojori_action_library/Runtime/Shading/Library/Colors.gdshaderinc" uniform vec4 albedo : source_color; diff --git a/Runtime/Procedural/Baking/PixelDensityTool.cs b/Runtime/Procedural/Baking/PixelDensityTool.cs new file mode 100644 index 0000000..2a27df9 --- /dev/null +++ b/Runtime/Procedural/Baking/PixelDensityTool.cs @@ -0,0 +1,61 @@ +using System.Collections; +using System.Collections.Generic; +using Godot; +using System; +using System.Linq; +using System.Threading.Tasks; + + + +namespace Rokojori +{ + [Tool] + [GlobalClass] + public partial class PixelDensityTool:Node + { + [Export] + public float fovDegrees = 60; + + [Export] + public Vector2 screenSize = new Vector2( 1920, 1080 ); + + [Export] + public float startDistance = 1; + + [Export] + public float endDistance = 4000; + + [Export] + public int numEntries = 20; + + [Export] + public float densityTablePower = 2; + + + + [ExportToolButton( "Compute Pixel Density Tables")] + public Callable ExecuteButton => Callable.From( () => + { + var list = new List(); + for ( int i = 0; i < numEntries; i++ ) + { + var t = i / ( float ) ( numEntries - 1f ); + t = Mathf.Pow( t, densityTablePower ); + var distance = Mathf.Lerp( startDistance, endDistance, t ); + + var pixelDensity = Cameras.ComputePixelDensityVertical( fovDegrees, distance, screenSize ); + var minSize = 1f / pixelDensity; + + list.Add( "[" + distance._M()+ "] density: " + pixelDensity._FF() + "px/m - size:" + ( minSize < 1 ? minSize._CM() : minSize._M() ) + " " ); + + } + + distanceToPixelSize = list.ToArray(); + } + ); + + [Export] + public string[] distanceToPixelSize; + + } +} \ No newline at end of file diff --git a/Runtime/Procedural/Baking/PixelDensityTool.cs.uid b/Runtime/Procedural/Baking/PixelDensityTool.cs.uid new file mode 100644 index 0000000..b8efff4 --- /dev/null +++ b/Runtime/Procedural/Baking/PixelDensityTool.cs.uid @@ -0,0 +1 @@ +uid://cgavpqkqwoh8c diff --git a/Runtime/Procedural/Baking/PointMesh/PointCloudGenerator.cs b/Runtime/Procedural/Baking/PointMesh/PointCloudGenerator.cs new file mode 100644 index 0000000..e69de29 diff --git a/Runtime/Procedural/Baking/PointMesh/PointCloudGenerator.cs.uid b/Runtime/Procedural/Baking/PointMesh/PointCloudGenerator.cs.uid new file mode 100644 index 0000000..fdea0af --- /dev/null +++ b/Runtime/Procedural/Baking/PointMesh/PointCloudGenerator.cs.uid @@ -0,0 +1 @@ +uid://dglam3n6d2cwf diff --git a/Runtime/Procedural/Baking/PointMesh/PointMeshBaker.cs b/Runtime/Procedural/Baking/PointMesh/PointMeshBaker.cs new file mode 100644 index 0000000..f5e8f32 --- /dev/null +++ b/Runtime/Procedural/Baking/PointMesh/PointMeshBaker.cs @@ -0,0 +1,86 @@ +using System.Collections; +using System.Collections.Generic; +using Godot; +using System; + + + +namespace Rokojori +{ + [Tool] + [GlobalClass] + public partial class PointMeshBaker:Node + { + [Export] + public Texture2D albedo; + + [Export] + public Texture2D normal; + + [Export] + public MeshInstance3D output; + + [Export] + public int pixelsX; + + [Export] + public int pixelsY; + + [Export] + public Vector2 pivot; + + [Export] + public Vector3 offset; + + [Export] + public Vector3 scale; + + [ExportToolButton( "Bake")] + public Callable BakeButton => Callable.From( () => + { + BakePointMesh(); + } + ); + + public void BakePointMesh() + { + var mg = new MeshGeometry( true, false, true, false ); + mg.customMeshAttributes.Add( new MeshAttributeVector4List( 0 ) ); + mg.normals = null; + + var albedoImage = albedo.GetImage(); + var normalImage = normal.GetImage(); + + var index = 0; + + for ( int x = 0; x < pixelsX; x++ ) + { + for ( int y = 0; y < pixelsY; y++ ) + { + var fx = x / (float) pixelsX; + var fy = 1f - y / (float) pixelsY; + + var position = new Vector3( fx - pivot.X, fy - pivot.Y, 0 ) * scale + offset; + + var colorPosX = Mathf.FloorToInt( fx * albedoImage.GetSize().X ); + var colorPosY = Mathf.FloorToInt( fy * albedoImage.GetSize().Y ); + var color = albedoImage.GetPixel( colorPosX, colorPosY ); + + var normalPosX = Mathf.FloorToInt( fx * normalImage.GetSize().X ); + var normalPosY = Mathf.FloorToInt( fy * normalImage.GetSize().Y ); + var normal = normalImage.GetPixel( normalPosX, normalPosY ); + + mg.AddPoint( position, color.srgbToLinear(), normal.srgbToLinear().ToVector3() * 2.0f - Vector3.One, 0 ); + + // this.LogInfo( "Created point at:", index, position ); + + index ++; + } + } + + output = output == null ? this.CreateChild() : output; + + output.Mesh = mg.GenerateMesh( Mesh.PrimitiveType.Points, null, false ); + } + } +} \ No newline at end of file diff --git a/Runtime/Procedural/Baking/PointMesh/PointMeshBaker.cs.uid b/Runtime/Procedural/Baking/PointMesh/PointMeshBaker.cs.uid new file mode 100644 index 0000000..50b0cce --- /dev/null +++ b/Runtime/Procedural/Baking/PointMesh/PointMeshBaker.cs.uid @@ -0,0 +1 @@ +uid://bx52vt8y36542 diff --git a/Runtime/Procedural/Mesh/MassRenderer.cs b/Runtime/Procedural/Mesh/MassRenderer.cs index a9fce4b..33bccb3 100644 --- a/Runtime/Procedural/Mesh/MassRenderer.cs +++ b/Runtime/Procedural/Mesh/MassRenderer.cs @@ -2,6 +2,7 @@ using System.Collections; using System.Collections.Generic; using Godot; using System; +using System.Linq; @@ -43,7 +44,19 @@ namespace Rokojori [ExportGroup("Outputs")] [Export] - public LODMultiMeshInstance3D multiMeshNode; + public LODMultiMeshInstance3D[] multiMeshNodes; + + [Export] + public float multiMeshSplitSize = 25; + + [Export] + public Vector3 multiMeshSplitScatterRelative = new Vector3( 2, 0, 2 ); + + [Export] + public Vector3 multiMeshSplitScatterScale = new Vector3( 10, 10, 10 ); + + Dictionary multiMeshMapping = new Dictionary(); + [Export] public Node3D meshesContainer; [Export] @@ -112,16 +125,25 @@ namespace Rokojori public void Clear() { - multiMeshNode = Nodes.EnsureValid( multiMeshNode ); + if ( multiMeshNodes != null ) + { + for ( int i = 0 ; i < multiMeshNodes.Length; i++ ) + { + multiMeshNodes[ i ] = Nodes.EnsureValid( multiMeshNodes[ i ] ); + + if ( multiMeshNodes[ i ] != null ) + { + Nodes.RemoveAndDelete( multiMeshNodes[ i ] ); + } + } + + multiMeshNodes = []; + } + meshesContainer = Nodes.EnsureValid( meshesContainer ); combinedMesh = Nodes.EnsureValid( combinedMesh ); - if ( multiMeshNode != null ) - { - multiMeshNode.Multimesh.InstanceCount = 0; - } - if ( meshesContainer != null ) { Nodes.RemoveAndDeleteChildren( meshesContainer ); @@ -135,36 +157,58 @@ namespace Rokojori void CreateMultiMeshes() { - multiMeshNode = Nodes.EnsureValid( multiMeshNode ); - - if ( multiMeshNode == null ) - { - multiMeshNode = this.CreateChild(); - multiMeshNode.Multimesh = new MultiMesh(); - multiMeshNode.Multimesh.TransformFormat = MultiMesh.TransformFormatEnum.Transform3D; - } - - var mm = multiMeshNode.Multimesh; - - mm.Mesh = mesh; - mm.InstanceCount = positions.Length; - - if ( materialOveride != null ) - { - multiMeshNode.MaterialOverride = materialOveride; - } + var instancesSorted = new MapList(); for ( int i = 0; i < positions.Length; i++ ) { - var trsf = Math3D.TRS( positions[ i ], rotations[ i ], scales[ i ] ); - mm.SetInstanceTransform( i, trsf ); - } + var floatIndex = ( positions[ i ] / multiMeshSplitSize ); + floatIndex += Noise.Perlin3( positions[ i ] * multiMeshSplitScatterScale ) * multiMeshSplitScatterRelative; + var index = floatIndex.RoundToInt(); + instancesSorted.Add( index, i ); + } + + var keys = instancesSorted.Keys.ToList(); + var numMultiMeshes = keys.Count; + multiMeshNodes = new LODMultiMeshInstance3D[ numMultiMeshes ]; + + for ( int i = 0; i < numMultiMeshes; i++ ) + { + var multiMeshNode = this.CreateChild(); + multiMeshNode.Multimesh = new MultiMesh(); + multiMeshNode.Multimesh.TransformFormat = MultiMesh.TransformFormatEnum.Transform3D; + + multiMeshNodes[ i ] = multiMeshNode; + + var mm = multiMeshNode.Multimesh; + var meshIndices = instancesSorted[ keys[ i ] ]; + + mm.Mesh = mesh; + mm.InstanceCount = meshIndices.Count; + + if ( materialOveride != null ) + { + multiMeshNode.MaterialOverride = materialOveride; + } + + this.LogInfo( i, ">>", keys[ i ], ">>", meshIndices.Count ); + + for ( int j = 0; j < meshIndices.Count; j++ ) + { + var index = meshIndices[ j ]; + var trsf = Math3D.TRS( positions[ index ], rotations[ index ], scales[ index ] ); + mm.SetInstanceTransform( j, trsf ); + } + + } + } + + void CreateMeshes() { if ( meshesContainer == null ) diff --git a/Runtime/Procedural/Mesh/MaterialSurfaceContainer.cs b/Runtime/Procedural/Mesh/MaterialSurfaceContainer.cs index 3b3af51..fd50fbe 100644 --- a/Runtime/Procedural/Mesh/MaterialSurfaceContainer.cs +++ b/Runtime/Procedural/Mesh/MaterialSurfaceContainer.cs @@ -34,6 +34,18 @@ namespace Rokojori public abstract T GetMaterialInSlot( MaterialSlot slot ) where T:Material; public abstract void SetMaterialInSlot( MaterialSlot slot, Material material ); + public static Material GetActiveFrom( Node3D owner, int surfaceIndex = 0 ) + { + var msc = From( owner, surfaceIndex ); + return msc.GetActiveMaterial(); + } + + public static T GetActiveFrom( Node3D owner, int surfaceIndex = 0 ) where T:Material + { + var msc = From( owner, surfaceIndex ); + return msc.GetActiveMaterial(); + } + public static void SetMaterialInSlot( Node3D owner, int surfaceIndex, MaterialSlot slot, Material material ) { var c = MaterialSurfaceContainer.From( owner, surfaceIndex ); diff --git a/Runtime/Procedural/Mesh/MeshGeometry.cs b/Runtime/Procedural/Mesh/MeshGeometry.cs index 316f910..1f855bf 100644 --- a/Runtime/Procedural/Mesh/MeshGeometry.cs +++ b/Runtime/Procedural/Mesh/MeshGeometry.cs @@ -2,21 +2,280 @@ using System.Collections; using System.Collections.Generic; using Godot; using System; - +using System.Linq; namespace Rokojori { + public class LODLerpingData + { + public Curve lowerLevelWeights = MathX.Curve( 0, 1 ); + public Curve higherLevelWeights = MathX.Curve( 0, 1 ); + + public int lerpSteps = 3; + + public void Sample( float weight, ListView source, List output ) + { + var numSamples = Mathf.Round( weight * source.Count ); + + var sourceCopy = source.SubList(); + sourceCopy.Shuffle( 7 ); + sourceCopy.Shuffle( 3 ); + sourceCopy.Shuffle( 5 ); + sourceCopy.ShuffleMultiple( 5 ); + + for ( int i = 0; i < numSamples; i++ ) + { + output.Add( sourceCopy[ i ] ); + } + } + + public float Sample( ListView lower, ListView higher, List output, int step, float lowerSize, float higherSize ) + { + var t = lerpSteps == 1 ? 0.5f : ( ( step + 1 )/ ( ( lerpSteps + 2 ) - 1f ) ); + + // 4 + // 0 => ( 0 + 1 ) / ( ( 4 + 2 ) -1 ) => 1 / ( 5 ) => 0.2 + // 1 => ( 1 + 1 ) / ( ( 4 + 2 ) -1 ) => 2 / ( 5 ) => 0.4 + // 2 => ( 2 + 1 ) / ( ( 4 + 2 ) -1 ) => 3 / ( 5 ) => 0.6 + // 3 => ( 3 + 1 ) / ( ( 4 + 2 ) -1 ) => 4 / ( 5 ) => 0.8 + + var lowerWeight = lowerLevelWeights.Sample( 1f - t ); + var higherWeight = higherLevelWeights.Sample( t ); + + Sample( lowerWeight, lower, output ); + Sample( higherWeight, higher, output ); + + return Mathf.Lerp( lowerSize, higherSize, t ); + } + } + + public class CustomMeshAttributeList + { + protected int customIndex = 0; + public int index => customIndex; + + protected ArrayMesh.ArrayCustomFormat customFormat; + public ArrayMesh.ArrayCustomFormat format => customFormat; + + public CustomMeshAttributeList( int customIndex, ArrayMesh.ArrayCustomFormat customFormat ) + { + this.customIndex = customIndex; + this.customFormat = customFormat; + } + + public Mesh.ArrayFormat GetFormatFlag() + { + var channel = GetChannelFormat(); + var shift = GetShift(); + + return channel | (Mesh.ArrayFormat)( ( (long)customFormat ) << (int)shift ); + } + + public virtual CustomMeshAttributeList Clone() + { + return null; + } + + + public SurfaceTool.CustomFormat GetSurfaceToolFormat() + { + if ( ArrayMesh.ArrayCustomFormat.RgbaFloat == customFormat ) + { + return SurfaceTool.CustomFormat.RgbaFloat; + } + + if ( ArrayMesh.ArrayCustomFormat.RgbFloat == customFormat ) + { + return SurfaceTool.CustomFormat.RgbFloat; + } + + if ( ArrayMesh.ArrayCustomFormat.RgFloat == customFormat ) + { + return SurfaceTool.CustomFormat.RgFloat; + } + + if ( ArrayMesh.ArrayCustomFormat.RFloat == customFormat ) + { + return SurfaceTool.CustomFormat.RFloat; + } + + return SurfaceTool.CustomFormat.Max; + } + + public ArrayMesh.ArrayType GetTypeSlot() + { + if ( customIndex == 0 ) + { + return ArrayMesh.ArrayType.Custom0; + } + + if ( customIndex == 1 ) + { + return ArrayMesh.ArrayType.Custom1; + } + + if ( customIndex == 2 ) + { + return ArrayMesh.ArrayType.Custom2; + } + + if ( customIndex == 3 ) + { + return ArrayMesh.ArrayType.Custom3; + } + + return ArrayMesh.ArrayType.Max; + + } + + public ArrayMesh.ArrayFormat GetChannelFormat() + { + if ( customIndex == 0 ) + { + return ArrayMesh.ArrayFormat.FormatCustom0; + } + + if ( customIndex == 1 ) + { + return ArrayMesh.ArrayFormat.FormatCustom1; + } + + if ( customIndex == 2 ) + { + return ArrayMesh.ArrayFormat.FormatCustom2; + } + + if ( customIndex == 3 ) + { + return ArrayMesh.ArrayFormat.FormatCustom3; + } + + return 0; + + } + + public long GetShift() + { + if ( customIndex == 0 ) + { + return (long)ArrayMesh.ArrayFormat.FormatCustom0Shift; + } + + if ( customIndex == 1 ) + { + return (long)ArrayMesh.ArrayFormat.FormatCustom1Shift; + } + + if ( customIndex == 2 ) + { + return (long)ArrayMesh.ArrayFormat.FormatCustom2Shift; + } + + if ( customIndex == 3 ) + { + return (long)ArrayMesh.ArrayFormat.FormatCustom3Shift; + } + + return 0; + } + + public virtual void WriteData( Godot.Collections.Array array ) + { + + } + + public virtual void Write( SurfaceTool surfaceTool, int index ) + { + + } + + public virtual void AddTo( CustomMeshAttributeList list, int sourceIndex ) + { + + } + } + + public abstract class CustomMeshAttributeList : CustomMeshAttributeList + { + public List values = new List(); + public CustomMeshAttributeList( int customIndex, ArrayMesh.ArrayCustomFormat customFormat ):base( customIndex, customFormat ) + {} + } + + + public class MeshAttributeVector4List : CustomMeshAttributeList + { + public MeshAttributeVector4List( int customIndex ):base( customIndex, ArrayMesh.ArrayCustomFormat.RgbaFloat ) + {} + + public override CustomMeshAttributeList Clone() + { + var v4 = new MeshAttributeVector4List( customIndex ); + v4.values = Lists.Clone( values ); + + return v4; + } + + public override void WriteData( Godot.Collections.Array array ) + { + var colors = new List(); + + + values.ForEach( + ( v ) => + { + colors.AddRange( new float[]{ v.X, v.Y, v.Z, v.W } ); + } + ); + + RJLog.Log( GetTypeSlot(), customFormat, colors.Count ); + array[ (int) GetTypeSlot() ] = colors.ToArray(); + + + } + + + public override void Write( SurfaceTool tool, int index ) + { + tool.SetCustom( this.index, new Color( values[ index ].X, values[ index ].Y, values[ index ].Z, values[ index ].W) ); + } + + public override void AddTo( CustomMeshAttributeList list, int sourceIndex ) + { + var typeList = list as MeshAttributeVector4List; + + typeList.values.Add( values[ sourceIndex ] ); + } + + } + + + public class MeshGeometry { public string name; + public List vertices = new List(); + public int numVertices => Lists.Size( vertices ); + public List indices = new List(); public List normals; + public int numNormals => Lists.Size( normals ); + public List uvs; + public int numUVs => Lists.Size( uvs ); + public List uv2s; + public int numUV2s => Lists.Size( uv2s ); + public List colors; + public int numColors => Lists.Size( colors ); + + public float lodEdgeLength = 0; + + public List customMeshAttributes = new List(); public int numTriangles => indices.Count / 3; @@ -517,6 +776,19 @@ namespace Rokojori mg.uv2s = Lists.Clone( uv2s ); mg.colors = Lists.Clone( colors ); + mg.lodEdgeLength = lodEdgeLength; + + if ( customMeshAttributes != null ) + { + mg.customMeshAttributes = new List(); + customMeshAttributes.ForEach( + ( m )=> + { + mg.customMeshAttributes.Add( m.Clone() ); + } + ); + } + return mg; } @@ -536,15 +808,41 @@ namespace Rokojori } + public void AddPoint( Vector3 position, Color color, Vector3 normal, int normalIndex ) + { + vertices.Add( position ); + colors.Add( color ); + ( (MeshAttributeVector4List) customMeshAttributes[ normalIndex ] ).values.Add( new Vector4( normal.X, normal.Y, normal.Z, 0.0f ) ); + + indices.Add( indices.Count ); + } + + public void AddPoint( Vector3 position, Color color, Vector3 normal, int normalIndex, Vector2 uv, int uvIndex ) + { + vertices.Add( position ); + colors.Add( color ); + + ( (MeshAttributeVector4List) customMeshAttributes[ normalIndex ] ).values.Add( new Vector4( normal.X, normal.Y, normal.Z, 0.0f ) ); + ( (MeshAttributeVector4List) customMeshAttributes[ uvIndex ] ).values.Add( new Vector4( uv.X, uv.Y, 0.0f, 0.0f ) ); + + indices.Add( indices.Count ); + } - public void Add( MeshGeometry sourceGeometry, Transform3D? optionalTransform = null ) + public void Add( MeshGeometry sourceGeometry, Transform3D? optionalTransform = null, List indicesTarget = null ) { var mappedIndices = new Dictionary(); var rotation = optionalTransform == null ? Quaternion.Identity : ( (Transform3D)optionalTransform ).Basis.GetRotationQuaternion(); var transform = optionalTransform == null ? Transform3D.Identity : (Transform3D)optionalTransform; + var outputIndices = indices; + + if ( indicesTarget != null ) + { + outputIndices = indicesTarget; + } + for ( int i = 0; i < sourceGeometry.indices.Count; i++ ) { var sourceIndex = sourceGeometry.indices[ i ]; @@ -569,10 +867,13 @@ namespace Rokojori vertices.Add( transform * v ); } - - - if ( normals != null && sourceGeometry.normals != null) + if ( normals != null && sourceGeometry.numNormals > 0 ) { + if ( sourceIndex < 0 || sourceIndex >= sourceGeometry.normals.Count ) + { + RJLog.Log( "Normals index bad:", sourceIndex, sourceGeometry.normals.Count ); + } + if ( optionalTransform == null ) { normals.Add( sourceGeometry.normals[ sourceIndex ] ); @@ -584,26 +885,36 @@ namespace Rokojori } - if ( uvs != null && sourceGeometry.uvs != null) + if ( uvs != null && sourceGeometry.numUVs > 0 ) { uvs.Add( sourceGeometry.uvs[ sourceIndex ] ); } - if ( colors != null && sourceGeometry.colors != null) - { - colors.Add( sourceGeometry.colors[ sourceIndex ] ); - } - - if ( uv2s != null && sourceGeometry.uv2s != null) + if ( uv2s != null && sourceGeometry.numUV2s > 0 ) { uv2s.Add( sourceGeometry.uv2s[ sourceIndex ] ); } + if ( colors != null && sourceGeometry.numColors > 0 ) + { + colors.Add( sourceGeometry.colors[ sourceIndex ] ); + } + + + if ( Lists.Size( customMeshAttributes ) == Lists.Size( sourceGeometry.customMeshAttributes ) ) + { + for ( int j = 0; j < customMeshAttributes.Count; j++ ) + { + var customList = customMeshAttributes[ j ]; + var sourceCustomList = sourceGeometry.customMeshAttributes[ j ]; + sourceCustomList.AddTo( customList, sourceIndex ); + } + } mappedIndices[ sourceIndex ] = newIndex; } - indices.Add( mappedIndices[ sourceIndex ] ); + outputIndices.Add( mappedIndices[ sourceIndex ] ); } } @@ -1043,19 +1354,49 @@ namespace Rokojori } - - - public ArrayMesh GenerateMesh( Mesh.PrimitiveType type = Mesh.PrimitiveType.Triangles, ArrayMesh arrayMesh = null, bool generateTangents = true ) + + public static ArrayMesh GenerateLODMesh( List + mgs, Mesh.PrimitiveType type = Mesh.PrimitiveType.Triangles, ArrayMesh arrayMesh = null, + bool generateTangents = true, LODLerpingData lerpingData = null ) + { + return mgs[ 0 ].GenerateMesh( type, arrayMesh, generateTangents, mgs.Sub( 1 ), lerpingData ); + } + + public static ArrayMesh GeneratePointsLODMesh( List mgs, LODLerpingData lerpingData = null, bool generateTangents = true ) + { + return GenerateLODMesh( mgs, Mesh.PrimitiveType.Points, null, generateTangents, lerpingData ); + } + + public static ArrayMesh GenerateLinesLODMesh( List mgs, LODLerpingData lerpingData = null, bool generateTangents = true ) + { + return GenerateLODMesh( mgs, Mesh.PrimitiveType.Lines, null, generateTangents, lerpingData ); + } + + public static ArrayMesh GenerateTrianglesLODMesh( List mgs, LODLerpingData lerpingData = null, bool generateTangents = true ) + { + return GenerateLODMesh( mgs, Mesh.PrimitiveType.Triangles, null, generateTangents, lerpingData ); + } + + public ArrayMesh GenerateMesh( + Mesh.PrimitiveType type = Mesh.PrimitiveType.Triangles, ArrayMesh arrayMesh = null, + bool generateTangents = true, List lods = null, LODLerpingData lerpingData = null ) { if ( arrayMesh == null ) { arrayMesh = new ArrayMesh(); } + var lodDictionary = new Godot.Collections.Dictionary(); + + + _GenerateLODs( type, lods, lodDictionary, lerpingData ); + var surfaceArray = new Godot.Collections.Array(); surfaceArray.Resize( (int) Mesh.ArrayType.Max ); + var flags = Mesh.ArrayFormat.FormatVertex | Mesh.ArrayFormat.FormatIndex; + if ( vertices != null && vertices.Count != 0 ) { surfaceArray[ (int) Mesh.ArrayType.Vertex ] = vertices.ToArray(); @@ -1064,29 +1405,49 @@ namespace Rokojori if ( normals != null && normals.Count != 0 ) { surfaceArray[ (int) Mesh.ArrayType.Normal ] = normals.ToArray(); + flags |= Mesh.ArrayFormat.FormatNormal; } if ( uvs != null && uvs.Count != 0 ) { surfaceArray[ (int) Mesh.ArrayType.TexUV ] = uvs.ToArray(); + flags |= Mesh.ArrayFormat.FormatTexUV; } if ( uv2s != null && uv2s.Count != 0 ) { surfaceArray[ (int) Mesh.ArrayType.TexUV2 ] = uv2s.ToArray(); + flags |= Mesh.ArrayFormat.FormatTexUV2; } if ( colors != null && colors.Count != 0 ) { surfaceArray[ (int) Mesh.ArrayType.Color ] = colors.ToArray(); + flags |= Mesh.ArrayFormat.FormatColor; } if ( indices != null && indices.Count != 0 ) { surfaceArray[ (int) Mesh.ArrayType.Index ] = indices.ToArray(); + flags |= Mesh.ArrayFormat.FormatIndex; + } + + customMeshAttributes.ForEach( + c => + { + flags |= c.GetFormatFlag(); + c.WriteData( surfaceArray ); + } + ); + + if ( lodDictionary != null && lodDictionary.Count > 0 ) + { + var keys = Lists.From( lodDictionary.Keys ); + RJLog.Log( "LODS:", keys ); } - arrayMesh.AddSurfaceFromArrays( Mesh.PrimitiveType.Triangles, surfaceArray ); + RJLog.Log( "Flags:", flags ); + arrayMesh.AddSurfaceFromArrays( type, surfaceArray, null, lodDictionary, flags ); if ( generateTangents ) { @@ -1094,7 +1455,135 @@ namespace Rokojori } return arrayMesh; + } + void _GenerateLODs( Mesh.PrimitiveType type, List lods, + Godot.Collections.Dictionary lodDictionary, LODLerpingData lerpingData ) + { + if ( lods == null ) + { + return; + } + + RJLog.Log( "Creating mesh with LODs", vertices.Count ); + + var higherIndices = indices; + var higherIndicesLength = indices.Count; + var higherEdgeLength = this.lodEdgeLength; + + var primitiveLength = 3; + + if ( Mesh.PrimitiveType.Lines == type ) + { + primitiveLength = 2; + } + else if ( Mesh.PrimitiveType.Points == type ) + { + primitiveLength = 1; + } + + + var lodIndex = -1; + lods.ForEach( + ( lod )=> + { + lodIndex ++; + + + var lodIndices = new List(); + Add( lod, null, lodIndices ); + + if ( lerpingData != null ) + { + var lowOffsetIndex = lodIndices.Count / primitiveLength; + var lowIndices = Lists.Create( lowOffsetIndex, i => i ); + var highIndices = Lists.Create( higherIndicesLength / primitiveLength, i => i + lowOffsetIndex ); + + for ( int s = 0; s < lerpingData.lerpSteps; s ++ ) + { + var i = ( lerpingData.lerpSteps - 1 ) - s; + var lerpedGenericOutput = new List(); + + var lerpedEdgeLength = lerpingData.Sample( lowIndices.View(), highIndices.View(), + lerpedGenericOutput, i, lod.lodEdgeLength, higherEdgeLength ); + + var lerpedPrimitiveIndices = new List(); + + var evaluatedJ = 0; + var evaluatedK = 0; + var isLow = false; + var offset = 0; + + try + { + for ( int j = 0; j < lerpedGenericOutput.Count; j++ ) + { + evaluatedJ = j; + var primitiveIndex = lerpedGenericOutput[ j ]; + isLow = primitiveIndex < lowOffsetIndex; + + if ( primitiveIndex < lowOffsetIndex ) + { + offset = primitiveIndex * primitiveLength; + + for ( int k = 0; k < primitiveLength; k ++ ) + { + evaluatedK = k; + lerpedPrimitiveIndices.Add( lodIndices[ offset + k ] ); + } + } + else + { + offset = ( primitiveIndex - lowOffsetIndex ) * primitiveLength; + + for ( int k = 0; k < primitiveLength; k ++ ) + { + evaluatedK = k; + lerpedPrimitiveIndices.Add( higherIndices[ offset + k ] ); + } + } + + } + } + catch ( System.Exception e ) + { + RJLog.Log( + "LodIndex", lodIndex, + "Lerped Output Size:", lerpedGenericOutput.Count, + "j", evaluatedJ, + "k", evaluatedK, + "isLow", isLow, + "offset", offset, + "indices", indices.Count, + "indices", higherIndices.Count, + "primitiveLength", primitiveLength, + "lowOffsetIndex", lowOffsetIndex, + "Low Size", lodIndices.Count, + "High Size", higherIndicesLength + ); + RJLog.Error( e ); + } + + RJLog.Log( "Adding lod", lods.IndexOf( lod ), i, "size:", lerpedEdgeLength, "verts:", lerpedPrimitiveIndices.Count ); + lodDictionary[ lerpedEdgeLength ] = lerpedPrimitiveIndices.ToArray(); + + } + } + + higherIndices = lodIndices; + higherIndicesLength = lodIndices.Count; + higherEdgeLength = lod.lodEdgeLength; + + + RJLog.Log( "Adding lod", lods.IndexOf( lod ), "full", "size:", lod.lodEdgeLength, "verts:", lodIndices.Count ); + lodDictionary[ lod.lodEdgeLength ] = lodIndices.ToArray(); + } + ); + + RJLog.Log( "Added vertices", vertices.Count ); + } + + } } \ No newline at end of file diff --git a/Runtime/Procedural/Scatter/Generators/GenerateInBox.cs b/Runtime/Procedural/Scatter/Generators/GenerateInBox.cs index 6fe0536..5e6b0e9 100644 --- a/Runtime/Procedural/Scatter/Generators/GenerateInBox.cs +++ b/Runtime/Procedural/Scatter/Generators/GenerateInBox.cs @@ -34,8 +34,8 @@ namespace Rokojori if ( snapToWorldGrid ) { var snapping = Vector3.One / density; - minPosition = Math3D.SnapCeiled( minPosition, snapping ); - maxPosition = Math3D.SnapFloored( maxPosition, snapping ); + minPosition = minPosition.SnapCeiled( snapping ); + maxPosition = maxPosition.SnapFloored( snapping ); } var pointsX = Mathf.CeilToInt( ( maxPosition.X - minPosition.X ) * density ); diff --git a/Runtime/Procedural/Scatter/Generators/GeneratorEntry.cs b/Runtime/Procedural/Scatter/Generators/GeneratorEntry.cs index 072e74a..6027d2d 100644 --- a/Runtime/Procedural/Scatter/Generators/GeneratorEntry.cs +++ b/Runtime/Procedural/Scatter/Generators/GeneratorEntry.cs @@ -26,6 +26,9 @@ namespace Rokojori [Export] public bool useInstancing = false; + [Export] + public float instancingSplitSize = 25; + protected PackedScene _cachedNode3DScene; public PackedScene GetPackedScene() diff --git a/Runtime/Procedural/Scatter/Generators/GeneratorScatterer.cs b/Runtime/Procedural/Scatter/Generators/GeneratorScatterer.cs index b3a77a2..43bae04 100644 --- a/Runtime/Procedural/Scatter/Generators/GeneratorScatterer.cs +++ b/Runtime/Procedural/Scatter/Generators/GeneratorScatterer.cs @@ -63,6 +63,7 @@ namespace Rokojori p.scene = gs.GetPackedScene() != null ? gs.GetPackedScene() : packedScene; p.parent = gs.container != null ? gs.container : container; p.instanced = gs.useInstancing; + p.instanceSplitSize = gs.instancingSplitSize; } } diff --git a/Runtime/Procedural/Scatter/ScatterPoint.cs b/Runtime/Procedural/Scatter/ScatterPoint.cs index 2ccbd25..796a9da 100644 --- a/Runtime/Procedural/Scatter/ScatterPoint.cs +++ b/Runtime/Procedural/Scatter/ScatterPoint.cs @@ -10,11 +10,13 @@ namespace Rokojori public class ScatterPoint:PointData { public bool instanced = false; + public float instanceSplitSize = 25; protected Scatterer _creator; public Scatterer creator => _creator; protected int _creatorID; public int creatorID => _creatorID; + public ScatterPoint( Scatterer creator, int id ) { this._creator = creator; diff --git a/Runtime/Procedural/Scatter/Scatterer.cs b/Runtime/Procedural/Scatter/Scatterer.cs index 6e5f794..b43a80e 100644 --- a/Runtime/Procedural/Scatter/Scatterer.cs +++ b/Runtime/Procedural/Scatter/Scatterer.cs @@ -343,6 +343,7 @@ namespace Rokojori c.materialOveride = mwm.material; c.mesh = mwm.mesh; + c.multiMeshSplitSize = sp.instanceSplitSize; _instancedMassRenderers.Add( mwm.mesh, c ); diff --git a/Runtime/Reallusion/CCImportFile/CCCustomShader.cs b/Runtime/Reallusion/CCImportFile/CCCustomShader.cs new file mode 100644 index 0000000..9e8b7b5 --- /dev/null +++ b/Runtime/Reallusion/CCImportFile/CCCustomShader.cs @@ -0,0 +1,196 @@ + +using System.Diagnostics; +using System.Collections; +using System.Collections.Generic; +using System; +using Godot; + + +namespace Rokojori.Reallusion +{ + public class CCCustomShader:CCImportFileBase + { + public string name; + + + public CCCustomShader( CCImportFile file, string name ):base( file ) + { + this.name = name; + } + + JSONObject _jsonObject; + + public void ReadFrom( JSONObject jsonObject ) + { + _jsonObject = jsonObject; + + if ( name == "RLEyeOcclusion" ) + { + ReadEyeOcclusion( jsonObject ); + } + + if ( name == "RLEye" ) + { + ReadEye( jsonObject ); + } + } + + public CCJSONProperty> shadowTopColor = new CCJSONProperty>( "Shadow Color"); + public CCJSONProperty> shadowBottomColor = new CCJSONProperty>( "Shadow2 Color"); + + void ReadEyeOcclusion( JSONObject jsonObject ) + { + var variable = jsonObject.GetObject( "Variable" ); + + shadowTopColor.Read( variable ); + shadowBottomColor.Read( variable ); + } + + public float GetFloatVariable( string name, float alternative = 0 ) + { + var value = _jsonObject.ByPath( "Variable", name ); + + if ( value == null ) + { + return alternative; + } + + return value.floatValue; + } + + public List GetFloatArrayVariable( string name ) + { + var value = _jsonObject.ByPath( "Variable", name ); + + return value.AsFloatList(); + } + + public Vector3 GetVector3Variable( string name ) + { + var value = GetFloatArrayVariable( name ); + + var v = Vector3.Zero; + v.X = value[ 0 ]; + v.Y = value[ 1 ]; + v.Z = value[ 2 ]; + + return v; + } + + public Color GetColorVariable( string name, float basis, bool sRGB ) + { + var value = GetFloatArrayVariable( name ); + + var color = ColorX.From( value, basis ); + + if ( sRGB ) + { + color = color.linearToSRGB(); + } + + return color; + } + + public Vector3 GetColorVariableAsVector3( string name, float basis, bool sRGB ) + { + var color = GetColorVariable( name, basis, sRGB ); + return new Vector3( color.R, color.G, color.B ); + } + + public string GetImageTexturePath( string name ) + { + var value = _jsonObject.ByPath( "Image", name, "Texture Path" ); + + if ( value == null ) + { + return null; + } + + return value.stringValue; + + } + + public Texture2D GetImageTexture( string name ) + { + var path = GetImageTexturePath( name ); + return GetTextureFromRelativePath( path ); + } + + Texture2D GetTextureFromRelativePath( string relativePath ) + { + var rootDirectoryPath = FilePath.Absolute( importFile.directory ); + var relativeFilePath = rootDirectoryPath.MakeRelative( relativePath ); + + try + { + var texture = ResourceLoader.Load( relativeFilePath.fullPath ); + + return texture; + } + catch( System.Exception e ) + { + RJLog.Error( "Could not load texture", relativePath, relativeFilePath.fullPath ); + RJLog.Error( e ); + } + + return null; + } + + + void ReadEye( JSONObject jsonObject ) + { + + } + + /* EYE */ + + public Texture2D GetIrisNormal() + { + return GetImageTexture( "Iris Normal" ); + } + + /* SKIN */ + + public Texture2D GetMicroNormal() + { + return GetImageTexture( "MicroNormal" ); + } + + public Texture2D GetMicroNormalMask() + { + return GetImageTexture( "MicroNormalMask" ); + } + + public Texture2D GetSpecularMask() + { + return GetImageTexture( "Specular Mask" ); + } + + public Texture2D GetSSSMap() + { + return GetImageTexture( "SSS Map" ); + } + + public Texture2D GetTransmisionMap() + { + return GetImageTexture( "Transmission Map" ); + } + + /* HAIR */ + + public Texture2D GetHairRootMap() + { + return GetImageTexture( "Hair Root Map" ); + } + + public Texture2D GetHairFlowMap() + { + return GetImageTexture( "Hair Flow Map" ); + } + + public Texture2D GetHairIDMap() + { + return GetImageTexture( "Hair ID Map" ); + } + } +} \ No newline at end of file diff --git a/Runtime/Reallusion/CCImportFile/CCCustomShader.cs.uid b/Runtime/Reallusion/CCImportFile/CCCustomShader.cs.uid new file mode 100644 index 0000000..4157f30 --- /dev/null +++ b/Runtime/Reallusion/CCImportFile/CCCustomShader.cs.uid @@ -0,0 +1 @@ +uid://b8uk66gggbs48 diff --git a/Runtime/Reallusion/CCImportFile/CCImportFile.cs b/Runtime/Reallusion/CCImportFile/CCImportFile.cs new file mode 100644 index 0000000..70f879e --- /dev/null +++ b/Runtime/Reallusion/CCImportFile/CCImportFile.cs @@ -0,0 +1,93 @@ + +using System.Diagnostics; +using System.Collections; +using System.Collections.Generic; +using System; +using Godot; + + +namespace Rokojori.Reallusion +{ + public class CCImportFile:CCImportFileBase + { + public string name; + + public CCObjectInfo ccObject; + public List messages = new List(); + public string path; + + public string directory => FilePath.Absolute( path ).CreateAbsoluteParent().fullPath; + + public CCImportFile():base( null ) + { + _importFile = this; + } + + public void _Error( params object[] items ) + { + Messages.Error( messages, RJLog.GetLogString( items ) ); + } + + public void _Info( params object[] items ) + { + Messages.Info( messages, RJLog.GetLogString( items ) ); + } + + public void ReadFrom( JSONData data ) + { + if ( data == null ) + { + Error( "Root is null" ); + return; + } + + if ( data.dataType != JSONDataType.OBJECT ) + { + Error( "Invalid root, not an object, actual type: ", data.dataType ); + return; + } + + + var root = data.AsObject(); + + if ( root.keys.Count == 0 ) + { + Error( "Root has no children" ); + return; + } + + if ( root.keys.Count > 1 ) + { + Error( "Root has more than one child" ); + return; + } + + var rootKey = root.keys[ 0 ]; + + name = rootKey; + + Info( "Found root object:", name ); + + var rootObject = root.GetObject( rootKey ); + + var objectKey = "Object"; + + if ( ! ValidateMember( rootObject, objectKey, "Checking cc object" ) ) + { + return; + } + + var objectData = rootObject.GetObject( objectKey ); + + ccObject = new CCObjectInfo( this ); + + + ccObject.ReadFrom( objectData ); + + + } + + + + } +} \ No newline at end of file diff --git a/Runtime/Reallusion/CCImportFile/CCImportFile.cs.uid b/Runtime/Reallusion/CCImportFile/CCImportFile.cs.uid new file mode 100644 index 0000000..97807d9 --- /dev/null +++ b/Runtime/Reallusion/CCImportFile/CCImportFile.cs.uid @@ -0,0 +1 @@ +uid://bu7vm4bmr6ji1 diff --git a/Runtime/Reallusion/CCImportFile/CCImportFileBase.cs b/Runtime/Reallusion/CCImportFile/CCImportFileBase.cs new file mode 100644 index 0000000..e935af0 --- /dev/null +++ b/Runtime/Reallusion/CCImportFile/CCImportFileBase.cs @@ -0,0 +1,67 @@ + + + +namespace Rokojori.Reallusion +{ + public class CCImportFileBase + { + protected CCImportFile _importFile; + public CCImportFile importFile => _importFile; + + + public CCImportFileBase( CCImportFile importFile ) + { + _importFile = importFile; + } + + public virtual void Error( params object[] items ) + { + importFile._Error( items ); + } + + public virtual void Info( params object[] items ) + { + importFile._Info( items ); + } + + + public bool ValidateMember( JSONData parentNode, string name, string contextInfo, JSONDataType jsonType = JSONDataType.OBJECT ) + { + if ( parentNode == null ) + { + Error( contextInfo, "parent node is null" ); + return false; + } + + if ( ! parentNode.isObject ) + { + Error( contextInfo, "parent node is not an object" ); + return false; + } + + if ( ! parentNode.isObject ) + { + Error( contextInfo, "parent node is not an object" ); + return false; + } + + var parentObject = parentNode.AsObject(); + + if ( ! parentObject.HasKey( name ) ) + { + Error( contextInfo, "parent node doesn't have the key:", name ); + return false; + } + + var childData = parentObject.Get( name ); + + if ( childData.dataType != jsonType ) + { + Error( contextInfo, "node doesn't have the expected type " + jsonType, "it has:", childData.dataType ); + return false; + } + + return true; + } + } +} \ No newline at end of file diff --git a/Runtime/Reallusion/CCImportFile/CCImportFileBase.cs.uid b/Runtime/Reallusion/CCImportFile/CCImportFileBase.cs.uid new file mode 100644 index 0000000..0a9255c --- /dev/null +++ b/Runtime/Reallusion/CCImportFile/CCImportFileBase.cs.uid @@ -0,0 +1 @@ +uid://c17odjuuq0md diff --git a/Runtime/Reallusion/CCImportFile/CCJSONProperty.cs b/Runtime/Reallusion/CCImportFile/CCJSONProperty.cs new file mode 100644 index 0000000..967ccda --- /dev/null +++ b/Runtime/Reallusion/CCImportFile/CCJSONProperty.cs @@ -0,0 +1,92 @@ + +using System.Diagnostics; +using System.Collections; +using System.Collections.Generic; +using System; +using Godot; + +namespace Rokojori.Reallusion +{ + public class CCJSONProperty + { + protected string _name; + public string name => _name; + + public T value; + public bool exists = false; + + protected Func _customReader; + + public CCJSONProperty( string name ) + { + _name = name; + } + + public void SetReader(Func reader = null ) + { + _name = name; + _customReader = reader; + } + + + public T GetOr( T alternative ) + { + if ( ! exists ) + { + return alternative; + } + + return value; + } + + + + + + + public void Read( JSONObject root ) + { + if ( ! root.HasKey( _name ) ) + { + exists = false; + return; + } + + var data = root.Get( _name ); + + if ( _customReader != null ) + { + Set( _customReader( data ) ); + } + else if ( Is( typeof( int ) ) ) + { + Set( data.intValue ); + } + else if ( Is( typeof( float ) ) ) + { + Set( data.floatValue ); + } + else if ( Is( typeof( string ) ) ) + { + Set( data.stringValue ); + } + else if ( Is( typeof( List ) ) ) + { + Set( data.AsArray().AsFloatList() ); + } + + exists = true; + } + + void Set( object value ) + { + this.value = (T) value; + } + + bool Is( Type type ) + { + return typeof( T ) == type; + } + + } +} \ No newline at end of file diff --git a/Runtime/Reallusion/CCImportFile/CCJSONProperty.cs.uid b/Runtime/Reallusion/CCImportFile/CCJSONProperty.cs.uid new file mode 100644 index 0000000..315d502 --- /dev/null +++ b/Runtime/Reallusion/CCImportFile/CCJSONProperty.cs.uid @@ -0,0 +1 @@ +uid://cwsu3thtluxci diff --git a/Runtime/Reallusion/CCImportFile/CCMaterialGenerator/CCMaterialGenerator.cs b/Runtime/Reallusion/CCImportFile/CCMaterialGenerator/CCMaterialGenerator.cs new file mode 100644 index 0000000..c9ed89b --- /dev/null +++ b/Runtime/Reallusion/CCImportFile/CCMaterialGenerator/CCMaterialGenerator.cs @@ -0,0 +1,20 @@ + +using System.Diagnostics; +using System.Collections; +using System.Collections.Generic; +using System; +using Godot; + + +namespace Rokojori.Reallusion +{ + [Tool] + [GlobalClass] + public partial class CCMaterialGenerator:Resource + { + public virtual Material CreateMaterial( CCMaterialInfo materialInfo, CCMaterialSettings settings ) + { + return materialInfo.CreateMaterial( settings ); + } + } +} \ No newline at end of file diff --git a/Runtime/Reallusion/CCImportFile/CCMaterialGenerator/CCMaterialGenerator.cs.uid b/Runtime/Reallusion/CCImportFile/CCMaterialGenerator/CCMaterialGenerator.cs.uid new file mode 100644 index 0000000..8b0644f --- /dev/null +++ b/Runtime/Reallusion/CCImportFile/CCMaterialGenerator/CCMaterialGenerator.cs.uid @@ -0,0 +1 @@ +uid://dri0mpp4tlwbt diff --git a/Runtime/Reallusion/CCImportFile/CCMaterialInfo.cs b/Runtime/Reallusion/CCImportFile/CCMaterialInfo.cs new file mode 100644 index 0000000..20b7cd4 --- /dev/null +++ b/Runtime/Reallusion/CCImportFile/CCMaterialInfo.cs @@ -0,0 +1,552 @@ + +using System.Diagnostics; +using System.Collections; +using System.Collections.Generic; +using System; +using Godot; + + +namespace Rokojori.Reallusion +{ + public class CCMaterialInfo:CCImportFileBase + { + + public string name; + + + public CCJSONProperty materialType = new CCJSONProperty( "Material Type" ); + public CCJSONProperty multiUVIndex = new CCJSONProperty( "MultiUV Index" ); + public CCJSONProperty nodeType = new CCJSONProperty( "Node Type" ); + public CCJSONProperty twoSide = new CCJSONProperty( "Two Side" ); + public CCJSONProperty> diffuseColor = new CCJSONProperty>( "Diffuse Color" ); + public CCJSONProperty> ambientColor = new CCJSONProperty>( "Ambient Color" ); + public CCJSONProperty> specularColor = new CCJSONProperty>( "Specular Color" ); + public CCJSONProperty opacity = new CCJSONProperty( "Opacity" ); + public CCJSONProperty selfIllumination = new CCJSONProperty( "Self Illumination" ); + public CCJSONProperty specular = new CCJSONProperty( "Specular" ); + public CCJSONProperty glossiness = new CCJSONProperty( "Glossiness" ); + + public CCJSONProperty> textures = new CCJSONProperty>( "Textures" ); + + public CCJSONProperty customShader = new CCJSONProperty( "Custom Shader" ); + + public CCJSONProperty subsurfaceScatter = new CCJSONProperty( "Subsurface Scatter" ); + + public CCMaterialInfo( CCImportFile ccImportFile, string name ):base( ccImportFile ) + { + this.name = name; + + textures.SetReader( + ( data ) => + { + var list = new List(); + var obj = data.AsObject(); + + Info( "Reading textures:", obj.keys ); + + obj.keys.ForEach( + k => + { + var ti = CCTextureInfo.Create( importFile, k, obj.Get( k ) ); + Info( "Adding texture for material", name, ti.name, ti.texturePath.value ); + list.Add( ti ); + } + ); + + + return list; + } + ); + + customShader.SetReader( + ( data ) => + { + var shaderName = data.AsObject().Get( "Shader Name" ).stringValue; + var cs = new CCCustomShader( importFile, shaderName ); + + Info( "Found Shader", shaderName ); + + cs.ReadFrom( data.AsObject() ); + + return cs; + + } + ); + + subsurfaceScatter.SetReader( + ( data ) => + { + var ss = new CCSubsurfaceScatter( importFile ); + + ss.ReadFrom( data.AsObject() ); + + return ss; + + } + ); + } + + public void ReadFrom( JSONObject root ) + { + materialType.Read( root ); + multiUVIndex.Read( root ); + nodeType.Read( root ); + twoSide.Read( root ); + diffuseColor.Read( root ); + ambientColor.Read( root ); + specularColor.Read( root ); + opacity.Read( root ); + selfIllumination.Read( root ); + textures.Read( root ); + customShader.Read( root ); + subsurfaceScatter.Read( root ); + } + + public bool IsCustomShader( string shaderName ) + { + return customShader.exists && customShader.value.name == shaderName; + } + + public Material CreateMaterial( CCMaterialSettings settings ) + { + RJLog.Log( "Custom Shader", customShader.exists ? customShader.value.name : "none" ); + + if ( settings.materialType.shaderType == CCMaterialType.CCShaderType.RLHair ) + { + return CreateHairMaterial( settings ); + } + + if ( settings.materialType.shaderType == CCMaterialType.CCShaderType.RLEyeOcclusion ) + { + return CreateEyeOcclusionMaterial( settings ); + } + + if ( settings.materialType.shaderType == CCMaterialType.CCShaderType.RLEye ) + { + return CreateEyeMaterial( settings ); + } + + + if ( + settings.materialType.shaderType == CCMaterialType.CCShaderType.RLSkin || + settings.materialType.shaderType == CCMaterialType.CCShaderType.RLHead + ) + { + + return CreateSkinMaterial( settings ); + } + + if ( HasOpacityTexture() ) + { + return CreateOpacityMaterial( settings ); + } + + + return CreatePBRMaterial( settings ); + } + + + public Color GetAlbedoColor( float gamma ) + { + var a = opacity.GetOr( 1.0f ); + var color = ColorX.From( diffuseColor.GetOr( new List{ 255, 255, 255, 255 } ), 255 ); + color.A *= a; + + color = color.Gamma( gamma ); + + return color; + } + + public bool HasOpacityTexture() + { + if ( textures.exists ) + { + var opacityTexture = textures.value.Find( t => t.name == CCTextureInfo.Opacity ); + return opacityTexture != null; + } + + return false; + } + + public bool IsTransparent() + { + return HasOpacityTexture() || GetAlbedoColor( 1.0f ).A < 1.0f; + } + + + public CCMaterialType GetMaterialType() + { + var materialType = new CCMaterialType(); + + materialType.shaderType = CCMaterialType.CCShaderType.PBR; + + if ( customShader.exists ) + { + materialType.shaderType = ReflectionHelper.StringToEnum( customShader.value.name, CCMaterialType.CCShaderType.Unknown ); + } + + return materialType; + } + + + public StandardMaterial3D CreatePBRMaterial( CCMaterialSettings settings, bool skin = false ) + { + var material = new StandardMaterial3D(); + + material.CullMode = twoSide.GetOr( false ) ? BaseMaterial3D.CullModeEnum.Disabled : BaseMaterial3D.CullModeEnum.Back; + + material.Metallic = 1.0f; + material.AlbedoColor = GetAlbedoColor( settings.configuration.gammaForAlbedoColor ); + material.Transparency = IsTransparent() ? BaseMaterial3D.TransparencyEnum.Alpha : BaseMaterial3D.TransparencyEnum.Disabled; + material.MetallicSpecular = skin ? 0.0f : 0.5f; + + + if ( skin && subsurfaceScatter.exists) + { + material.SubsurfScatterEnabled = true; + material.SubsurfScatterStrength = subsurfaceScatter.value.radius.value / 3.0f; + material.SubsurfScatterSkinMode = true; + } + + if ( ! textures.exists ) + { + return material; + } + + textures.value.ForEach( + ( t ) => + { + if ( t.isBaseColor ) + { + material.AlbedoTexture = t.GetTexture(); + var uv1Scale = t.tiling.GetOr( new List(){ 1, 1 } ); + var uv1Offset = t.offset.GetOr( new List(){ 0, 0 } ); + material.Uv1Scale = new Vector3( uv1Scale[ 0 ], uv1Scale[ 1 ], 1 ); + material.Uv1Offset = new Vector3( uv1Offset[ 0 ], uv1Offset[ 1 ], 1 ); + } + else if ( t.isNormal ) + { + material.NormalTexture = t.GetTexture(); + material.NormalEnabled = true; + } + else if ( t.isRoughness ) + { + material.RoughnessTexture = t.GetTexture(); + material.RoughnessTextureChannel = BaseMaterial3D.TextureChannel.Red; + } + else if ( t.isMetallic ) + { + material.MetallicTexture = t.GetTexture(); + material.MetallicTextureChannel = BaseMaterial3D.TextureChannel.Red; + } + else if ( t.isGlow ) + { + material.EmissionEnabled = true; + material.EmissionTexture = t.GetTexture(); + } + else if ( t.isAO ) + { + material.AOEnabled = true; + material.AOTexture = t.GetTexture(); + material.AOTextureChannel = BaseMaterial3D.TextureChannel.Red; + } + } + ); + + return material; + } + + public ShaderMaterial CreateEyeOcclusionMaterial( CCMaterialSettings settings ) + { + var eyeOcclusionMaterial = new CCEyeOcclusionMaterial(); + + eyeOcclusionMaterial.shadowTopColor.Set( + ColorX.From( customShader.value.shadowTopColor.value, 255.0f ) + ); + + eyeOcclusionMaterial.shadowBottomColor.Set( + ColorX.From( customShader.value.shadowBottomColor.value, 255.0f ) + ); + + return eyeOcclusionMaterial; + } + + public ShaderMaterial CreateEyeMaterial( CCMaterialSettings settings ) + { + var eyeMaterial = new CCEyeMaterial(); + + textures.value.ForEach( + ( t ) => + { + if ( t.isBaseColor ) + { + eyeMaterial.textureAlbedo.Set( t.GetTexture() ); + + } + } + ); + + eyeMaterial.textureNormal.Set( customShader.value.GetIrisNormal() ); + + return eyeMaterial; + } + + public ShaderMaterial CreateSkinMaterial( CCMaterialSettings settings ) + { + var skinMaterial = new CCSkinMaterial(); + CustomMaterial outputMaterial = skinMaterial; + + if ( settings.configuration.transmissiveSkin ) + { + outputMaterial = new CCSkinTransmissiveMaterial(); + } + + if ( settings.configuration.applyAlbedoNoise ) + { + var skinScale = 2.0f; + + if ( name.EndsWith( "Head" ) ) + { + skinScale = 1.0f; + } + else if ( name.EndsWith( "Body" ) ) + { + skinScale = 5.0f; + } + + + skinMaterial.albedoNoiseUvScale.AssignFor( outputMaterial, skinScale ); + skinMaterial.albedoNoiseOffset.AssignFor( outputMaterial, settings.configuration.albedoNoiseBrightness ); + skinMaterial.albedoNoise.AssignFor( outputMaterial, settings.configuration.albedoNoiseAmount ); + skinMaterial.textureAlbedoNoise.AssignFor( outputMaterial, settings.configuration.skinAlbedoNoise ); + } + + skinMaterial.albedo.AssignFor( outputMaterial, GetAlbedoColor( settings.configuration.gammaForAlbedoColor ) ); + skinMaterial.specular.AssignFor( outputMaterial, 0.5f ); + + + var tiling = customShader.value.GetFloatVariable( "MicroNormal Tiling", 20f ); + skinMaterial.uv1Scale.AssignFor( outputMaterial, Vector3.One ); + skinMaterial.uv2Scale.AssignFor( outputMaterial, Vector3.One * tiling ); + + skinMaterial.microNormalTexture.AssignFor( outputMaterial, customShader.value.GetMicroNormal() ); + skinMaterial.microNormalMaskTexture.AssignFor( outputMaterial, customShader.value.GetMicroNormalMask() ); + skinMaterial.microNormalScale.AssignFor( outputMaterial, customShader.value.GetFloatVariable( "MicroNormal Strength", 0.5f ) ); + + if ( outputMaterial is CCSkinTransmissiveMaterial st ) + { + st.textureSubsurfaceTransmittance.Set( customShader.value.GetTransmisionMap() ); + } + // skinMaterial.textureSubsurfaceTransmittance.Set( customShader.value.GetTransmisionMap() ); + skinMaterial.textureSpecular.AssignFor( outputMaterial, customShader.value.GetSpecularMask() ); + skinMaterial.textureSubsurfaceScattering.AssignFor( outputMaterial, customShader.value.GetSSSMap() ); + + textures.value.ForEach( + ( t ) => + { + if ( t.isBaseColor ) + { + skinMaterial.textureAlbedo.AssignFor( outputMaterial, t.GetTexture() ); + + var uv1Scale = t.tiling.GetOr( new List(){ 1, 1 } ); + var uv1Offset = t.offset.GetOr( new List(){ 0, 0 } ); + + skinMaterial.uv1Scale.AssignFor( outputMaterial, new Vector3( uv1Scale[ 0 ], uv1Scale[ 1 ], 1 ) ); + skinMaterial.uv1Offset.AssignFor( outputMaterial, new Vector3( uv1Offset[ 0 ], uv1Offset[ 1 ], 1 ) ); + } + else if ( t.isNormal ) + { + skinMaterial.textureNormal.AssignFor( outputMaterial, t.GetTexture() ); + } + else if ( t.isRoughness ) + { + skinMaterial.textureRoughness.AssignFor( outputMaterial, t.GetTexture() ); + } + else if ( t.isAO ) + { + skinMaterial.textureAmbientOcclusion.AssignFor( outputMaterial, t.GetTexture() ); + } + } + ); + + return outputMaterial; + + } + + public ShaderMaterial CreateOpacityMaterial( CCMaterialSettings settings ) + { + var opacityMaterial = new CCPBROpacityMaterial(); + + opacityMaterial.albedo.Set( GetAlbedoColor( settings.configuration.gammaForAlbedoColor ) ); + opacityMaterial.specular.Set( 0.0f ); + opacityMaterial.opacity.Set( opacity.GetOr( 1 ) ); + opacityMaterial.uv1Scale.Set( Vector3.One ); + opacityMaterial.uv2Scale.Set( Vector3.One ); + + textures.value.ForEach( + ( t ) => + { + if ( t.isBaseColor ) + { + opacityMaterial.textureAlbedo.Set( t.GetTexture() ); + + var uv1Scale = t.tiling.GetOr( new List(){ 1, 1 } ); + var uv1Offset = t.offset.GetOr( new List(){ 0, 0 } ); + + opacityMaterial.uv1Scale.Set( new Vector3( uv1Scale[ 0 ], uv1Scale[ 1 ], 1 ) ); + opacityMaterial.uv1Offset.Set( new Vector3( uv1Offset[ 0 ], uv1Offset[ 1 ], 1 ) ); + } + if ( t.isOpacity ) + { + opacityMaterial.textureOpacity.Set( t.GetTexture() ); + } + else if ( t.isNormal ) + { + opacityMaterial.textureNormal.Set( t.GetTexture() ); + } + else if ( t.isRoughness ) + { + opacityMaterial.textureRoughness.Set( t.GetTexture() ); + } + else if ( t.isMetallic ) + { + opacityMaterial.textureMetallic.Set( t.GetTexture() ); + opacityMaterial.metallicTextureChannel.Set( new Vector4( 1, 0, 0, 0 ) ); + } + else if ( t.isAO ) + { + opacityMaterial.textureAmbientOcclusion.Set( t.GetTexture() ); + opacityMaterial.aoTextureChannel.Set( new Vector4( 1, 0, 0, 0 ) ); + } + } + ); + + return opacityMaterial; + } + + public ShaderMaterial CreateHairMaterial( CCMaterialSettings settings ) + { + + + var scissorMaterial = new CCHairScissorMaterial(); + var alphaMaterial = new CCHairAlphaMaterial(); + var alphaBackMaterial = new CCHairAlphaBackMaterial(); + + + scissorMaterial.NextPass = alphaBackMaterial; + alphaBackMaterial.NextPass = alphaMaterial; + + alphaBackMaterial.RenderPriority = settings.materialRenderPriorityIndexBack; + alphaMaterial.RenderPriority = settings.materialRenderPriorityIndexFront; + + var m = new List(){ scissorMaterial, alphaMaterial, alphaBackMaterial }; + + var mat = scissorMaterial; + + CustomMaterial outputMaterial = scissorMaterial; + + var opacityScale = 1.0f; + + if ( CCImportConfiguration.HairShaderMode.Alpha_Only == settings.configuration.hairShaderMode ) + { + var hairMaterial = new CCHairMaterial(); + hairMaterial.RenderPriority = settings.materialRenderPriorityIndexBack; + outputMaterial = hairMaterial; + m = new List(){ hairMaterial }; + opacityScale = 1.5f; + } + else if ( CCImportConfiguration.HairShaderMode.Shadow_Scissor_AlphaBack_AlphaFront == settings.configuration.hairShaderMode ) + { + scissorMaterial.NextPass = null; + + var shadowMaterial = new CCHairShadowMaterial(); + shadowMaterial.RenderPriority = -2; + var hairMaterial = new CCHairScissorMaterial(); + + outputMaterial = shadowMaterial; + shadowMaterial.NextPass = hairMaterial; + hairMaterial.NextPass = alphaBackMaterial; + + m = new List(){ shadowMaterial, hairMaterial, alphaMaterial, alphaBackMaterial }; + opacityScale = 1f; + } + + mat.naturalColors.AssignFor( m, settings.configuration.naturalColors ); + mat.maximumHighlightAmount.AssignFor( m, settings.configuration.maximumHighlightAmount ); + + mat.opacityGamma.AssignFor( m, settings.configuration.GetHairOpacityGamma( settings.meshName, settings.materialIndex ) ); + + mat.flowMap.AssignFor( m, customShader.value.GetHairFlowMap() ); + mat.rootMap.AssignFor( m, customShader.value.GetHairRootMap() ); + mat.idMap.AssignFor( m, customShader.value.GetHairIDMap() ); + + mat.vertexGreyToColor.AssignFor( m, customShader.value.GetColorVariable( "VertexGrayToColor", 255f, false ) ); + mat.vertexColorStrength.AssignFor( m, customShader.value.GetFloatVariable( "VertexColorStrength" ) ); + mat.diffuseStrength.AssignFor( m, customShader.value.GetFloatVariable( "Diffuse Strength" ) ); + mat.baseColorMapStrength.AssignFor( m, customShader.value.GetFloatVariable( "BaseColorMapStrength" ) ); + + mat.strandRootColor.AssignFor( m, customShader.value.GetColorVariable( "RootColor", 255f, false ) ); + mat.strandRootStrength.AssignFor( m, customShader.value.GetFloatVariable( "RootColorStrength" ) ); + + mat.strandEndColor.AssignFor( m, customShader.value.GetColorVariable( "TipColor", 255f, false ) ); + mat.strandEndStrength.AssignFor( m, customShader.value.GetFloatVariable( "TipColorStrength" ) ); + + mat.highlightAColor.AssignFor( m, customShader.value.GetColorVariable( "_1st Dye Color", 255, false ) ); + mat.highlightAStrength.AssignFor( m, customShader.value.GetFloatVariable( "_1st Dye Strength" ) ); + mat.highlightARange.AssignFor( m, + customShader.value.GetColorVariable( "_1st Dye Distribution from Grayscale", 255, false ).ToVector3() + ); + mat.highlightAOverlapEnd.AssignFor( m, customShader.value.GetFloatVariable( "Mask 1st Dye by RootMap" ) ); + mat.highlightAInvert.AssignFor( m, customShader.value.GetFloatVariable( "Invert 1st Dye RootMap Mask" ) ); + + mat.highlightBColor.AssignFor( m, customShader.value.GetColorVariable( "_2nd Dye Color", 255, false ) ); + mat.highlightBStrength.AssignFor( m, customShader.value.GetFloatVariable( "_2nd Dye Strength" ) ); + mat.highlightBRange.AssignFor( m, + customShader.value.GetColorVariable( "_2nd Dye Distribution from Grayscale", 255, false ).ToVector3() + ); + mat.highlightBOverlapEnd.AssignFor( m, customShader.value.GetFloatVariable( "Mask 2nd Dye by RootMap" ) ); + mat.highlightBInvert.AssignFor( m, customShader.value.GetFloatVariable( "Invert 2nd Dye RootMap Mask" ) ); + + + mat.albedo.AssignFor( m, GetAlbedoColor( settings.configuration.gammaForAlbedoColor ) ); + // mat.specular.AssignFor( m, 0.5f ); + mat.opacity.AssignFor( m, opacity.GetOr( 1 ) * opacityScale ); + mat.blendAmount.AssignFor( m, 0f ); + + + textures.value.ForEach( + ( t ) => + { + if ( t.isBaseColor ) + { + mat.textureAlbedo.AssignFor( m, t.GetTexture() ); + } + if ( t.isOpacity ) + { + mat.textureOpacity.AssignFor( m, t.GetTexture() ); + } + else if ( t.isRoughness ) + { + mat.textureRoughness.AssignFor( m, t.GetTexture() ); + } + else if ( t.isMetallic ) + { + mat.textureMetallic.AssignFor( m, t.GetTexture() ); + } + else if ( t.isAO ) + { + mat.textureAmbientOcclusion.AssignFor( m, t.GetTexture() ); + } + else if ( t.isBlend ) + { + mat.textureBlend.AssignFor( m, t.GetTexture() ); + mat.blendAmount.AssignFor( m, t.strength.GetOr( 0f ) / 100f ) ; + } + } + ); + + return outputMaterial; + } + + } +} \ No newline at end of file diff --git a/Runtime/Reallusion/CCImportFile/CCMaterialInfo.cs.uid b/Runtime/Reallusion/CCImportFile/CCMaterialInfo.cs.uid new file mode 100644 index 0000000..f29c6d5 --- /dev/null +++ b/Runtime/Reallusion/CCImportFile/CCMaterialInfo.cs.uid @@ -0,0 +1 @@ +uid://cpqsmi25kxc1h diff --git a/Runtime/Reallusion/CCImportFile/CCMaterialType.cs b/Runtime/Reallusion/CCImportFile/CCMaterialType.cs new file mode 100644 index 0000000..ed27e60 --- /dev/null +++ b/Runtime/Reallusion/CCImportFile/CCMaterialType.cs @@ -0,0 +1,32 @@ + +using System.Diagnostics; +using System.Collections; +using System.Collections.Generic; +using System; +using Godot; + + +namespace Rokojori.Reallusion +{ + [Tool] + [GlobalClass] + public partial class CCMaterialType:Resource + { + public enum CCShaderType + { + Unknown, + PBR, + RLTongue, + RLHead, + RLSkin, + RLEyeTearline, + RLEyeOcclusion, + RLTeethGum, + RLEye, + RLHair + } + + [Export] + public CCShaderType shaderType; + } +} \ No newline at end of file diff --git a/Runtime/Reallusion/CCImportFile/CCMaterialType.cs.uid b/Runtime/Reallusion/CCImportFile/CCMaterialType.cs.uid new file mode 100644 index 0000000..0e67642 --- /dev/null +++ b/Runtime/Reallusion/CCImportFile/CCMaterialType.cs.uid @@ -0,0 +1 @@ +uid://ckl15as5h8w34 diff --git a/Runtime/Reallusion/CCImportFile/CCMeshInfo.cs b/Runtime/Reallusion/CCImportFile/CCMeshInfo.cs new file mode 100644 index 0000000..dc50788 --- /dev/null +++ b/Runtime/Reallusion/CCImportFile/CCMeshInfo.cs @@ -0,0 +1,49 @@ + +using System.Diagnostics; +using System.Collections; +using System.Collections.Generic; +using System; +using Godot; + + +namespace Rokojori.Reallusion +{ + public class CCMeshInfo:CCImportFileBase + { + public static readonly string Materials = "Materials"; + + public string name; + + public List materials = []; + + public CCMeshInfo( CCImportFile ccImportFile ):base( ccImportFile ){} + + + public void ReadFrom( JSONObject root ) + { + if ( ! ValidateMember( root, Materials, "Checking mesh info " + "'" + name + "'" ) ) + { + return; + } + + var materials = root.GetObject( Materials ); + + Info( "Found materials for", "'" + name + "'", ":", materials.size ); + + materials.keys.ForEach( + ( mk )=> + { + var name = mk; + var value = materials.GetObject( name ); + + Info( "Adding material:", name ); + var materialInfo = new CCMaterialInfo( importFile, name ); + + materialInfo.ReadFrom( value ); + + this.materials.Add( materialInfo ); + } + ); + } + } +} \ No newline at end of file diff --git a/Runtime/Reallusion/CCImportFile/CCMeshInfo.cs.uid b/Runtime/Reallusion/CCImportFile/CCMeshInfo.cs.uid new file mode 100644 index 0000000..6b5781d --- /dev/null +++ b/Runtime/Reallusion/CCImportFile/CCMeshInfo.cs.uid @@ -0,0 +1 @@ +uid://bqjn4egy3weqv diff --git a/Runtime/Reallusion/CCImportFile/CCObjectInfo.cs b/Runtime/Reallusion/CCImportFile/CCObjectInfo.cs new file mode 100644 index 0000000..62d11b9 --- /dev/null +++ b/Runtime/Reallusion/CCImportFile/CCObjectInfo.cs @@ -0,0 +1,65 @@ + +using System.Diagnostics; +using System.Collections; +using System.Collections.Generic; +using System; +using Godot; + + +namespace Rokojori.Reallusion +{ + public class CCObjectInfo:CCImportFileBase + { + public static readonly string Meshes = "Meshes"; + + public string name; + + public List meshes = []; + + public CCObjectInfo( CCImportFile ccImportFile ):base( ccImportFile ){} + + public void ReadFrom( JSONObject root ) + { + var rootKey = root.keys[ 0 ]; + + name = rootKey; + + Info( "Found object entry:", name ); + + if ( ! ValidateMember( root, rootKey, "Checking root object" ) ) + { + return; + } + + var rootObject = root.GetObject( rootKey ); + + + + if ( ! ValidateMember( rootObject, CCObjectInfo.Meshes, "Checking root object meshes" ) ) + { + return; + } + + var meshes = rootObject.GetObject( CCObjectInfo.Meshes ); + + Info( "Found meshes", meshes.size ); + + meshes.keys.ForEach( + ( mk )=> + { + var name = mk; + var value = meshes.GetObject( mk ); + + var meshInfo = new CCMeshInfo( importFile ); + meshInfo.name = name; + + meshInfo.ReadFrom( value ); + + this.meshes.Add( meshInfo ); + + } + ); + + } + } +} \ No newline at end of file diff --git a/Runtime/Reallusion/CCImportFile/CCObjectInfo.cs.uid b/Runtime/Reallusion/CCImportFile/CCObjectInfo.cs.uid new file mode 100644 index 0000000..47a8f9e --- /dev/null +++ b/Runtime/Reallusion/CCImportFile/CCObjectInfo.cs.uid @@ -0,0 +1 @@ +uid://cqjoabuofavll diff --git a/Runtime/Reallusion/CCImportFile/CCSubsurfaceScatter.cs b/Runtime/Reallusion/CCImportFile/CCSubsurfaceScatter.cs new file mode 100644 index 0000000..d22b043 --- /dev/null +++ b/Runtime/Reallusion/CCImportFile/CCSubsurfaceScatter.cs @@ -0,0 +1,24 @@ +using System.Diagnostics; +using System.Collections; +using System.Collections.Generic; +using System; +using Godot; + + +namespace Rokojori.Reallusion +{ + public class CCSubsurfaceScatter:CCImportFileBase + { + public CCJSONProperty radius = new CCJSONProperty( "Radius" ); + + public CCSubsurfaceScatter( CCImportFile file ):base( file ) + { + + } + + public void ReadFrom( JSONObject jsonObject ) + { + radius.Read( jsonObject ); + } + } +} \ No newline at end of file diff --git a/Runtime/Reallusion/CCImportFile/CCSubsurfaceScatter.cs.uid b/Runtime/Reallusion/CCImportFile/CCSubsurfaceScatter.cs.uid new file mode 100644 index 0000000..cf9979d --- /dev/null +++ b/Runtime/Reallusion/CCImportFile/CCSubsurfaceScatter.cs.uid @@ -0,0 +1 @@ +uid://cj1jyhcwiqijq diff --git a/Runtime/Reallusion/CCImportFile/CCTextureInfo.cs b/Runtime/Reallusion/CCImportFile/CCTextureInfo.cs new file mode 100644 index 0000000..6b532f8 --- /dev/null +++ b/Runtime/Reallusion/CCImportFile/CCTextureInfo.cs @@ -0,0 +1,105 @@ + +using System.Diagnostics; +using System.Collections; +using System.Collections.Generic; +using System; +using Godot; + + +namespace Rokojori.Reallusion +{ + public class CCTextureInfo:CCImportFileBase + { + public static readonly string BaseColor = "Base Color"; + public bool isBaseColor => Is( BaseColor ); + + public static readonly string Opacity = "Opacity"; + public bool isOpacity => Is( Opacity ); + + public static readonly string Metallic = "Metallic"; + public bool isMetallic => Is( Metallic ); + + public static readonly string Roughness = "Roughness"; + public bool isRoughness => Is( Roughness ); + + public static readonly string Normal = "Normal"; + public bool isNormal => Is( Normal ); + + public static readonly string AO = "AO"; + public bool isAO => Is( AO ); + + public static readonly string Glow = "Glow"; + public bool isGlow => Is( Glow ); + + public static readonly string Blend = "Blend"; + public bool isBlend => Is( Blend ); + + public string name; + + public CCJSONProperty texturePath = new CCJSONProperty( "Texture Path"); + + public CCJSONProperty strength = new CCJSONProperty( "Strength"); + + public CCJSONProperty> offset = new CCJSONProperty>( "Offset" ); + public CCJSONProperty> tiling = new CCJSONProperty>( "Tiling" ); + + + public CCTextureInfo( CCImportFile file, string name ):base( file ) + { + this.name = name; + } + + public Texture2D GetTexture() + { + var path = texturePath.value; + return GetTextureFromRelativePath( path ); + } + + Texture2D GetTextureFromRelativePath( string relativePath ) + { + var rootDirectoryPath = FilePath.Absolute( importFile.directory ); + var relativeFilePath = rootDirectoryPath.MakeRelative( relativePath ); + + var texture = ResourceLoader.Load( relativeFilePath.fullPath ); + + return texture; + + // var img = new Image(); + // var result = img.Load( relativeFilePath.fullPath ); + + // if ( result != Godot.Error.Ok ) + // { + // Error( "Could not load image:", relativePath, ">>", relativeFilePath.fullPath ); + // return null; + // } + + // return ImageTexture.CreateFromImage( img ); + } + + public void ReadFrom( JSONObject jsonObject ) + { + texturePath.Read( jsonObject ); + strength.Read( jsonObject ); + offset.Read( jsonObject ); + tiling.Read( jsonObject ); + } + + public bool Is( string type ) + { + return name == type; + } + + + + public static CCTextureInfo Create( CCImportFile file, string name, JSONData data ) + { + var ti = new CCTextureInfo( file, name ); + + ti.ReadFrom( data.AsObject() ); + + return ti; + } + + + } +} \ No newline at end of file diff --git a/Runtime/Reallusion/CCImportFile/CCTextureInfo.cs.uid b/Runtime/Reallusion/CCImportFile/CCTextureInfo.cs.uid new file mode 100644 index 0000000..3c20d6a --- /dev/null +++ b/Runtime/Reallusion/CCImportFile/CCTextureInfo.cs.uid @@ -0,0 +1 @@ +uid://cugub7jkvrhmn diff --git a/Runtime/Reallusion/CCImportSettings/CCHairOpacityGammaOverwrite.cs b/Runtime/Reallusion/CCImportSettings/CCHairOpacityGammaOverwrite.cs new file mode 100644 index 0000000..7be0d67 --- /dev/null +++ b/Runtime/Reallusion/CCImportSettings/CCHairOpacityGammaOverwrite.cs @@ -0,0 +1,24 @@ + +using System.Diagnostics; +using System.Collections; +using System.Collections.Generic; +using System; +using Godot; +using System.Threading.Tasks; +using System.Text; + +namespace Rokojori.Reallusion +{ + [Tool] + [GlobalClass] + public partial class CCHairOpacityGammaOverwrite:Resource + { + [Export] + public CCMaterialTarget[] targets; + + [Export] + public float hairOpacityGamma = 1.0f; + + + } +} \ No newline at end of file diff --git a/Runtime/Reallusion/CCImportSettings/CCHairOpacityGammaOverwrite.cs.uid b/Runtime/Reallusion/CCImportSettings/CCHairOpacityGammaOverwrite.cs.uid new file mode 100644 index 0000000..0aad47f --- /dev/null +++ b/Runtime/Reallusion/CCImportSettings/CCHairOpacityGammaOverwrite.cs.uid @@ -0,0 +1 @@ +uid://bjq02y86lq2sn diff --git a/Runtime/Reallusion/CCImportSettings/CCImportConfiguration.cs b/Runtime/Reallusion/CCImportSettings/CCImportConfiguration.cs new file mode 100644 index 0000000..ff02464 --- /dev/null +++ b/Runtime/Reallusion/CCImportSettings/CCImportConfiguration.cs @@ -0,0 +1,99 @@ + +using System.Diagnostics; +using System.Collections; +using System.Collections.Generic; +using System; +using Godot; +using System.Threading.Tasks; +using System.Text; + +namespace Rokojori.Reallusion +{ + [Tool] + [GlobalClass] + public partial class CCImportConfiguration:Resource + { + + [Export] + public bool setRenderPrioritiesForHair = true; + + [Export] + public float gammaForAlbedoColor = 1.0f / 2.2f; + + [Export] + public CCMaterialOverwrite[] materialOverwrites = []; + + [ExportGroup( "Skin")] + [Export] + public bool transmissiveSkin = true; + + public bool applyAlbedoNoise = true; + + [Export] + public Texture2D skinAlbedoNoise; + + [Export] + public float albedoNoiseBrightness = -0.5f; + + [Export] + public float albedoNoiseAmount = 0.2f; + + public enum HairShaderMode + { + Alpha_Only, + Scissor_AlphaBack_AlphaFront, + Shadow_Scissor_AlphaBack_AlphaFront + } + + [ExportGroup( "Hair")] + [Export] + public HairShaderMode hairShaderMode = HairShaderMode.Scissor_AlphaBack_AlphaFront; + + [Export(PropertyHint.Range,"0,1")] + public float naturalColors = 0.5f; + + [Export(PropertyHint.Range,"0,1")] + public float maximumHighlightAmount = 0.5f; + + [Export] + public float hairOpacityGamma = 1.2f; + + [Export] + public CCHairOpacityGammaOverwrite[] hairOpacityGammaOverwrites = []; + + public Material GetOverwriteMaterial( string name, int index ) + { + var ov = Arrays.Find( materialOverwrites, mo => mo.meshName == name && mo.materialSurfaceIndex == index ); + + return ov == null ? null : ov.material; + } + + public float GetHairOpacityGamma( string meshName, int surfaceIndex ) + { + if ( hairOpacityGammaOverwrites == null || hairOpacityGammaOverwrites.Length == 0 ) + { + return hairOpacityGamma; + } + + for ( int i = 0; i < hairOpacityGammaOverwrites.Length; i++ ) + { + var overwriteTargets = hairOpacityGammaOverwrites[ i ].targets; + + for ( int j = 0; j < overwriteTargets.Length; j++ ) + { + var target = overwriteTargets[ j ]; + + if ( target.meshName == meshName && target.materialSurfaceIndex == surfaceIndex ) + { + return hairOpacityGammaOverwrites[ i ].hairOpacityGamma; + } + } + } + + + return hairOpacityGamma; + + } + + } +} \ No newline at end of file diff --git a/Runtime/Reallusion/CCImportSettings/CCImportConfiguration.cs.uid b/Runtime/Reallusion/CCImportSettings/CCImportConfiguration.cs.uid new file mode 100644 index 0000000..7f0e4af --- /dev/null +++ b/Runtime/Reallusion/CCImportSettings/CCImportConfiguration.cs.uid @@ -0,0 +1 @@ +uid://bokvy3rghbbj2 diff --git a/Runtime/Reallusion/CCImportSettings/CCImportSettings.cs b/Runtime/Reallusion/CCImportSettings/CCImportSettings.cs new file mode 100644 index 0000000..324cd1d --- /dev/null +++ b/Runtime/Reallusion/CCImportSettings/CCImportSettings.cs @@ -0,0 +1,24 @@ + +using System.Diagnostics; +using System.Collections; +using System.Collections.Generic; +using System; +using Godot; +using System.Threading.Tasks; +using System.Text; + +namespace Rokojori.Reallusion +{ + [Tool] + [GlobalClass] + public partial class CCImportSettings:Resource + { + + [Export] + public CCMeshSettings[] meshes = []; + + [Export] + public CCImportConfiguration configuration; + + } +} \ No newline at end of file diff --git a/Runtime/Reallusion/CCImportSettings/CCImportSettings.cs.uid b/Runtime/Reallusion/CCImportSettings/CCImportSettings.cs.uid new file mode 100644 index 0000000..bc49629 --- /dev/null +++ b/Runtime/Reallusion/CCImportSettings/CCImportSettings.cs.uid @@ -0,0 +1 @@ +uid://c3ivvup44r57n diff --git a/Runtime/Reallusion/CCImportSettings/CCMaterialOverwrite.cs b/Runtime/Reallusion/CCImportSettings/CCMaterialOverwrite.cs new file mode 100644 index 0000000..69f50d9 --- /dev/null +++ b/Runtime/Reallusion/CCImportSettings/CCMaterialOverwrite.cs @@ -0,0 +1,26 @@ + +using System.Diagnostics; +using System.Collections; +using System.Collections.Generic; +using System; +using Godot; +using System.Threading.Tasks; +using System.Text; + +namespace Rokojori.Reallusion +{ + [Tool] + [GlobalClass] + public partial class CCMaterialOverwrite:Resource + { + [Export] + public string meshName; + + [Export] + public Material material; + + [Export] + public int materialSurfaceIndex; + + } +} \ No newline at end of file diff --git a/Runtime/Reallusion/CCImportSettings/CCMaterialOverwrite.cs.uid b/Runtime/Reallusion/CCImportSettings/CCMaterialOverwrite.cs.uid new file mode 100644 index 0000000..542571e --- /dev/null +++ b/Runtime/Reallusion/CCImportSettings/CCMaterialOverwrite.cs.uid @@ -0,0 +1 @@ +uid://bjfhuvfg37cp6 diff --git a/Runtime/Reallusion/CCImportSettings/CCMaterialSettings.cs b/Runtime/Reallusion/CCImportSettings/CCMaterialSettings.cs new file mode 100644 index 0000000..882ae96 --- /dev/null +++ b/Runtime/Reallusion/CCImportSettings/CCMaterialSettings.cs @@ -0,0 +1,39 @@ + +using System.Diagnostics; +using System.Collections; +using System.Collections.Generic; +using System; +using Godot; +using System.Threading.Tasks; +using System.Text; + +namespace Rokojori.Reallusion +{ + + [Tool] + [GlobalClass] + public partial class CCMaterialSettings:Resource + { + [Export] + public string materialName; + + [Export] + public int materialIndex; + + [Export] + public string meshName; + + [Export] + public CCMaterialType materialType; + + [Export] + public int materialRenderPriorityIndexBack; + + [Export] + public int materialRenderPriorityIndexFront; + + [Export] + public CCImportConfiguration configuration; + + } +} \ No newline at end of file diff --git a/Runtime/Reallusion/CCImportSettings/CCMaterialSettings.cs.uid b/Runtime/Reallusion/CCImportSettings/CCMaterialSettings.cs.uid new file mode 100644 index 0000000..8f323f8 --- /dev/null +++ b/Runtime/Reallusion/CCImportSettings/CCMaterialSettings.cs.uid @@ -0,0 +1 @@ +uid://cc3ftibne5wwn diff --git a/Runtime/Reallusion/CCImportSettings/CCMaterialTarget.cs b/Runtime/Reallusion/CCImportSettings/CCMaterialTarget.cs new file mode 100644 index 0000000..8cfab9b --- /dev/null +++ b/Runtime/Reallusion/CCImportSettings/CCMaterialTarget.cs @@ -0,0 +1,24 @@ + +using System.Diagnostics; +using System.Collections; +using System.Collections.Generic; +using System; +using Godot; +using System.Threading.Tasks; +using System.Text; + +namespace Rokojori.Reallusion +{ + [Tool] + [GlobalClass] + public partial class CCMaterialTarget:Resource + { + [Export] + public string meshName = ""; + + [Export] + public int materialSurfaceIndex = 0; + + + } +} \ No newline at end of file diff --git a/Runtime/Reallusion/CCImportSettings/CCMaterialTarget.cs.uid b/Runtime/Reallusion/CCImportSettings/CCMaterialTarget.cs.uid new file mode 100644 index 0000000..705ae75 --- /dev/null +++ b/Runtime/Reallusion/CCImportSettings/CCMaterialTarget.cs.uid @@ -0,0 +1 @@ +uid://bl6hvu2d2riad diff --git a/Runtime/Reallusion/CCImportSettings/CCMeshSettings.cs b/Runtime/Reallusion/CCImportSettings/CCMeshSettings.cs new file mode 100644 index 0000000..c6a3e2b --- /dev/null +++ b/Runtime/Reallusion/CCImportSettings/CCMeshSettings.cs @@ -0,0 +1,22 @@ + +using System.Diagnostics; +using System.Collections; +using System.Collections.Generic; +using System; +using Godot; +using System.Threading.Tasks; +using System.Text; + +namespace Rokojori.Reallusion +{ + [Tool] + [GlobalClass] + public partial class CCMeshSettings:Resource + { + [Export] + public string meshName; + + [Export] + public CCMaterialSettings[] materials = []; + } +} \ No newline at end of file diff --git a/Runtime/Reallusion/CCImportSettings/CCMeshSettings.cs.uid b/Runtime/Reallusion/CCImportSettings/CCMeshSettings.cs.uid new file mode 100644 index 0000000..61a51a8 --- /dev/null +++ b/Runtime/Reallusion/CCImportSettings/CCMeshSettings.cs.uid @@ -0,0 +1 @@ +uid://c5dlwgthk7tdy diff --git a/Runtime/Reallusion/CCImportTool.cs b/Runtime/Reallusion/CCImportTool.cs new file mode 100644 index 0000000..df55e07 --- /dev/null +++ b/Runtime/Reallusion/CCImportTool.cs @@ -0,0 +1,24 @@ +using System.Collections; +using System.Collections.Generic; +using System; +using Godot; +using System.Threading.Tasks; + + +namespace Rokojori.Reallusion +{ + public class CCImportTool + { + public CCImportFile Read( string path ) + { + var data = FilesSync.LoadUTF8( path ); + var json = JSON.Parse( data ); + + var ccImportFile = new CCImportFile(); + ccImportFile.path = path; + ccImportFile.ReadFrom( json ); + + return ccImportFile; + } + } +} \ No newline at end of file diff --git a/Runtime/Reallusion/CCImportTool.cs.uid b/Runtime/Reallusion/CCImportTool.cs.uid new file mode 100644 index 0000000..b9c32ee --- /dev/null +++ b/Runtime/Reallusion/CCImportTool.cs.uid @@ -0,0 +1 @@ +uid://qohcsdwodj3s diff --git a/Runtime/Reallusion/CCImporter.cs b/Runtime/Reallusion/CCImporter.cs new file mode 100644 index 0000000..f5ab1b2 --- /dev/null +++ b/Runtime/Reallusion/CCImporter.cs @@ -0,0 +1,239 @@ + +using System.Diagnostics; +using System.Collections; +using System.Collections.Generic; +using System; +using Godot; +using System.Threading.Tasks; +using System.Text; + +namespace Rokojori.Reallusion +{ + [Tool] + [GlobalClass] + public partial class CCImporter:Node + { + [Export] + public Node3D characterRoot; + + [Export] + public string path; + + [Export] + public CCImportConfiguration configuration; + + [Export] + public bool addCCMaterialsNode = true; + + [Export] + public CCImportSettings importSettings; + + [Export] + public CCMaterialGenerator materialGenerator; + + + + + [ExportToolButton( "Import")] + public Callable ImportButton => Callable.From( + () => + { + Import(); + } + ); + + [ExportToolButton( "Set Materials")] + public Callable SetMaterialsButton => Callable.From( + () => + { + SetMaterials(); + } + ); + + CCImportFile importFile; + + public void Import() + { + this.LogInfo( "Loading:", path ); + + importFile = new CCImportTool().Read( path ); + + var sb = new StringBuilder(); + + importFile.messages.ForEach( + ( m )=> + { + sb.Append( m.type == MessageType.Error ? "Error: " : "Info: " ); + sb.Append( m.content ); + sb.Append( "\n" ); + } + ); + + this.LogInfo( sb ); + + importSettings = new CCImportSettings(); + importSettings.configuration = configuration; + + + var meshIndex = 0; + + importFile.ccObject.meshes.ForEach( + ( m )=> + { + var meshSettings = new CCMeshSettings(); + meshSettings.meshName = m.name; + + + for ( int i = 0; i < m.materials.Count; i++ ) + { + var materialSetting = new CCMaterialSettings(); + materialSetting.meshName = m.name; + materialSetting.materialName = m.materials[ i ].name; + materialSetting.materialIndex = i; + materialSetting.materialType = m.materials[ i ].GetMaterialType(); + + meshSettings.materials = Arrays.AddEntry( meshSettings.materials, materialSetting ); + } + + importSettings.meshes = Arrays.AddEntry( importSettings.meshes, meshSettings ); + + meshIndex ++; + } + ); + + } + + + public void SetMaterials() + { + var meshIndex = -1; + + var ccmaterials = addCCMaterialsNode ? characterRoot.GetOrCreateChild( "CC Materials" ) : null; + + if ( ccmaterials != null ) + { + ccmaterials.Clear(); + ccmaterials.root = characterRoot; + } + + for ( int i = 0; i < importSettings.meshes.Length; i++ ) + { + var ms = importSettings.meshes[ i ]; + + for ( int j = 0; j < ms.materials.Length; j++ ) + { + ms.materials[ j ].configuration = importSettings.configuration; + } + } + + if ( importSettings.configuration.setRenderPrioritiesForHair ) + { + var renderIndex = 0; + + for ( int i = 0; i < importSettings.meshes.Length; i++ ) + { + var ms = importSettings.meshes[ i ]; + + for ( int j = 0; j < ms.materials.Length; j++ ) + { + if ( ms.materials[ j ].materialType.shaderType == CCMaterialType.CCShaderType.RLHair ) + { + ms.materials[ j ].materialRenderPriorityIndexBack = renderIndex; + renderIndex ++; + } + } + } + + for ( int i = 0; i < importSettings.meshes.Length; i++ ) + { + var ms = importSettings.meshes[ i ]; + + for ( int j = 0; j < ms.materials.Length; j++ ) + { + if ( ms.materials[ j ].materialType.shaderType == CCMaterialType.CCShaderType.RLHair ) + { + ms.materials[ j ].materialRenderPriorityIndexFront = renderIndex; + renderIndex ++; + } + } + } + } + + importFile.ccObject.meshes.ForEach( + ( m )=> + { + meshIndex ++; + var meshSettings = importSettings.meshes[ meshIndex ]; + + var mesh = characterRoot.FindChild( m.name ) as MeshInstance3D; + + if ( mesh == null ) + { + return; + } + + + for ( int i = 0; i < m.materials.Count; i++ ) + { + var settings = meshSettings.materials[ i ]; + var material = materialGenerator == null ? m.materials[ i ].CreateMaterial( settings ) : + materialGenerator.CreateMaterial( m.materials[ i ], settings ); + + + var overwriteMaterial = settings.configuration.GetOverwriteMaterial( m.name, i ); + + if ( overwriteMaterial != null ) + { + material = overwriteMaterial; + } + + mesh.SetSurfaceOverrideMaterial( i, material ); + + if ( ccmaterials == null ) + { + continue; + } + + if ( settings.materialType.shaderType == CCMaterialType.CCShaderType.RLHair ) + { + var hairMaterial = (CustomMaterial) material; + var materials = Materials.ResolveNextPasses( material ); + + materials.ForEach( m => + { + ccmaterials.hairMaterials = Arrays.AddEntry( ccmaterials.hairMaterials, m ); + } + ); + + ccmaterials.hairSpecular.ReadFrom( hairMaterial ); + ccmaterials.hairMetallic.ReadFrom( hairMaterial ); + ccmaterials.hairRoughness.ReadFrom( hairMaterial ); + + + } + else if ( + settings.materialType.shaderType == CCMaterialType.CCShaderType.RLHead || + settings.materialType.shaderType == CCMaterialType.CCShaderType.RLSkin + ) + { + var skinMaterial = (CustomMaterial) material; + var materials = Materials.ResolveNextPasses( material ); + materials.ForEach( m => + { + ccmaterials.skinMaterials = Arrays.AddEntry( ccmaterials.skinMaterials, m ); + } + ); + + ccmaterials.skinAlbedoNoise.ReadFrom( skinMaterial ); + ccmaterials.skinAlbedoNoiseOffset.ReadFrom( skinMaterial ); + } + + } + + + } + ); + } + } + +} \ No newline at end of file diff --git a/Runtime/Reallusion/CCImporter.cs.uid b/Runtime/Reallusion/CCImporter.cs.uid new file mode 100644 index 0000000..aa37c3e --- /dev/null +++ b/Runtime/Reallusion/CCImporter.cs.uid @@ -0,0 +1 @@ +uid://bs1bce3aw7vs1 diff --git a/Runtime/Reallusion/Materials/CCMaterials.cs b/Runtime/Reallusion/Materials/CCMaterials.cs new file mode 100644 index 0000000..dd62ad3 --- /dev/null +++ b/Runtime/Reallusion/Materials/CCMaterials.cs @@ -0,0 +1,81 @@ + +using System.Diagnostics; +using System.Collections; +using System.Collections.Generic; +using System; +using Godot; +using System.Threading.Tasks; +using System.Text; + +namespace Rokojori.Reallusion +{ + [Tool] + [GlobalClass] + public partial class CCMaterials:Node + { + [Export] + public Node3D root; + + [Export] + public bool applyProperties = false; + + [ExportGroup("Hair")] + [Export] + public Material[] hairMaterials = []; + + [Export] + public FloatProperty hairSpecular = FloatProperty.Create( "specular", 0 ); + [Export] + public FloatProperty hairMetallic = FloatProperty.Create( "metallic", 0 ); + [Export] + public FloatProperty hairRoughness = FloatProperty.Create( "roughness", 0 ); + + void ApplyHairProperties() + { + Apply( hairMaterials, hairSpecular ); + Apply( hairMaterials, hairMetallic ); + Apply( hairMaterials, hairRoughness ); + } + + [ExportGroup("Skin")] + [Export] + public Material[] skinMaterials = []; + + [Export] + public FloatProperty skinAlbedoNoise = FloatProperty.Create( "albedoNoise", 0 ); + [Export] + public FloatProperty skinAlbedoNoiseOffset = FloatProperty.Create( "albedoNoiseOffset", 0 ); + + void ApplySkinProperties() + { + Apply( skinMaterials, skinAlbedoNoise ); + Apply( skinMaterials, skinAlbedoNoiseOffset ); + } + + public void Clear() + { + root = null; + hairMaterials = []; + skinMaterials = []; + } + + public override void _Process( double delta ) + { + if ( ! applyProperties ) + { + return; + } + + ApplyHairProperties(); + ApplySkinProperties(); + } + + void Apply( Material[] materials, ShaderProperty sp ) + { + for ( int i = 0; i < materials.Length; i++ ) + { + sp.Apply( materials[ i ] ); + } + } + } +} \ No newline at end of file diff --git a/Runtime/Reallusion/Materials/CCMaterials.cs.uid b/Runtime/Reallusion/Materials/CCMaterials.cs.uid new file mode 100644 index 0000000..b7414f9 --- /dev/null +++ b/Runtime/Reallusion/Materials/CCMaterials.cs.uid @@ -0,0 +1 @@ +uid://wmkwia3eixd8 diff --git a/Runtime/Reallusion/Shaders/CCEye.gdshader b/Runtime/Reallusion/Shaders/CCEye.gdshader new file mode 100644 index 0000000..20b30fc --- /dev/null +++ b/Runtime/Reallusion/Shaders/CCEye.gdshader @@ -0,0 +1,41 @@ +// NOTE: Shader automatically converted from Godot Engine 4.4.stable.mono's StandardMaterial3D. + +shader_type spatial; +render_mode blend_mix, depth_draw_opaque, cull_back, diffuse_burley, specular_schlick_ggx; + +#include "res://addons/rokojori_action_library/Runtime/Shading/Library/Transform.gdshaderinc" + +uniform sampler2D texture_albedo : source_color, filter_linear_mipmap, repeat_enable; + +uniform sampler2D texture_normal : hint_roughness_normal, filter_linear_mipmap, repeat_enable; +uniform float normal_scale : hint_range(0, 2) = 0.1; + +uniform float roughness : hint_range(0, 1) = 0.2; + +uniform float irisRange : hint_range(0.1, 10) = 5; +uniform float irisPower : hint_range(0.1, 10) = 5; +uniform float irisScale:hint_range(0.01,2.0) = 1; + +//void vertex() +//{ + //UV = scale( UV, vec2(0.5), vec2(uvScale) ); +//} + +void fragment() +{ + vec2 base_uv = UV; + float d = ( irisRange * length( UV - vec2( 0.5, 0.5 ) ) ) / length( vec2( 0.5, 0.5 ) ); + d = clamp( d, 0, 1 ); + d = pow( d, irisPower ); + base_uv = mix( UV, scale( UV, vec2(0.5), vec2(2.0 - irisScale) ), 1.0 - d); + + vec4 albedo_tex = texture(texture_albedo, base_uv); + ALBEDO = albedo_tex.rgb; + //ALBEDO = vec3( d ); + + ROUGHNESS = mix( roughness, 1, d ); + + NORMAL_MAP = texture(texture_normal, base_uv).rgb; + //ALBEDO = normalize( vec3( UV.rg*0.5, 1) ); + NORMAL_MAP_DEPTH = normal_scale; +} diff --git a/Runtime/Reallusion/Shaders/CCEye.gdshader.uid b/Runtime/Reallusion/Shaders/CCEye.gdshader.uid new file mode 100644 index 0000000..1c5a00c --- /dev/null +++ b/Runtime/Reallusion/Shaders/CCEye.gdshader.uid @@ -0,0 +1 @@ +uid://b2l7elkoeqqoy diff --git a/Runtime/Reallusion/Shaders/CCEyeMaterial.cs b/Runtime/Reallusion/Shaders/CCEyeMaterial.cs new file mode 100644 index 0000000..0f9caea --- /dev/null +++ b/Runtime/Reallusion/Shaders/CCEyeMaterial.cs @@ -0,0 +1,51 @@ +using Godot; + +namespace Rokojori +{ + // Generated by ShaderClassGenerator + + public class CCEyeShader + { + public static readonly CachedResource shader = new CachedResource( + "res://addons/rokojori_action_library/Runtime/Reallusion/Shaders/CCEye.gdshader" + ); + + public static readonly Texture2DPropertyName textureAlbedo = Texture2DPropertyName.Create( "texture_albedo" ); + public static readonly Texture2DPropertyName textureNormal = Texture2DPropertyName.Create( "texture_normal" ); + public static readonly FloatPropertyName normalScale = FloatPropertyName.Create( "normal_scale" ); + public static readonly FloatPropertyName roughness = FloatPropertyName.Create( "roughness" ); + public static readonly FloatPropertyName irisRange = FloatPropertyName.Create( "irisRange" ); + public static readonly FloatPropertyName irisPower = FloatPropertyName.Create( "irisPower" ); + public static readonly FloatPropertyName irisScale = FloatPropertyName.Create( "irisScale" ); + + } + + [Tool] + public partial class CCEyeMaterial:CustomMaterial + { + + + public readonly CustomMaterialProperty textureAlbedo; + public readonly CustomMaterialProperty textureNormal; + public readonly CustomMaterialProperty normalScale; + public readonly CustomMaterialProperty roughness; + public readonly CustomMaterialProperty irisRange; + public readonly CustomMaterialProperty irisPower; + public readonly CustomMaterialProperty irisScale; + + public CCEyeMaterial() + { + Shader = CCEyeShader.shader.Get(); + + textureAlbedo = new CustomMaterialProperty( this, CCEyeShader.textureAlbedo ); + textureNormal = new CustomMaterialProperty( this, CCEyeShader.textureNormal ); + normalScale = new CustomMaterialProperty( this, CCEyeShader.normalScale ); + roughness = new CustomMaterialProperty( this, CCEyeShader.roughness ); + irisRange = new CustomMaterialProperty( this, CCEyeShader.irisRange ); + irisPower = new CustomMaterialProperty( this, CCEyeShader.irisPower ); + irisScale = new CustomMaterialProperty( this, CCEyeShader.irisScale ); + } + + } + +} \ No newline at end of file diff --git a/Runtime/Reallusion/Shaders/CCEyeMaterial.cs.uid b/Runtime/Reallusion/Shaders/CCEyeMaterial.cs.uid new file mode 100644 index 0000000..ddab79d --- /dev/null +++ b/Runtime/Reallusion/Shaders/CCEyeMaterial.cs.uid @@ -0,0 +1 @@ +uid://dabg2rbrefna2 diff --git a/Runtime/Reallusion/Shaders/CCEyeOcclusion.gdshader b/Runtime/Reallusion/Shaders/CCEyeOcclusion.gdshader new file mode 100644 index 0000000..9271523 --- /dev/null +++ b/Runtime/Reallusion/Shaders/CCEyeOcclusion.gdshader @@ -0,0 +1,23 @@ +shader_type spatial; +render_mode blend_mix, cull_back, unshaded; + +uniform vec4 shadowTopColor : source_color; +uniform vec4 shadowBottomColor: source_color; +uniform float opacity: hint_range(0, 5) = 1; +uniform float scaling: hint_range(0, 5) = 1; + + +void vertex() +{ + VERTEX += NORMAL * 0.001; +} + +void fragment() +{ + vec4 mixedColor = mix( shadowTopColor, shadowBottomColor, UV.y ); + ALBEDO = mixedColor.rgb; + float d = scaling * length ( UV - vec2( 0.5, 0.5 ) ) / length( vec2( 0.5, 0.5 )); + ALPHA *= min( 1.0, mixedColor.a * opacity * d ); + + +} diff --git a/Runtime/Reallusion/Shaders/CCEyeOcclusion.gdshader.uid b/Runtime/Reallusion/Shaders/CCEyeOcclusion.gdshader.uid new file mode 100644 index 0000000..8a22f6d --- /dev/null +++ b/Runtime/Reallusion/Shaders/CCEyeOcclusion.gdshader.uid @@ -0,0 +1 @@ +uid://dkxt0ircdjvu6 diff --git a/Runtime/Reallusion/Shaders/CCEyeOcclusionMaterial.cs b/Runtime/Reallusion/Shaders/CCEyeOcclusionMaterial.cs new file mode 100644 index 0000000..7ef951e --- /dev/null +++ b/Runtime/Reallusion/Shaders/CCEyeOcclusionMaterial.cs @@ -0,0 +1,48 @@ +using Godot; + +namespace Rokojori +{ + // Generated by ShaderClassGenerator + + public class CCEyeOcclusionShader + { + public static readonly CachedResource shader = new CachedResource( + "res://addons/rokojori_action_library/Runtime/Reallusion/Shaders/CCEyeOcclusion.gdshader" + ); + + public static readonly ColorPropertyName shadowTopColor = ColorPropertyName.Create( "shadowTopColor" ); + public static readonly ColorPropertyName shadowBottomColor = ColorPropertyName.Create( "shadowBottomColor" ); + public static readonly FloatPropertyName opacity = FloatPropertyName.Create( "opacity" ); + public static readonly FloatPropertyName scaling = FloatPropertyName.Create( "scaling" ); + public static readonly Vector3PropertyName uv1Scale = Vector3PropertyName.Create( "uv1_scale" ); + public static readonly Vector3PropertyName uv1Offset = Vector3PropertyName.Create( "uv1_offset" ); + + } + + [Tool] + public partial class CCEyeOcclusionMaterial:CustomMaterial + { + + + public readonly CustomMaterialProperty shadowTopColor; + public readonly CustomMaterialProperty shadowBottomColor; + public readonly CustomMaterialProperty opacity; + public readonly CustomMaterialProperty scaling; + public readonly CustomMaterialProperty uv1Scale; + public readonly CustomMaterialProperty uv1Offset; + + public CCEyeOcclusionMaterial() + { + Shader = CCEyeOcclusionShader.shader.Get(); + + shadowTopColor = new CustomMaterialProperty( this, CCEyeOcclusionShader.shadowTopColor ); + shadowBottomColor = new CustomMaterialProperty( this, CCEyeOcclusionShader.shadowBottomColor ); + opacity = new CustomMaterialProperty( this, CCEyeOcclusionShader.opacity ); + scaling = new CustomMaterialProperty( this, CCEyeOcclusionShader.scaling ); + uv1Scale = new CustomMaterialProperty( this, CCEyeOcclusionShader.uv1Scale ); + uv1Offset = new CustomMaterialProperty( this, CCEyeOcclusionShader.uv1Offset ); + } + + } + +} \ No newline at end of file diff --git a/Runtime/Reallusion/Shaders/CCEyeOcclusionMaterial.cs.uid b/Runtime/Reallusion/Shaders/CCEyeOcclusionMaterial.cs.uid new file mode 100644 index 0000000..c000e15 --- /dev/null +++ b/Runtime/Reallusion/Shaders/CCEyeOcclusionMaterial.cs.uid @@ -0,0 +1 @@ +uid://dv5sc7wcqh3po diff --git a/Runtime/Reallusion/Shaders/CCPBROpacity.gdshader b/Runtime/Reallusion/Shaders/CCPBROpacity.gdshader new file mode 100644 index 0000000..3524cc0 --- /dev/null +++ b/Runtime/Reallusion/Shaders/CCPBROpacity.gdshader @@ -0,0 +1,4 @@ +shader_type spatial; +render_mode blend_mix, depth_draw_opaque, cull_back, diffuse_burley, specular_schlick_ggx; + +#include "res://addons/rokojori_action_library/Runtime/Reallusion/Shaders/CCPBROpacityBase.gdshaderinc" \ No newline at end of file diff --git a/Runtime/Reallusion/Shaders/CCPBROpacity.gdshader.uid b/Runtime/Reallusion/Shaders/CCPBROpacity.gdshader.uid new file mode 100644 index 0000000..16d6c5b --- /dev/null +++ b/Runtime/Reallusion/Shaders/CCPBROpacity.gdshader.uid @@ -0,0 +1 @@ +uid://dg88aky5t1qi4 diff --git a/Runtime/Reallusion/Shaders/CCPBROpacityBase.gdshaderinc b/Runtime/Reallusion/Shaders/CCPBROpacityBase.gdshaderinc new file mode 100644 index 0000000..40376bf --- /dev/null +++ b/Runtime/Reallusion/Shaders/CCPBROpacityBase.gdshaderinc @@ -0,0 +1,88 @@ +#include "res://addons/rokojori_action_library/Runtime/Shading/Library/Textures.gdshaderinc" + +uniform vec4 albedo : source_color; +uniform sampler2D texture_albedo : source_color, filter_linear_mipmap_anisotropic, repeat_enable; +uniform sampler2D texture_opacity:hint_default_white; +uniform float opacity: hint_range(0, 5) = 1; + +#ifdef USE_ALPHA_SCISSOR +uniform float alphaScissorTreshold:hint_range(0,1) = 0.4; +#endif + +#ifdef USE_ALPHA_DISCARD +uniform float alphaDiscardTreshold:hint_range(0,1) = 0.4; +#endif + +uniform sampler2D texture_normal : hint_roughness_normal, filter_linear_mipmap_anisotropic, repeat_enable; +uniform float normal_scale : hint_range(0, 5.0) = 1.0; + +uniform sampler2D texture_roughness : hint_roughness_r, filter_linear_mipmap_anisotropic, repeat_enable; +uniform float roughness : hint_range(0.0, 1.0) = 1.0; +uniform float roughnessOffset : hint_range(-1.0, 1.0) = 0.0; + +uniform sampler2D texture_metallic : hint_default_black, filter_linear_mipmap_anisotropic, repeat_enable; +uniform float metallic : hint_range(0.0, 1.0, 0.01) = 1.0; +uniform float metallicOffset : hint_range(-1.0, 1.0) = 0.0; + +uniform float specular : hint_range(0.0, 1.0); + +uniform sampler2D texture_ambient_occlusion : hint_default_white, filter_linear_mipmap_anisotropic, repeat_enable; +uniform float ao_light_affect : hint_range(0.0, 1.0) = 1.0; +uniform float ambientOcclusionAmount : hint_range(0.0, 2.0) = 1.0; +uniform float ambientOcclusionOffset : hint_range(-1.0, 1.0) = 0.0; + +uniform float rim : hint_range(0.0, 1.0); +uniform float rim_tint : hint_range(0.0, 1.0); + +uniform sampler2D texture_emission : source_color, hint_default_black, filter_linear_mipmap_anisotropic, repeat_enable; +uniform vec4 emission : source_color; +uniform float emission_energy : hint_range(0.0, 100.0); + + +uniform vec3 uv1_scale; +uniform vec3 uv1_offset; + +void vertex() +{ + UV = UV * uv1_scale.xy + uv1_offset.xy; +} + +void fragment() +{ + + ALPHA *= sampleAlpha( texture_opacity, texture_albedo, UV, albedo, opacity ); + + #ifdef USE_ALPHA_SCISSOR + + ALPHA_SCISSOR_THRESHOLD = alphaScissorTreshold; + + #endif + + #ifdef USE_ALPHA_DISCARD + + if ( ALPHA < alphaDiscardTreshold ) + { + discard; + } + + #endif + + ALBEDO = sampleRGB( texture_albedo, UV, albedo ); + + + METALLIC = sampleRed( texture_metallic, UV, metallic, metallicOffset ); + SPECULAR = specular; + ROUGHNESS = sampleRed( texture_roughness, UV, roughness, roughnessOffset ); + + NORMAL_MAP = sampleRGB( texture_normal, UV ); + NORMAL_MAP_DEPTH = normal_scale; + + EMISSION = sampleEmission( texture_emission, UV, emission_energy, emission ); + + RIM = rim; + RIM_TINT = rim_tint; + + AO = sampleOcclusion( texture_ambient_occlusion, UV, ambientOcclusionAmount, ambientOcclusionOffset ); + AO_LIGHT_AFFECT = ao_light_affect; + +} diff --git a/Runtime/Reallusion/Shaders/CCPBROpacityBase.gdshaderinc.uid b/Runtime/Reallusion/Shaders/CCPBROpacityBase.gdshaderinc.uid new file mode 100644 index 0000000..6793995 --- /dev/null +++ b/Runtime/Reallusion/Shaders/CCPBROpacityBase.gdshaderinc.uid @@ -0,0 +1 @@ +uid://8ep8ij3igfi7 diff --git a/Runtime/Reallusion/Shaders/CCPBROpacityDiscard.gdshader b/Runtime/Reallusion/Shaders/CCPBROpacityDiscard.gdshader new file mode 100644 index 0000000..fcf741b --- /dev/null +++ b/Runtime/Reallusion/Shaders/CCPBROpacityDiscard.gdshader @@ -0,0 +1,5 @@ +shader_type spatial; +render_mode blend_mix, depth_draw_always, cull_back, diffuse_burley, specular_schlick_ggx; + +#define USE_ALPHA_DISCARD +#include "res://addons/rokojori_action_library/Runtime/Reallusion/Shaders/CCPBROpacityBase.gdshaderinc" \ No newline at end of file diff --git a/Runtime/Reallusion/Shaders/CCPBROpacityDiscard.gdshader.uid b/Runtime/Reallusion/Shaders/CCPBROpacityDiscard.gdshader.uid new file mode 100644 index 0000000..35773b0 --- /dev/null +++ b/Runtime/Reallusion/Shaders/CCPBROpacityDiscard.gdshader.uid @@ -0,0 +1 @@ +uid://ban84lwb8ggkq diff --git a/Runtime/Reallusion/Shaders/CCPBROpacityMaterial.cs b/Runtime/Reallusion/Shaders/CCPBROpacityMaterial.cs new file mode 100644 index 0000000..d3c498b --- /dev/null +++ b/Runtime/Reallusion/Shaders/CCPBROpacityMaterial.cs @@ -0,0 +1,159 @@ +using Godot; + +namespace Rokojori +{ + // Generated by ShaderClassGenerator + + public class CCPBROpacityShader + { + public static readonly CachedResource shader = new CachedResource( + "res://addons/rokojori_action_library/Runtime/Reallusion/Shaders/CCPBROpacity.gdshader" + ); + + public static readonly ColorPropertyName albedo = ColorPropertyName.Create( "albedo" ); + public static readonly Texture2DPropertyName textureAlbedo = Texture2DPropertyName.Create( "texture_albedo" ); + public static readonly Vector2IPropertyName albedoTextureSize = Vector2IPropertyName.Create( "albedo_texture_size" ); + public static readonly FloatPropertyName pointSize = FloatPropertyName.Create( "point_size" ); + public static readonly Texture2DPropertyName textureOpacity = Texture2DPropertyName.Create( "texture_opacity" ); + public static readonly FloatPropertyName opacity = FloatPropertyName.Create( "opacity" ); + public static readonly FloatPropertyName roughness = FloatPropertyName.Create( "roughness" ); + public static readonly Texture2DPropertyName textureMetallic = Texture2DPropertyName.Create( "texture_metallic" ); + public static readonly Vector4PropertyName metallicTextureChannel = Vector4PropertyName.Create( "metallic_texture_channel" ); + public static readonly Texture2DPropertyName textureRoughness = Texture2DPropertyName.Create( "texture_roughness" ); + public static readonly FloatPropertyName specular = FloatPropertyName.Create( "specular" ); + public static readonly FloatPropertyName metallic = FloatPropertyName.Create( "metallic" ); + public static readonly Texture2DPropertyName textureEmission = Texture2DPropertyName.Create( "texture_emission" ); + public static readonly ColorPropertyName emission = ColorPropertyName.Create( "emission" ); + public static readonly FloatPropertyName emissionEnergy = FloatPropertyName.Create( "emission_energy" ); + public static readonly Texture2DPropertyName textureNormal = Texture2DPropertyName.Create( "texture_normal" ); + public static readonly FloatPropertyName normalScale = FloatPropertyName.Create( "normal_scale" ); + public static readonly FloatPropertyName rim = FloatPropertyName.Create( "rim" ); + public static readonly FloatPropertyName rimTint = FloatPropertyName.Create( "rim_tint" ); + public static readonly Texture2DPropertyName textureRim = Texture2DPropertyName.Create( "texture_rim" ); + public static readonly FloatPropertyName clearcoat = FloatPropertyName.Create( "clearcoat" ); + public static readonly FloatPropertyName clearcoatRoughness = FloatPropertyName.Create( "clearcoat_roughness" ); + public static readonly Texture2DPropertyName textureClearcoat = Texture2DPropertyName.Create( "texture_clearcoat" ); + public static readonly Texture2DPropertyName textureAmbientOcclusion = Texture2DPropertyName.Create( "texture_ambient_occlusion" ); + public static readonly Vector4PropertyName aoTextureChannel = Vector4PropertyName.Create( "ao_texture_channel" ); + public static readonly FloatPropertyName aoLightAffect = FloatPropertyName.Create( "ao_light_affect" ); + public static readonly FloatPropertyName subsurfaceScatteringStrength = FloatPropertyName.Create( "subsurface_scattering_strength" ); + public static readonly Texture2DPropertyName textureSubsurfaceScattering = Texture2DPropertyName.Create( "texture_subsurface_scattering" ); + public static readonly ColorPropertyName transmittanceColor = ColorPropertyName.Create( "transmittance_color" ); + public static readonly FloatPropertyName transmittanceDepth = FloatPropertyName.Create( "transmittance_depth" ); + public static readonly Texture2DPropertyName textureSubsurfaceTransmittance = Texture2DPropertyName.Create( "texture_subsurface_transmittance" ); + public static readonly FloatPropertyName transmittanceBoost = FloatPropertyName.Create( "transmittance_boost" ); + public static readonly ColorPropertyName backlight = ColorPropertyName.Create( "backlight" ); + public static readonly Texture2DPropertyName textureBacklight = Texture2DPropertyName.Create( "texture_backlight" ); + public static readonly Texture2DPropertyName textureHeightmap = Texture2DPropertyName.Create( "texture_heightmap" ); + public static readonly FloatPropertyName heightmapScale = FloatPropertyName.Create( "heightmap_scale" ); + public static readonly IntPropertyName heightmapMinLayers = IntPropertyName.Create( "heightmap_min_layers" ); + public static readonly IntPropertyName heightmapMaxLayers = IntPropertyName.Create( "heightmap_max_layers" ); + public static readonly Vector2PropertyName heightmapFlip = Vector2PropertyName.Create( "heightmap_flip" ); + public static readonly Vector3PropertyName uv1Scale = Vector3PropertyName.Create( "uv1_scale" ); + public static readonly Vector3PropertyName uv1Offset = Vector3PropertyName.Create( "uv1_offset" ); + public static readonly Vector3PropertyName uv2Scale = Vector3PropertyName.Create( "uv2_scale" ); + public static readonly Vector3PropertyName uv2Offset = Vector3PropertyName.Create( "uv2_offset" ); + + } + + [Tool] + public partial class CCPBROpacityMaterial:CustomMaterial + { + + + public readonly CustomMaterialProperty albedo; + public readonly CustomMaterialProperty textureAlbedo; + public readonly CustomMaterialProperty albedoTextureSize; + public readonly CustomMaterialProperty pointSize; + public readonly CustomMaterialProperty textureOpacity; + public readonly CustomMaterialProperty opacity; + public readonly CustomMaterialProperty roughness; + public readonly CustomMaterialProperty textureMetallic; + public readonly CustomMaterialProperty metallicTextureChannel; + public readonly CustomMaterialProperty textureRoughness; + public readonly CustomMaterialProperty specular; + public readonly CustomMaterialProperty metallic; + public readonly CustomMaterialProperty textureEmission; + public readonly CustomMaterialProperty emission; + public readonly CustomMaterialProperty emissionEnergy; + public readonly CustomMaterialProperty textureNormal; + public readonly CustomMaterialProperty normalScale; + public readonly CustomMaterialProperty rim; + public readonly CustomMaterialProperty rimTint; + public readonly CustomMaterialProperty textureRim; + public readonly CustomMaterialProperty clearcoat; + public readonly CustomMaterialProperty clearcoatRoughness; + public readonly CustomMaterialProperty textureClearcoat; + public readonly CustomMaterialProperty textureAmbientOcclusion; + public readonly CustomMaterialProperty aoTextureChannel; + public readonly CustomMaterialProperty aoLightAffect; + public readonly CustomMaterialProperty subsurfaceScatteringStrength; + public readonly CustomMaterialProperty textureSubsurfaceScattering; + public readonly CustomMaterialProperty transmittanceColor; + public readonly CustomMaterialProperty transmittanceDepth; + public readonly CustomMaterialProperty textureSubsurfaceTransmittance; + public readonly CustomMaterialProperty transmittanceBoost; + public readonly CustomMaterialProperty backlight; + public readonly CustomMaterialProperty textureBacklight; + public readonly CustomMaterialProperty textureHeightmap; + public readonly CustomMaterialProperty heightmapScale; + public readonly CustomMaterialProperty heightmapMinLayers; + public readonly CustomMaterialProperty heightmapMaxLayers; + public readonly CustomMaterialProperty heightmapFlip; + public readonly CustomMaterialProperty uv1Scale; + public readonly CustomMaterialProperty uv1Offset; + public readonly CustomMaterialProperty uv2Scale; + public readonly CustomMaterialProperty uv2Offset; + + public CCPBROpacityMaterial() + { + Shader = CCPBROpacityShader.shader.Get(); + + albedo = new CustomMaterialProperty( this, CCPBROpacityShader.albedo ); + textureAlbedo = new CustomMaterialProperty( this, CCPBROpacityShader.textureAlbedo ); + albedoTextureSize = new CustomMaterialProperty( this, CCPBROpacityShader.albedoTextureSize ); + pointSize = new CustomMaterialProperty( this, CCPBROpacityShader.pointSize ); + textureOpacity = new CustomMaterialProperty( this, CCPBROpacityShader.textureOpacity ); + opacity = new CustomMaterialProperty( this, CCPBROpacityShader.opacity ); + roughness = new CustomMaterialProperty( this, CCPBROpacityShader.roughness ); + textureMetallic = new CustomMaterialProperty( this, CCPBROpacityShader.textureMetallic ); + metallicTextureChannel = new CustomMaterialProperty( this, CCPBROpacityShader.metallicTextureChannel ); + textureRoughness = new CustomMaterialProperty( this, CCPBROpacityShader.textureRoughness ); + specular = new CustomMaterialProperty( this, CCPBROpacityShader.specular ); + metallic = new CustomMaterialProperty( this, CCPBROpacityShader.metallic ); + textureEmission = new CustomMaterialProperty( this, CCPBROpacityShader.textureEmission ); + emission = new CustomMaterialProperty( this, CCPBROpacityShader.emission ); + emissionEnergy = new CustomMaterialProperty( this, CCPBROpacityShader.emissionEnergy ); + textureNormal = new CustomMaterialProperty( this, CCPBROpacityShader.textureNormal ); + normalScale = new CustomMaterialProperty( this, CCPBROpacityShader.normalScale ); + rim = new CustomMaterialProperty( this, CCPBROpacityShader.rim ); + rimTint = new CustomMaterialProperty( this, CCPBROpacityShader.rimTint ); + textureRim = new CustomMaterialProperty( this, CCPBROpacityShader.textureRim ); + clearcoat = new CustomMaterialProperty( this, CCPBROpacityShader.clearcoat ); + clearcoatRoughness = new CustomMaterialProperty( this, CCPBROpacityShader.clearcoatRoughness ); + textureClearcoat = new CustomMaterialProperty( this, CCPBROpacityShader.textureClearcoat ); + textureAmbientOcclusion = new CustomMaterialProperty( this, CCPBROpacityShader.textureAmbientOcclusion ); + aoTextureChannel = new CustomMaterialProperty( this, CCPBROpacityShader.aoTextureChannel ); + aoLightAffect = new CustomMaterialProperty( this, CCPBROpacityShader.aoLightAffect ); + subsurfaceScatteringStrength = new CustomMaterialProperty( this, CCPBROpacityShader.subsurfaceScatteringStrength ); + textureSubsurfaceScattering = new CustomMaterialProperty( this, CCPBROpacityShader.textureSubsurfaceScattering ); + transmittanceColor = new CustomMaterialProperty( this, CCPBROpacityShader.transmittanceColor ); + transmittanceDepth = new CustomMaterialProperty( this, CCPBROpacityShader.transmittanceDepth ); + textureSubsurfaceTransmittance = new CustomMaterialProperty( this, CCPBROpacityShader.textureSubsurfaceTransmittance ); + transmittanceBoost = new CustomMaterialProperty( this, CCPBROpacityShader.transmittanceBoost ); + backlight = new CustomMaterialProperty( this, CCPBROpacityShader.backlight ); + textureBacklight = new CustomMaterialProperty( this, CCPBROpacityShader.textureBacklight ); + textureHeightmap = new CustomMaterialProperty( this, CCPBROpacityShader.textureHeightmap ); + heightmapScale = new CustomMaterialProperty( this, CCPBROpacityShader.heightmapScale ); + heightmapMinLayers = new CustomMaterialProperty( this, CCPBROpacityShader.heightmapMinLayers ); + heightmapMaxLayers = new CustomMaterialProperty( this, CCPBROpacityShader.heightmapMaxLayers ); + heightmapFlip = new CustomMaterialProperty( this, CCPBROpacityShader.heightmapFlip ); + uv1Scale = new CustomMaterialProperty( this, CCPBROpacityShader.uv1Scale ); + uv1Offset = new CustomMaterialProperty( this, CCPBROpacityShader.uv1Offset ); + uv2Scale = new CustomMaterialProperty( this, CCPBROpacityShader.uv2Scale ); + uv2Offset = new CustomMaterialProperty( this, CCPBROpacityShader.uv2Offset ); + } + + } + +} \ No newline at end of file diff --git a/Runtime/Reallusion/Shaders/CCPBROpacityMaterial.cs.uid b/Runtime/Reallusion/Shaders/CCPBROpacityMaterial.cs.uid new file mode 100644 index 0000000..6bbbc72 --- /dev/null +++ b/Runtime/Reallusion/Shaders/CCPBROpacityMaterial.cs.uid @@ -0,0 +1 @@ +uid://gvk3nw2edy7l diff --git a/Runtime/Reallusion/Shaders/CCSkin.gdshader b/Runtime/Reallusion/Shaders/CCSkin.gdshader new file mode 100644 index 0000000..075f2d6 --- /dev/null +++ b/Runtime/Reallusion/Shaders/CCSkin.gdshader @@ -0,0 +1,5 @@ +shader_type spatial; +render_mode blend_mix, depth_draw_opaque, cull_back, diffuse_burley, specular_schlick_ggx, sss_mode_skin; + + +#include "res://addons/rokojori_action_library/Runtime/Reallusion/Shaders/CCSkinBase.gdshaderinc" diff --git a/Runtime/Reallusion/Shaders/CCSkin.gdshader.uid b/Runtime/Reallusion/Shaders/CCSkin.gdshader.uid new file mode 100644 index 0000000..0f40fa0 --- /dev/null +++ b/Runtime/Reallusion/Shaders/CCSkin.gdshader.uid @@ -0,0 +1 @@ +uid://bqarvud66yyfy diff --git a/Runtime/Reallusion/Shaders/CCSkinBase.gdshaderinc b/Runtime/Reallusion/Shaders/CCSkinBase.gdshaderinc new file mode 100644 index 0000000..f4b7a71 --- /dev/null +++ b/Runtime/Reallusion/Shaders/CCSkinBase.gdshaderinc @@ -0,0 +1,113 @@ + +#include "res://addons/rokojori_action_library/Runtime/Shading/Library/Colors.gdshaderinc" +#include "res://addons/rokojori_action_library/Runtime/Shading/Library/Noise.gdshaderinc" +#include "res://addons/rokojori_action_library/Runtime/Shading/Library/Transform.gdshaderinc" +#include "res://addons/rokojori_action_library/Runtime/Shading/Library/Normals.gdshaderinc" + +uniform vec4 albedo : source_color; +uniform sampler2D texture_albedo : source_color, filter_linear_mipmap, repeat_enable; +uniform sampler2D texture_albedoNoise : source_color, filter_linear_mipmap, repeat_enable; +uniform float albedoNoise : hint_range(0.0, 1.0) = 0; +uniform float albedoNoiseOffset : hint_range(-1.0, 1.0) = 0.1 ; +uniform float albedoNoiseUVScale : hint_range(0.0, 5.0) = 1.0; +uniform float albedoNoiseToRoughness: hint_range(-5.0, 5.0) = 0.1; +uniform float roughness : hint_range(0.0, 1.0) = 1.0; +uniform float roughnessOffset : hint_range(-1.0, 1.0) = 0.1; + +uniform float roughnessOverwriteAmount : hint_range(0.0, 1.0) = 0; +uniform float roughnessOverwriteValue : hint_range(0.0, 1.0) = 0; + +uniform sampler2D texture_roughness : hint_roughness_r, filter_linear_mipmap, repeat_enable; + +uniform float specular : hint_range(0.0, 1.0, 0.01); +uniform sampler2D texture_specular : hint_default_white, filter_linear_mipmap, repeat_enable; + + +uniform sampler2D texture_normal : hint_roughness_normal, filter_linear_mipmap, repeat_enable; +uniform float normal_scale : hint_range(0, 16.0) = 1.0; + +uniform float rim : hint_range(0.0, 1.0, 0.01) = 0.5; +uniform float rim_tint : hint_range(0.0, 1.0, 0.01) = 0.85; + +uniform sampler2D texture_ambient_occlusion : hint_default_white, filter_linear_mipmap, repeat_enable; +uniform float ao_light_affect : hint_range(0.0, 1.0, 0.01) = 1.0; + +uniform sampler2D microNormalTexture : hint_normal, filter_linear_mipmap, repeat_enable; +uniform sampler2D microNormalMaskTexture : hint_default_white, filter_linear_mipmap, repeat_enable; +uniform float microNormalScale = 1; + +uniform float subsurface_scattering_strength : hint_range(0.0, 1.0, 0.01) = 1.0; +uniform sampler2D texture_subsurface_scattering : hint_default_white, filter_linear_mipmap, repeat_enable; + +#ifdef USE_TRANSMISSION + +uniform bool transmissionEnabled = false; +uniform vec4 transmittance_color : source_color = vec4( 1,1,1,1); +uniform float transmittance_depth : hint_range(0.001, 8.0, 0.001) = 8.0; +uniform sampler2D texture_subsurface_transmittance : hint_default_white, filter_linear_mipmap, repeat_enable; +uniform float transmittance_boost : hint_range(0.0, 1.0, 0.01) = 0.5; + +#endif + +uniform vec3 uv1_scale; +uniform vec3 uv1_offset; + +uniform vec3 uv2_scale; +uniform vec3 uv2_offset; + +void vertex() +{ + UV = UV * uv1_scale.xy + uv1_offset.xy; + UV2 = UV * uv2_scale.xy + uv2_offset.xy; +} + + +void fragment() +{ + vec2 base_uv = UV; + vec2 base_uv2 = UV2; + + + vec4 albedo_tex = texture(texture_albedo, base_uv); + vec4 noise_tex = ( texture(texture_albedoNoise, base_uv * albedoNoiseUVScale) + albedoNoiseOffset ) * albedoNoise; + float noiseLuma = ( noise_tex.r + noise_tex.g + noise_tex.b ) / 3.0; + ALBEDO = albedo.rgb * albedo_tex.rgb + noise_tex.rgb; + + + float specular_tex = 1.0 - pow( texture(texture_specular, base_uv).r, 2.2 ); + SPECULAR = specular * specular_tex; + + float roughness_tex = texture(texture_roughness, base_uv).r; + float roughnessCombined = clamp( roughness_tex * roughness + roughnessOffset + noiseLuma * albedoNoiseToRoughness, 0, 1); + roughnessCombined = mix( roughnessCombined, roughnessOverwriteValue, roughnessOverwriteAmount ); + ROUGHNESS = roughnessCombined; + + NORMAL_MAP = texture(texture_normal, base_uv).rgb; + NORMAL_MAP_DEPTH = normal_scale; + + RIM = rim; + RIM_TINT = rim_tint; + + AO = texture(texture_ambient_occlusion, base_uv).r; + AO_LIGHT_AFFECT = ao_light_affect; + + float sss_tex = texture(texture_subsurface_scattering, base_uv).r; + SSS_STRENGTH = subsurface_scattering_strength * sss_tex; + + #ifdef USE_TRANSMISSION + + float transmittance_tex = texture(texture_subsurface_transmittance, base_uv).r; + SSS_TRANSMITTANCE_COLOR = transmittance_color; + SSS_TRANSMITTANCE_DEPTH = transmittance_depth; + SSS_TRANSMITTANCE_BOOST = transmittance_boost * transmittance_tex; + + #endif + + BACKLIGHT = albedo.rgb * albedo_tex.rgb * 0.2; + + vec4 microNormalSampled = texture( microNormalTexture, base_uv2 ); + vec4 microNormalMaskSampled = texture( microNormalMaskTexture, base_uv ); + vec3 microNormal = scaleNormalMap( microNormalSampled.rgb, microNormalScale * 1.5 ); + + NORMAL_MAP = mix( NORMAL_MAP, addNormalMaps( NORMAL_MAP, microNormal ), microNormalScale ); +} diff --git a/Runtime/Reallusion/Shaders/CCSkinBase.gdshaderinc.uid b/Runtime/Reallusion/Shaders/CCSkinBase.gdshaderinc.uid new file mode 100644 index 0000000..e99f940 --- /dev/null +++ b/Runtime/Reallusion/Shaders/CCSkinBase.gdshaderinc.uid @@ -0,0 +1 @@ +uid://qkjbruh0u50k diff --git a/Runtime/Reallusion/Shaders/CCSkinMaterial.cs b/Runtime/Reallusion/Shaders/CCSkinMaterial.cs new file mode 100644 index 0000000..7c022b6 --- /dev/null +++ b/Runtime/Reallusion/Shaders/CCSkinMaterial.cs @@ -0,0 +1,117 @@ +using Godot; + +namespace Rokojori +{ + // Generated by ShaderClassGenerator + + public class CCSkinShader + { + public static readonly CachedResource shader = new CachedResource( + "res://addons/rokojori_action_library/Runtime/Reallusion/Shaders/CCSkin.gdshader" + ); + + public static readonly ColorPropertyName albedo = ColorPropertyName.Create( "albedo" ); + public static readonly Texture2DPropertyName textureAlbedo = Texture2DPropertyName.Create( "texture_albedo" ); + public static readonly Texture2DPropertyName textureAlbedoNoise = Texture2DPropertyName.Create( "texture_albedoNoise" ); + public static readonly FloatPropertyName albedoNoise = FloatPropertyName.Create( "albedoNoise" ); + public static readonly FloatPropertyName albedoNoiseOffset = FloatPropertyName.Create( "albedoNoiseOffset" ); + public static readonly FloatPropertyName albedoNoiseUvScale = FloatPropertyName.Create( "albedoNoiseUVScale" ); + public static readonly FloatPropertyName albedoNoiseToRoughness = FloatPropertyName.Create( "albedoNoiseToRoughness" ); + public static readonly FloatPropertyName roughness = FloatPropertyName.Create( "roughness" ); + public static readonly FloatPropertyName roughnessOffset = FloatPropertyName.Create( "roughnessOffset" ); + public static readonly FloatPropertyName roughnessOverwriteAmount = FloatPropertyName.Create( "roughnessOverwriteAmount" ); + public static readonly FloatPropertyName roughnessOverwriteValue = FloatPropertyName.Create( "roughnessOverwriteValue" ); + public static readonly Texture2DPropertyName textureRoughness = Texture2DPropertyName.Create( "texture_roughness" ); + public static readonly FloatPropertyName specular = FloatPropertyName.Create( "specular" ); + public static readonly Texture2DPropertyName textureSpecular = Texture2DPropertyName.Create( "texture_specular" ); + public static readonly Texture2DPropertyName textureNormal = Texture2DPropertyName.Create( "texture_normal" ); + public static readonly FloatPropertyName normalScale = FloatPropertyName.Create( "normal_scale" ); + public static readonly FloatPropertyName rim = FloatPropertyName.Create( "rim" ); + public static readonly FloatPropertyName rimTint = FloatPropertyName.Create( "rim_tint" ); + public static readonly Texture2DPropertyName textureAmbientOcclusion = Texture2DPropertyName.Create( "texture_ambient_occlusion" ); + public static readonly FloatPropertyName aoLightAffect = FloatPropertyName.Create( "ao_light_affect" ); + public static readonly Texture2DPropertyName microNormalTexture = Texture2DPropertyName.Create( "microNormalTexture" ); + public static readonly Texture2DPropertyName microNormalMaskTexture = Texture2DPropertyName.Create( "microNormalMaskTexture" ); + public static readonly FloatPropertyName microNormalScale = FloatPropertyName.Create( "microNormalScale" ); + public static readonly FloatPropertyName subsurfaceScatteringStrength = FloatPropertyName.Create( "subsurface_scattering_strength" ); + public static readonly Texture2DPropertyName textureSubsurfaceScattering = Texture2DPropertyName.Create( "texture_subsurface_scattering" ); + public static readonly Vector3PropertyName uv1Scale = Vector3PropertyName.Create( "uv1_scale" ); + public static readonly Vector3PropertyName uv1Offset = Vector3PropertyName.Create( "uv1_offset" ); + public static readonly Vector3PropertyName uv2Scale = Vector3PropertyName.Create( "uv2_scale" ); + public static readonly Vector3PropertyName uv2Offset = Vector3PropertyName.Create( "uv2_offset" ); + + } + + [Tool] + public partial class CCSkinMaterial:CustomMaterial + { + + + public readonly CustomMaterialProperty albedo; + public readonly CustomMaterialProperty textureAlbedo; + public readonly CustomMaterialProperty textureAlbedoNoise; + public readonly CustomMaterialProperty albedoNoise; + public readonly CustomMaterialProperty albedoNoiseOffset; + public readonly CustomMaterialProperty albedoNoiseUvScale; + public readonly CustomMaterialProperty albedoNoiseToRoughness; + public readonly CustomMaterialProperty roughness; + public readonly CustomMaterialProperty roughnessOffset; + public readonly CustomMaterialProperty roughnessOverwriteAmount; + public readonly CustomMaterialProperty roughnessOverwriteValue; + public readonly CustomMaterialProperty textureRoughness; + public readonly CustomMaterialProperty specular; + public readonly CustomMaterialProperty textureSpecular; + public readonly CustomMaterialProperty textureNormal; + public readonly CustomMaterialProperty normalScale; + public readonly CustomMaterialProperty rim; + public readonly CustomMaterialProperty rimTint; + public readonly CustomMaterialProperty textureAmbientOcclusion; + public readonly CustomMaterialProperty aoLightAffect; + public readonly CustomMaterialProperty microNormalTexture; + public readonly CustomMaterialProperty microNormalMaskTexture; + public readonly CustomMaterialProperty microNormalScale; + public readonly CustomMaterialProperty subsurfaceScatteringStrength; + public readonly CustomMaterialProperty textureSubsurfaceScattering; + public readonly CustomMaterialProperty uv1Scale; + public readonly CustomMaterialProperty uv1Offset; + public readonly CustomMaterialProperty uv2Scale; + public readonly CustomMaterialProperty uv2Offset; + + public CCSkinMaterial() + { + Shader = CCSkinShader.shader.Get(); + + albedo = new CustomMaterialProperty( this, CCSkinShader.albedo ); + textureAlbedo = new CustomMaterialProperty( this, CCSkinShader.textureAlbedo ); + textureAlbedoNoise = new CustomMaterialProperty( this, CCSkinShader.textureAlbedoNoise ); + albedoNoise = new CustomMaterialProperty( this, CCSkinShader.albedoNoise ); + albedoNoiseOffset = new CustomMaterialProperty( this, CCSkinShader.albedoNoiseOffset ); + albedoNoiseUvScale = new CustomMaterialProperty( this, CCSkinShader.albedoNoiseUvScale ); + albedoNoiseToRoughness = new CustomMaterialProperty( this, CCSkinShader.albedoNoiseToRoughness ); + roughness = new CustomMaterialProperty( this, CCSkinShader.roughness ); + roughnessOffset = new CustomMaterialProperty( this, CCSkinShader.roughnessOffset ); + roughnessOverwriteAmount = new CustomMaterialProperty( this, CCSkinShader.roughnessOverwriteAmount ); + roughnessOverwriteValue = new CustomMaterialProperty( this, CCSkinShader.roughnessOverwriteValue ); + textureRoughness = new CustomMaterialProperty( this, CCSkinShader.textureRoughness ); + specular = new CustomMaterialProperty( this, CCSkinShader.specular ); + textureSpecular = new CustomMaterialProperty( this, CCSkinShader.textureSpecular ); + textureNormal = new CustomMaterialProperty( this, CCSkinShader.textureNormal ); + normalScale = new CustomMaterialProperty( this, CCSkinShader.normalScale ); + rim = new CustomMaterialProperty( this, CCSkinShader.rim ); + rimTint = new CustomMaterialProperty( this, CCSkinShader.rimTint ); + textureAmbientOcclusion = new CustomMaterialProperty( this, CCSkinShader.textureAmbientOcclusion ); + aoLightAffect = new CustomMaterialProperty( this, CCSkinShader.aoLightAffect ); + microNormalTexture = new CustomMaterialProperty( this, CCSkinShader.microNormalTexture ); + microNormalMaskTexture = new CustomMaterialProperty( this, CCSkinShader.microNormalMaskTexture ); + microNormalScale = new CustomMaterialProperty( this, CCSkinShader.microNormalScale ); + subsurfaceScatteringStrength = new CustomMaterialProperty( this, CCSkinShader.subsurfaceScatteringStrength ); + textureSubsurfaceScattering = new CustomMaterialProperty( this, CCSkinShader.textureSubsurfaceScattering ); + uv1Scale = new CustomMaterialProperty( this, CCSkinShader.uv1Scale ); + uv1Offset = new CustomMaterialProperty( this, CCSkinShader.uv1Offset ); + uv2Scale = new CustomMaterialProperty( this, CCSkinShader.uv2Scale ); + uv2Offset = new CustomMaterialProperty( this, CCSkinShader.uv2Offset ); + } + + } + +} \ No newline at end of file diff --git a/Runtime/Reallusion/Shaders/CCSkinMaterial.cs.uid b/Runtime/Reallusion/Shaders/CCSkinMaterial.cs.uid new file mode 100644 index 0000000..a48cf21 --- /dev/null +++ b/Runtime/Reallusion/Shaders/CCSkinMaterial.cs.uid @@ -0,0 +1 @@ +uid://mqocokmx7gtq diff --git a/Runtime/Reallusion/Shaders/CCSkinTransmissive.gdshader b/Runtime/Reallusion/Shaders/CCSkinTransmissive.gdshader new file mode 100644 index 0000000..47e1178 --- /dev/null +++ b/Runtime/Reallusion/Shaders/CCSkinTransmissive.gdshader @@ -0,0 +1,5 @@ +shader_type spatial; +render_mode blend_mix, depth_draw_opaque, cull_back, diffuse_burley, specular_schlick_ggx, sss_mode_skin; + +#define USE_TRANSMISSION +#include "res://addons/rokojori_action_library/Runtime/Reallusion/Shaders/CCSkinBase.gdshaderinc" diff --git a/Runtime/Reallusion/Shaders/CCSkinTransmissive.gdshader.uid b/Runtime/Reallusion/Shaders/CCSkinTransmissive.gdshader.uid new file mode 100644 index 0000000..2ab8c9c --- /dev/null +++ b/Runtime/Reallusion/Shaders/CCSkinTransmissive.gdshader.uid @@ -0,0 +1 @@ +uid://b6uqr1f87laoa diff --git a/Runtime/Reallusion/Shaders/CCSkinTransmissiveMaterial.cs b/Runtime/Reallusion/Shaders/CCSkinTransmissiveMaterial.cs new file mode 100644 index 0000000..f015fbf --- /dev/null +++ b/Runtime/Reallusion/Shaders/CCSkinTransmissiveMaterial.cs @@ -0,0 +1,132 @@ +using Godot; + +namespace Rokojori +{ + // Generated by ShaderClassGenerator + + public class CCSkinTransmissiveShader + { + public static readonly CachedResource shader = new CachedResource( + "res://addons/rokojori_action_library/Runtime/Reallusion/Shaders/CCSkinTransmissive.gdshader" + ); + + public static readonly ColorPropertyName albedo = ColorPropertyName.Create( "albedo" ); + public static readonly Texture2DPropertyName textureAlbedo = Texture2DPropertyName.Create( "texture_albedo" ); + public static readonly Texture2DPropertyName textureAlbedoNoise = Texture2DPropertyName.Create( "texture_albedoNoise" ); + public static readonly FloatPropertyName albedoNoise = FloatPropertyName.Create( "albedoNoise" ); + public static readonly FloatPropertyName albedoNoiseOffset = FloatPropertyName.Create( "albedoNoiseOffset" ); + public static readonly FloatPropertyName albedoNoiseUvScale = FloatPropertyName.Create( "albedoNoiseUVScale" ); + public static readonly FloatPropertyName albedoNoiseToRoughness = FloatPropertyName.Create( "albedoNoiseToRoughness" ); + public static readonly FloatPropertyName roughness = FloatPropertyName.Create( "roughness" ); + public static readonly FloatPropertyName roughnessOffset = FloatPropertyName.Create( "roughnessOffset" ); + public static readonly FloatPropertyName roughnessOverwriteAmount = FloatPropertyName.Create( "roughnessOverwriteAmount" ); + public static readonly FloatPropertyName roughnessOverwriteValue = FloatPropertyName.Create( "roughnessOverwriteValue" ); + public static readonly Texture2DPropertyName textureRoughness = Texture2DPropertyName.Create( "texture_roughness" ); + public static readonly FloatPropertyName specular = FloatPropertyName.Create( "specular" ); + public static readonly Texture2DPropertyName textureSpecular = Texture2DPropertyName.Create( "texture_specular" ); + public static readonly Texture2DPropertyName textureNormal = Texture2DPropertyName.Create( "texture_normal" ); + public static readonly FloatPropertyName normalScale = FloatPropertyName.Create( "normal_scale" ); + public static readonly FloatPropertyName rim = FloatPropertyName.Create( "rim" ); + public static readonly FloatPropertyName rimTint = FloatPropertyName.Create( "rim_tint" ); + public static readonly Texture2DPropertyName textureAmbientOcclusion = Texture2DPropertyName.Create( "texture_ambient_occlusion" ); + public static readonly FloatPropertyName aoLightAffect = FloatPropertyName.Create( "ao_light_affect" ); + public static readonly Texture2DPropertyName microNormalTexture = Texture2DPropertyName.Create( "microNormalTexture" ); + public static readonly Texture2DPropertyName microNormalMaskTexture = Texture2DPropertyName.Create( "microNormalMaskTexture" ); + public static readonly FloatPropertyName microNormalScale = FloatPropertyName.Create( "microNormalScale" ); + public static readonly FloatPropertyName subsurfaceScatteringStrength = FloatPropertyName.Create( "subsurface_scattering_strength" ); + public static readonly Texture2DPropertyName textureSubsurfaceScattering = Texture2DPropertyName.Create( "texture_subsurface_scattering" ); + public static readonly BoolPropertyName transmissionEnabled = BoolPropertyName.Create( "transmissionEnabled" ); + public static readonly ColorPropertyName transmittanceColor = ColorPropertyName.Create( "transmittance_color" ); + public static readonly FloatPropertyName transmittanceDepth = FloatPropertyName.Create( "transmittance_depth" ); + public static readonly Texture2DPropertyName textureSubsurfaceTransmittance = Texture2DPropertyName.Create( "texture_subsurface_transmittance" ); + public static readonly FloatPropertyName transmittanceBoost = FloatPropertyName.Create( "transmittance_boost" ); + public static readonly Vector3PropertyName uv1Scale = Vector3PropertyName.Create( "uv1_scale" ); + public static readonly Vector3PropertyName uv1Offset = Vector3PropertyName.Create( "uv1_offset" ); + public static readonly Vector3PropertyName uv2Scale = Vector3PropertyName.Create( "uv2_scale" ); + public static readonly Vector3PropertyName uv2Offset = Vector3PropertyName.Create( "uv2_offset" ); + + } + + [Tool] + public partial class CCSkinTransmissiveMaterial:CustomMaterial + { + + + public readonly CustomMaterialProperty albedo; + public readonly CustomMaterialProperty textureAlbedo; + public readonly CustomMaterialProperty textureAlbedoNoise; + public readonly CustomMaterialProperty albedoNoise; + public readonly CustomMaterialProperty albedoNoiseOffset; + public readonly CustomMaterialProperty albedoNoiseUvScale; + public readonly CustomMaterialProperty albedoNoiseToRoughness; + public readonly CustomMaterialProperty roughness; + public readonly CustomMaterialProperty roughnessOffset; + public readonly CustomMaterialProperty roughnessOverwriteAmount; + public readonly CustomMaterialProperty roughnessOverwriteValue; + public readonly CustomMaterialProperty textureRoughness; + public readonly CustomMaterialProperty specular; + public readonly CustomMaterialProperty textureSpecular; + public readonly CustomMaterialProperty textureNormal; + public readonly CustomMaterialProperty normalScale; + public readonly CustomMaterialProperty rim; + public readonly CustomMaterialProperty rimTint; + public readonly CustomMaterialProperty textureAmbientOcclusion; + public readonly CustomMaterialProperty aoLightAffect; + public readonly CustomMaterialProperty microNormalTexture; + public readonly CustomMaterialProperty microNormalMaskTexture; + public readonly CustomMaterialProperty microNormalScale; + public readonly CustomMaterialProperty subsurfaceScatteringStrength; + public readonly CustomMaterialProperty textureSubsurfaceScattering; + public readonly CustomMaterialProperty transmissionEnabled; + public readonly CustomMaterialProperty transmittanceColor; + public readonly CustomMaterialProperty transmittanceDepth; + public readonly CustomMaterialProperty textureSubsurfaceTransmittance; + public readonly CustomMaterialProperty transmittanceBoost; + public readonly CustomMaterialProperty uv1Scale; + public readonly CustomMaterialProperty uv1Offset; + public readonly CustomMaterialProperty uv2Scale; + public readonly CustomMaterialProperty uv2Offset; + + public CCSkinTransmissiveMaterial() + { + Shader = CCSkinTransmissiveShader.shader.Get(); + + albedo = new CustomMaterialProperty( this, CCSkinTransmissiveShader.albedo ); + textureAlbedo = new CustomMaterialProperty( this, CCSkinTransmissiveShader.textureAlbedo ); + textureAlbedoNoise = new CustomMaterialProperty( this, CCSkinTransmissiveShader.textureAlbedoNoise ); + albedoNoise = new CustomMaterialProperty( this, CCSkinTransmissiveShader.albedoNoise ); + albedoNoiseOffset = new CustomMaterialProperty( this, CCSkinTransmissiveShader.albedoNoiseOffset ); + albedoNoiseUvScale = new CustomMaterialProperty( this, CCSkinTransmissiveShader.albedoNoiseUvScale ); + albedoNoiseToRoughness = new CustomMaterialProperty( this, CCSkinTransmissiveShader.albedoNoiseToRoughness ); + roughness = new CustomMaterialProperty( this, CCSkinTransmissiveShader.roughness ); + roughnessOffset = new CustomMaterialProperty( this, CCSkinTransmissiveShader.roughnessOffset ); + roughnessOverwriteAmount = new CustomMaterialProperty( this, CCSkinTransmissiveShader.roughnessOverwriteAmount ); + roughnessOverwriteValue = new CustomMaterialProperty( this, CCSkinTransmissiveShader.roughnessOverwriteValue ); + textureRoughness = new CustomMaterialProperty( this, CCSkinTransmissiveShader.textureRoughness ); + specular = new CustomMaterialProperty( this, CCSkinTransmissiveShader.specular ); + textureSpecular = new CustomMaterialProperty( this, CCSkinTransmissiveShader.textureSpecular ); + textureNormal = new CustomMaterialProperty( this, CCSkinTransmissiveShader.textureNormal ); + normalScale = new CustomMaterialProperty( this, CCSkinTransmissiveShader.normalScale ); + rim = new CustomMaterialProperty( this, CCSkinTransmissiveShader.rim ); + rimTint = new CustomMaterialProperty( this, CCSkinTransmissiveShader.rimTint ); + textureAmbientOcclusion = new CustomMaterialProperty( this, CCSkinTransmissiveShader.textureAmbientOcclusion ); + aoLightAffect = new CustomMaterialProperty( this, CCSkinTransmissiveShader.aoLightAffect ); + microNormalTexture = new CustomMaterialProperty( this, CCSkinTransmissiveShader.microNormalTexture ); + microNormalMaskTexture = new CustomMaterialProperty( this, CCSkinTransmissiveShader.microNormalMaskTexture ); + microNormalScale = new CustomMaterialProperty( this, CCSkinTransmissiveShader.microNormalScale ); + subsurfaceScatteringStrength = new CustomMaterialProperty( this, CCSkinTransmissiveShader.subsurfaceScatteringStrength ); + textureSubsurfaceScattering = new CustomMaterialProperty( this, CCSkinTransmissiveShader.textureSubsurfaceScattering ); + transmissionEnabled = new CustomMaterialProperty( this, CCSkinTransmissiveShader.transmissionEnabled ); + transmittanceColor = new CustomMaterialProperty( this, CCSkinTransmissiveShader.transmittanceColor ); + transmittanceDepth = new CustomMaterialProperty( this, CCSkinTransmissiveShader.transmittanceDepth ); + textureSubsurfaceTransmittance = new CustomMaterialProperty( this, CCSkinTransmissiveShader.textureSubsurfaceTransmittance ); + transmittanceBoost = new CustomMaterialProperty( this, CCSkinTransmissiveShader.transmittanceBoost ); + uv1Scale = new CustomMaterialProperty( this, CCSkinTransmissiveShader.uv1Scale ); + uv1Offset = new CustomMaterialProperty( this, CCSkinTransmissiveShader.uv1Offset ); + uv2Scale = new CustomMaterialProperty( this, CCSkinTransmissiveShader.uv2Scale ); + uv2Offset = new CustomMaterialProperty( this, CCSkinTransmissiveShader.uv2Offset ); + } + + } + +} \ No newline at end of file diff --git a/Runtime/Reallusion/Shaders/CCSkinTransmissiveMaterial.cs.uid b/Runtime/Reallusion/Shaders/CCSkinTransmissiveMaterial.cs.uid new file mode 100644 index 0000000..0e4a887 --- /dev/null +++ b/Runtime/Reallusion/Shaders/CCSkinTransmissiveMaterial.cs.uid @@ -0,0 +1 @@ +uid://cuulgfgoal8er diff --git a/Runtime/Reallusion/Shaders/Hair/CCHairBase.gdshaderinc b/Runtime/Reallusion/Shaders/Hair/CCHairBase.gdshaderinc new file mode 100644 index 0000000..e33c53d --- /dev/null +++ b/Runtime/Reallusion/Shaders/Hair/CCHairBase.gdshaderinc @@ -0,0 +1,419 @@ +#include "res://addons/rokojori_action_library/Runtime/Shading/Library/Colors.gdshaderinc" +#include "res://addons/rokojori_action_library/Runtime/Shading/Library/Textures.gdshaderinc" +#include "res://addons/rokojori_action_library/Runtime/Shading/Library/Math.gdshaderinc" +#include "res://addons/rokojori_action_library/Runtime/Shading/Library/Cameras.gdshaderinc" + +group_uniforms Albedo; +uniform bool enabled = true; +uniform vec4 albedo : source_color; +uniform sampler2D texture_albedo : source_color, filter_linear_mipmap_anisotropic; +uniform vec3 hslOffset = vec3( 0, 0, 0 ); +uniform sampler2D texture_blend : source_color,hint_default_white, filter_linear_mipmap_anisotropic; +uniform float blendAmount:hint_range(0, 1) =1; + +uniform float naturalColors: hint_range(0, 1) = 0.5; + +uniform sampler2D texture_opacity:hint_default_white, filter_linear_mipmap_anisotropic; +uniform float opacity: hint_range(0, 1) = 0.5; +uniform float opacityGamma = 1; + +#ifdef USE_SHADOW +uniform float opacityFarScale: hint_range(0, 1) = 0.4; + +uniform float opacityBlur : hint_range(0, 10) = 4; +uniform float opacityBlurFarScale : hint_range(0, 10) = 8; + + +uniform float opacityFarStart = 0.5; +uniform float opacityFarRange = 5; +uniform float opacityFarPower = 0.5; +uniform float extending = 0.001; + +#endif + +#ifdef USE_ALPHA_SCISSOR +uniform float alphaScissorTreshold:hint_range(0,1) = 0.5; +#endif + +#ifdef USE_ALPHA_DISCARD +uniform float alphaDiscardTreshold:hint_range(0,1) = 0.05; +#endif + +group_uniforms; + +group_uniforms HairMaps; +uniform sampler2D rootMap : filter_linear_mipmap_anisotropic; +uniform sampler2D flowMap : filter_linear_mipmap_anisotropic; +uniform sampler2D idMap : filter_linear_mipmap_anisotropic; +group_uniforms; + +group_uniforms MainColors; +uniform float diffuseStrength:hint_range(0.0, 1.0) = 1; +uniform float vertexColorStrength:hint_range(0.0, 1.0) = 1; +uniform vec4 vertexGreyToColor:source_color; + +uniform bool activateHairColor = true; + +uniform float baseColorMapStrength:hint_range(0.0, 1.0) = 1; + +uniform vec4 strandRootColor:source_color; +uniform float strandRootStrength:hint_range(0.0, 1.0) = 1; + +uniform vec4 strandEndColor:source_color; +uniform float strandEndStrength:hint_range(0.0, 1.0) = 1; + +uniform float strandGamma = 1.0; +group_uniforms; + +group_uniforms Highlights; +uniform float maximumHighlightAmount = 0.25; +uniform float highlightFadeOutStart = 0.1; +uniform float highlightFadeOutEnd = 1; +uniform float highlightFadeOutPower = 0.5; +uniform float highlightFadeOutAmount = 0.2; + +group_uniforms; + +group_uniforms HighlightA; +uniform vec4 highlightAColor:source_color; +uniform float highlightAStrength:hint_range(0.0, 1.0) = 1.0; +uniform vec3 highlightARange = vec3( 0, 0.25, 0.5); +uniform float highlightAOverlapEnd: hint_range(0.0, 1.0) = 1.0; +uniform float highlightAInvert: hint_range(0.0, 1.0) = 0.0; + + +group_uniforms; + +group_uniforms HighlightB; +uniform vec4 highlightBColor:source_color; +uniform float highlightBStrength:hint_range(0.0, 1.0) = 1.0; +uniform vec3 highlightBRange = vec3( 0, 0.25, 0.5); +uniform float highlightBOverlapEnd: hint_range(0.0, 1.0) = 1.0; +uniform float highlightBInvert: hint_range(0.0, 1.0) = 0.0; +group_uniforms; + + +// group_uniforms Normal; +// uniform sampler2D texture_normal : hint_roughness_normal, filter_linear_mipmap_anisotropic, repeat_enable; +// uniform float normal_scale : hint_range(-16.0, 16.0) = 1.0; + +group_uniforms Roughness_Metallness; +uniform float roughness : hint_range(0.0, 1.0) = 1.0; +uniform float roughnessOffset: hint_range(-1.0, 1.0) = -0.1; +uniform sampler2D texture_roughness : hint_roughness_r, filter_linear_mipmap_anisotropic, repeat_enable; + +uniform float metallic : hint_range(0.0, 1.0, 0.01) = 1.0; +uniform float metallicOffset: hint_range(-1.0, 1.0) = 0.25; +uniform sampler2D texture_metallic : hint_default_white, filter_linear_mipmap_anisotropic, repeat_enable; + +uniform float specular : hint_range(0.0, 1.0, 0.01) = 0.2; +uniform float specularOpacityAmount: hint_range(0.0, 1.0) = 1; +uniform float specularOpacityGamma: hint_range(0.0, 3) = 2; + +uniform float anisotropy_ratio: hint_range(0.0, 1.0) = 1; + +group_uniforms; + +group_uniforms emission; +uniform sampler2D texture_emission : source_color, hint_default_black, filter_linear_mipmap_anisotropic, repeat_enable; +uniform vec4 emission : source_color; +uniform float emission_energy : hint_range(0.0, 100.0, 0.01); + +uniform vec4 backlight : source_color; +uniform float albedoToBacklightAmount : hint_range(0.0, 1.0) = 0.25; +uniform sampler2D texture_backlight : hint_default_black, filter_linear_mipmap_anisotropic, repeat_enable; + +uniform float subsurface_scattering_strength : hint_range(0.0, 1.0) = 1.0; +group_uniforms; + + +// uniform float rim : hint_range(0.0, 1.0, 0.01); +// uniform float rim_tint : hint_range(0.0, 1.0, 0.01); +// uniform sampler2D texture_rim : hint_default_white, filter_linear_mipmap_anisotropic, repeat_enable; + +// uniform float clearcoat : hint_range(0.0, 1.0, 0.01); +// uniform float clearcoat_roughness : hint_range(0.0, 1.0, 0.01); +// uniform sampler2D texture_clearcoat : hint_default_white, filter_linear_mipmap_anisotropic, repeat_enable; + +group_uniforms Occlusion; +uniform sampler2D texture_ambient_occlusion : hint_default_white, filter_linear_mipmap_anisotropic, repeat_enable; +uniform float ao_light_affect : hint_range(0.0, 1.0 ) = 1.0; +uniform float ambientOcclusion:hint_range(0.0, 2.0) = 1.0; +uniform float aoGamma: hint_range(0.1, 10) = 1.0; + +uniform float rootOcclusionAmount: hint_range(0.0, 1.0 ) = 0.1; +uniform float rootOcclusionRange: hint_range(0.0, 1.0 ) = 0.3; + +uniform float endOcclusionAmount: hint_range(0.0, 1.0 ) = 0.1; +uniform float endOcclusionRange: hint_range(0.0, 1.0 ) = 0.3; + +uniform float rootBasedOcclusion:hint_range(0.0, 1.0) = 0.5; + +group_uniforms; +// uniform float subsurface_scattering_strength : hint_range(0.0, 1.0, 0.01); +// uniform sampler2D texture_subsurface_scattering : hint_default_white, filter_linear_mipmap_anisotropic, repeat_enable; + +// uniform vec4 transmittance_color : source_color; +// uniform float transmittance_depth : hint_range(0.001, 8.0, 0.001); +// uniform sampler2D texture_subsurface_transmittance : hint_default_white, filter_linear_mipmap_anisotropic, repeat_enable; +// uniform float transmittance_boost : hint_range(0.0, 1.0, 0.01); + + + +// uniform sampler2D texture_heightmap : hint_default_black, filter_linear_mipmap_anisotropic, repeat_enable; +// uniform float heightmap_scale : hint_range(-16.0, 16.0, 0.001); +// uniform int heightmap_min_layers : hint_range(1, 64); +// uniform int heightmap_max_layers : hint_range(1, 64); +// uniform vec2 heightmap_flip; + +// uniform vec3 uv1_scale; +// uniform vec3 uv1_offset; +// uniform vec3 uv2_scale; +// uniform vec3 uv2_offset; + +float computeCameraFadeout( float cameraDistance, float close, float range, float power, float closeValue, float farValue ) +{ + float far = close + range; + float mapped = mapClamped( cameraDistance, close, far, 0, 1 ); + + float powered = pow( mapped, power ); + + return mix( closeValue, farValue, powered ); +} + + +float computeHighlightCameraFadeout( float cameraDistance, float fadeStart, float fadeEnd, float power, float fadeOut ) +{ + float mapped = mapClamped( cameraDistance, fadeStart, fadeEnd, 0, 1 ); + + float powered = pow( mapped, power ); + + return mix( 1, fadeOut, powered ); +} + +varying float fadeAmount; + +#ifdef USE_SHADOW +varying float shadowBlur; +varying float shadowOpacity; +#endif + +void vertex() +{ + + + // UV = UV * uv1_scale.xy + uv1_offset.xy; + + float cameraDistance = cameraDistanceLocal( VERTEX, CAMERA_POSITION_WORLD, MODEL_MATRIX ); + + fadeAmount = computeHighlightCameraFadeout( + cameraDistance, highlightFadeOutStart, highlightFadeOutEnd, highlightFadeOutPower, highlightFadeOutAmount + ) * maximumHighlightAmount; + + #ifdef USE_SHADOW + + float farAmount = computeCameraFadeout( + cameraDistance, opacityFarStart, opacityFarRange, opacityFarPower, 0, 1 + ); + + shadowBlur = mix( opacityBlur, opacityBlurFarScale, farAmount ); + shadowOpacity = mix( opacity, opacityFarScale, farAmount ); + + + vec2 uv = UV - 0.5; + float angle = atan( uv.y, uv.x ); + vec3 viewPosition = normalize( localToView( VERTEX, MODELVIEW_MATRIX ) ); + vec2 uvE = vec2( cos( angle ), sin( angle ) ); + uvE = viewPosition.xy; + + vec3 localX = viewToLocalDirection( vec3( 1, 0, 0 ), INV_VIEW_MATRIX, MODEL_MATRIX ); + vec3 localY = viewToLocalDirection( vec3( 0, 1, 0 ), INV_VIEW_MATRIX, MODEL_MATRIX ); + + VERTEX += extending * NORMAL; + #endif + + + + + // fadeAmountA = max( 1, clamp01( fadeAmountA ) ); + // fadeAmountB = max( 1, clamp01( fadeAmountB ) ); +} + +void fragment() +{ + if ( ! enabled ) + { + discard; + } + + // if ( ! FRONT_FACING ) + // { + // NORMAL = -NORMAL; + // } + + vec2 base_uv = UV; + + + vec4 albedo_tex = albedo * texture( texture_albedo, base_uv ); + albedo_tex.rgb = adjustHSL( albedo_tex.rgb, hslOffset ); + albedo_tex.rgb = albedo_tex.rgb * diffuseStrength; + + #ifdef USE_SHADOW + + albedo_tex.rgb = vec3( 0, 0, 0 ); + + float sampledAlpha = sampleRedBlurredUnclamped( texture_opacity, base_uv, shadowOpacity, 0, shadowBlur ); + ALPHA = clamp01( sampledAlpha ); + + + #else + ALPHA = pow( sampleRed( texture_opacity, base_uv, opacity, 0 ), opacityGamma ); + #endif + + + + #ifdef USE_ALPHA_SCISSOR + ALPHA_SCISSOR_THRESHOLD = alphaScissorTreshold; + #endif + + #ifdef USE_ALPHA_DISCARD + + if ( ALPHA < alphaDiscardTreshold ) + { + discard; + } + + #endif + + + + float root = clamp01( 1.0 - texture( rootMap, UV ).r ); + float id = texture( idMap, UV ).r; + + if ( activateHairColor ) + { + + albedo_tex = mix( vec4( 1, 1, 1, 1 ), albedo_tex, baseColorMapStrength ); + + + albedo_tex.rgb = mix( albedo_tex.rgb, vertexGreyToColor.rgb, ( 1.0 - COLOR.r ) * vertexColorStrength ); + + float strandAmount = mix( strandEndStrength, strandRootStrength, root ); + vec4 strandColor = mix( strandEndColor, strandRootColor, root ); + strandColor = gamma( strandColor, strandGamma ); + + // albedo_tex.rgb = blendMode_colorHSL( albedo_tex, strandColor, strandAmount ).rgb; + // albedo_tex.rgb = mix( albedo_tex.rgb, strandColor.rgb, strandAmount ); + albedo_tex.rgb = mix( albedo_tex, strandColor, strandAmount ).rgb; + + + float highlightABlend = rangeAmount( id, highlightARange ) * highlightAStrength; + float rootBlendAmountA = mix( 1.0, mix( root, 1.0 - root, highlightAInvert ), highlightAOverlapEnd ); + vec3 rootBlendedA = mix( albedo_tex.rgb, highlightAColor.rgb, clamp01( rootBlendAmountA ) ); + + albedo_tex.rgb = mix( albedo_tex.rgb, rootBlendedA, highlightABlend * fadeAmount ); + + + float highlightBBlend = rangeAmount( id, highlightBRange ) * highlightBStrength; + float rootBlendAmountB = mix( 1.0, mix( root, 1.0 - root, highlightBInvert ), highlightBOverlapEnd ); + vec3 rootBlendedB = mix( albedo_tex.rgb, highlightBColor.rgb, clamp01( rootBlendAmountB ) ); + + albedo_tex.rgb = mix( albedo_tex.rgb, rootBlendedB, highlightBBlend * fadeAmount ); + + + } + else + { + albedo_tex.rgb = mix( albedo_tex.rgb, vertexGreyToColor.rgb, ( 1.0 - COLOR.r ) * vertexColorStrength ); + } + + + ALBEDO = albedo_tex.rgb; + + + if ( naturalColors > 0.0 ) + { + // ALBEDO = ALBEDO * 0.95; + vec3 hsl = RGBtoHSL( ALBEDO ); + + hsl.z = pow( hsl.z, 0.95 ) * 0.95 + hsl.y * 0.05; + hsl.y = pow( hsl.y, 2 ); + + hsl = clamp( hsl, 0, 1 ); + + ALBEDO = mix( ALBEDO, HSLtoRGB( hsl ), naturalColors ); + } + + vec4 blendTexture = texture( texture_blend, UV ); + ALBEDO = mix( ALBEDO, ALBEDO * blendTexture.rgb, blendAmount ); + + + + + // ALBEDO = clamp( COLOR.rgb, 0, 1 ); + + float metallic_tex = texture(texture_metallic, base_uv).r; + METALLIC = clamp( metallic_tex * metallic + metallicOffset, 0, 1 ); + SPECULAR = specular * mix( 1.0, pow( ALPHA, specularOpacityGamma ), specularOpacityAmount ); + + float roughness_tex =texture(texture_roughness, base_uv).r; + ROUGHNESS = clamp( roughness_tex * roughness + roughnessOffset, 0, 1 ); + + // // Normal Map: Enabled + // NORMAL_MAP = texture(texture_normal, base_uv).rgb; + // NORMAL_MAP_DEPTH = normal_scale; + + // Emission: Enabled + vec3 emission_tex = texture(texture_emission, base_uv).rgb; + // Emission Operator: Add + EMISSION = (emission.rgb + emission_tex) * emission_energy; + + + + // // Rim: Enabled + // vec2 rim_tex = texture(texture_rim, base_uv).xy; + // RIM = rim * rim_tex.x; + // RIM_TINT = rim_tint * rim_tex.y; + + // // Clearcoat: Enabled + // vec2 clearcoat_tex = texture(texture_clearcoat, base_uv).xy; + // CLEARCOAT = clearcoat * clearcoat_tex.x; + // CLEARCOAT_ROUGHNESS = clearcoat_roughness * clearcoat_tex.y; + + // Ambient Occlusion: Enabled + float sampledAO = texture(texture_ambient_occlusion, base_uv).a; + float rootAO = mapClamped( root, 0.0, rootOcclusionRange, 1.0 - rootOcclusionAmount, 1 ); + float endAO = mapClamped( root, 1.0, 1.0 - endOcclusionRange, 1.0 - endOcclusionAmount, 1 ); + + sampledAO *= mix( 1, ( rootAO * endAO ), rootBasedOcclusion ); + + AO = mix( 1, pow( sampledAO, aoGamma ), ambientOcclusion ); + AO_LIGHT_AFFECT = ao_light_affect; + + // // Subsurface Scattering: Enabled + // float sss_tex = texture(texture_subsurface_scattering, base_uv).r; + SSS_STRENGTH = subsurface_scattering_strength * ALPHA; + + // // Backlight: Enabled + // vec3 backlight_tex = texture(texture_backlight, base_uv).rgb; + // BACKLIGHT = (backlight.rgb + backlight_tex); + BACKLIGHT = albedo_tex.rgb * albedoToBacklightAmount; + + vec3 anisotropy_tex = texture(flowMap, base_uv).rga; + ANISOTROPY = anisotropy_ratio * anisotropy_tex.b; + ANISOTROPY_FLOW = anisotropy_tex.rg * 2.0 - 1.0; + + #ifdef USE_SHADOW + + ALBEDO = vec3( 0, 0, 0 ); + BACKLIGHT = vec3( 0, 0, 0 ); + AO_LIGHT_AFFECT = 1.0; + AO = 0.0; + EMISSION = vec3( 0, 0, 0 ); + ROUGHNESS = 1.0; + METALLIC = 0.0; + SPECULAR = 0.0; + + + #endif +} diff --git a/Runtime/Reallusion/Shaders/Hair/CCHairBase.gdshaderinc.uid b/Runtime/Reallusion/Shaders/Hair/CCHairBase.gdshaderinc.uid new file mode 100644 index 0000000..92af996 --- /dev/null +++ b/Runtime/Reallusion/Shaders/Hair/CCHairBase.gdshaderinc.uid @@ -0,0 +1 @@ +uid://ddcll8orve76r diff --git a/Runtime/Reallusion/Shaders/Hair/Variants/CCHair.gdshader b/Runtime/Reallusion/Shaders/Hair/Variants/CCHair.gdshader new file mode 100644 index 0000000..4590e12 --- /dev/null +++ b/Runtime/Reallusion/Shaders/Hair/Variants/CCHair.gdshader @@ -0,0 +1,5 @@ +shader_type spatial; +render_mode blend_mix, depth_draw_always, cull_disabled, diffuse_burley, specular_schlick_ggx, depth_prepass_alpha; + +#define USE_ALPHA_DISCARD +#include "res://addons/rokojori_action_library/Runtime/Reallusion/Shaders/Hair/CCHairBase.gdshaderinc" \ No newline at end of file diff --git a/Runtime/Reallusion/Shaders/Hair/Variants/CCHair.gdshader.uid b/Runtime/Reallusion/Shaders/Hair/Variants/CCHair.gdshader.uid new file mode 100644 index 0000000..a4006ba --- /dev/null +++ b/Runtime/Reallusion/Shaders/Hair/Variants/CCHair.gdshader.uid @@ -0,0 +1 @@ +uid://xlv57lva582i diff --git a/Runtime/Reallusion/Shaders/Hair/Variants/CCHairAlpha.gdshader b/Runtime/Reallusion/Shaders/Hair/Variants/CCHairAlpha.gdshader new file mode 100644 index 0000000..be13096 --- /dev/null +++ b/Runtime/Reallusion/Shaders/Hair/Variants/CCHairAlpha.gdshader @@ -0,0 +1,5 @@ +shader_type spatial; +render_mode blend_mix, cull_back, diffuse_burley, specular_schlick_ggx; + +// #define USE_ALPHA_DISCARD +#include "res://addons/rokojori_action_library/Runtime/Reallusion/Shaders/Hair/CCHairBase.gdshaderinc" \ No newline at end of file diff --git a/Runtime/Reallusion/Shaders/Hair/Variants/CCHairAlpha.gdshader.uid b/Runtime/Reallusion/Shaders/Hair/Variants/CCHairAlpha.gdshader.uid new file mode 100644 index 0000000..58be605 --- /dev/null +++ b/Runtime/Reallusion/Shaders/Hair/Variants/CCHairAlpha.gdshader.uid @@ -0,0 +1 @@ +uid://cgfub655abfdm diff --git a/Runtime/Reallusion/Shaders/Hair/Variants/CCHairAlphaBack.gdshader b/Runtime/Reallusion/Shaders/Hair/Variants/CCHairAlphaBack.gdshader new file mode 100644 index 0000000..2d6a1e4 --- /dev/null +++ b/Runtime/Reallusion/Shaders/Hair/Variants/CCHairAlphaBack.gdshader @@ -0,0 +1,5 @@ +shader_type spatial; +render_mode blend_mix, cull_front, diffuse_burley, specular_schlick_ggx; + +// #define USE_ALPHA_DISCARD +#include "res://addons/rokojori_action_library/Runtime/Reallusion/Shaders/Hair/CCHairBase.gdshaderinc" \ No newline at end of file diff --git a/Runtime/Reallusion/Shaders/Hair/Variants/CCHairAlphaBack.gdshader.uid b/Runtime/Reallusion/Shaders/Hair/Variants/CCHairAlphaBack.gdshader.uid new file mode 100644 index 0000000..0d2f98d --- /dev/null +++ b/Runtime/Reallusion/Shaders/Hair/Variants/CCHairAlphaBack.gdshader.uid @@ -0,0 +1 @@ +uid://b8pcornyi7oe5 diff --git a/Runtime/Reallusion/Shaders/Hair/Variants/CCHairAlphaBackMaterial.cs b/Runtime/Reallusion/Shaders/Hair/Variants/CCHairAlphaBackMaterial.cs new file mode 100644 index 0000000..c2c9716 --- /dev/null +++ b/Runtime/Reallusion/Shaders/Hair/Variants/CCHairAlphaBackMaterial.cs @@ -0,0 +1,219 @@ +using Godot; + +namespace Rokojori +{ + // Generated by ShaderClassGenerator + + public class CCHairAlphaBackShader + { + public static readonly CachedResource shader = new CachedResource( + "res://addons/rokojori_action_library/Runtime/Reallusion/Shaders/Hair/Variants/CCHairAlphaBack.gdshader" + ); + + public static readonly BoolPropertyName enabled = BoolPropertyName.Create( "enabled" ); + public static readonly ColorPropertyName albedo = ColorPropertyName.Create( "albedo" ); + public static readonly Texture2DPropertyName textureAlbedo = Texture2DPropertyName.Create( "texture_albedo" ); + public static readonly Vector3PropertyName hslOffset = Vector3PropertyName.Create( "hslOffset" ); + public static readonly Texture2DPropertyName textureBlend = Texture2DPropertyName.Create( "texture_blend" ); + public static readonly FloatPropertyName blendAmount = FloatPropertyName.Create( "blendAmount" ); + public static readonly FloatPropertyName naturalColors = FloatPropertyName.Create( "naturalColors" ); + public static readonly Texture2DPropertyName textureOpacity = Texture2DPropertyName.Create( "texture_opacity" ); + public static readonly FloatPropertyName opacity = FloatPropertyName.Create( "opacity" ); + public static readonly FloatPropertyName opacityGamma = FloatPropertyName.Create( "opacityGamma" ); + public static readonly Texture2DPropertyName rootMap = Texture2DPropertyName.Create( "rootMap" ); + public static readonly Texture2DPropertyName flowMap = Texture2DPropertyName.Create( "flowMap" ); + public static readonly Texture2DPropertyName idMap = Texture2DPropertyName.Create( "idMap" ); + public static readonly FloatPropertyName diffuseStrength = FloatPropertyName.Create( "diffuseStrength" ); + public static readonly FloatPropertyName vertexColorStrength = FloatPropertyName.Create( "vertexColorStrength" ); + public static readonly ColorPropertyName vertexGreyToColor = ColorPropertyName.Create( "vertexGreyToColor" ); + public static readonly BoolPropertyName activateHairColor = BoolPropertyName.Create( "activateHairColor" ); + public static readonly FloatPropertyName baseColorMapStrength = FloatPropertyName.Create( "baseColorMapStrength" ); + public static readonly ColorPropertyName strandRootColor = ColorPropertyName.Create( "strandRootColor" ); + public static readonly FloatPropertyName strandRootStrength = FloatPropertyName.Create( "strandRootStrength" ); + public static readonly ColorPropertyName strandEndColor = ColorPropertyName.Create( "strandEndColor" ); + public static readonly FloatPropertyName strandEndStrength = FloatPropertyName.Create( "strandEndStrength" ); + public static readonly FloatPropertyName strandGamma = FloatPropertyName.Create( "strandGamma" ); + public static readonly FloatPropertyName maximumHighlightAmount = FloatPropertyName.Create( "maximumHighlightAmount" ); + public static readonly ColorPropertyName highlightAColor = ColorPropertyName.Create( "highlightAColor" ); + public static readonly FloatPropertyName highlightAStrength = FloatPropertyName.Create( "highlightAStrength" ); + public static readonly Vector3PropertyName highlightARange = Vector3PropertyName.Create( "highlightARange" ); + public static readonly FloatPropertyName highlightAOverlapEnd = FloatPropertyName.Create( "highlightAOverlapEnd" ); + public static readonly FloatPropertyName highlightAInvert = FloatPropertyName.Create( "highlightAInvert" ); + public static readonly FloatPropertyName highlightAFadeOutStart = FloatPropertyName.Create( "highlightAFadeOutStart" ); + public static readonly FloatPropertyName highlightAFadeOutRange = FloatPropertyName.Create( "highlightAFadeOutRange" ); + public static readonly FloatPropertyName highlightAFadeOutPower = FloatPropertyName.Create( "highlightAFadeOutPower" ); + public static readonly FloatPropertyName highlightAFadeOutAmount = FloatPropertyName.Create( "highlightAFadeOutAmount" ); + public static readonly ColorPropertyName highlightBColor = ColorPropertyName.Create( "highlightBColor" ); + public static readonly FloatPropertyName highlightBStrength = FloatPropertyName.Create( "highlightBStrength" ); + public static readonly Vector3PropertyName highlightBRange = Vector3PropertyName.Create( "highlightBRange" ); + public static readonly FloatPropertyName highlightBOverlapEnd = FloatPropertyName.Create( "highlightBOverlapEnd" ); + public static readonly FloatPropertyName highlightBInvert = FloatPropertyName.Create( "highlightBInvert" ); + public static readonly FloatPropertyName highlightBFadeOutStart = FloatPropertyName.Create( "highlightBFadeOutStart" ); + public static readonly FloatPropertyName highlightBFadeOutRange = FloatPropertyName.Create( "highlightBFadeOutRange" ); + public static readonly FloatPropertyName highlightBFadeOutPower = FloatPropertyName.Create( "highlightBFadeOutPower" ); + public static readonly FloatPropertyName highlightBFadeOutAmount = FloatPropertyName.Create( "highlightBFadeOutAmount" ); + public static readonly FloatPropertyName roughness = FloatPropertyName.Create( "roughness" ); + public static readonly FloatPropertyName roughnessOffset = FloatPropertyName.Create( "roughnessOffset" ); + public static readonly Texture2DPropertyName textureRoughness = Texture2DPropertyName.Create( "texture_roughness" ); + public static readonly FloatPropertyName metallic = FloatPropertyName.Create( "metallic" ); + public static readonly FloatPropertyName metallicOffset = FloatPropertyName.Create( "metallicOffset" ); + public static readonly Texture2DPropertyName textureMetallic = Texture2DPropertyName.Create( "texture_metallic" ); + public static readonly FloatPropertyName specular = FloatPropertyName.Create( "specular" ); + public static readonly Texture2DPropertyName textureEmission = Texture2DPropertyName.Create( "texture_emission" ); + public static readonly ColorPropertyName emission = ColorPropertyName.Create( "emission" ); + public static readonly FloatPropertyName emissionEnergy = FloatPropertyName.Create( "emission_energy" ); + public static readonly ColorPropertyName backlight = ColorPropertyName.Create( "backlight" ); + public static readonly FloatPropertyName albedoToBacklightAmount = FloatPropertyName.Create( "albedoToBacklightAmount" ); + public static readonly Texture2DPropertyName textureBacklight = Texture2DPropertyName.Create( "texture_backlight" ); + public static readonly Texture2DPropertyName textureAmbientOcclusion = Texture2DPropertyName.Create( "texture_ambient_occlusion" ); + public static readonly FloatPropertyName aoLightAffect = FloatPropertyName.Create( "ao_light_affect" ); + public static readonly FloatPropertyName ambientOcclusion = FloatPropertyName.Create( "ambientOcclusion" ); + public static readonly FloatPropertyName aoGamma = FloatPropertyName.Create( "aoGamma" ); + public static readonly FloatPropertyName rootOcclusionAmount = FloatPropertyName.Create( "rootOcclusionAmount" ); + public static readonly FloatPropertyName rootOcclusionRange = FloatPropertyName.Create( "rootOcclusionRange" ); + public static readonly FloatPropertyName endOcclusionAmount = FloatPropertyName.Create( "endOcclusionAmount" ); + public static readonly FloatPropertyName endOcclusionRange = FloatPropertyName.Create( "endOcclusionRange" ); + + } + + [Tool] + public partial class CCHairAlphaBackMaterial:CustomMaterial + { + + + public readonly CustomMaterialProperty enabled; + public readonly CustomMaterialProperty albedo; + public readonly CustomMaterialProperty textureAlbedo; + public readonly CustomMaterialProperty hslOffset; + public readonly CustomMaterialProperty textureBlend; + public readonly CustomMaterialProperty blendAmount; + public readonly CustomMaterialProperty naturalColors; + public readonly CustomMaterialProperty textureOpacity; + public readonly CustomMaterialProperty opacity; + public readonly CustomMaterialProperty opacityGamma; + public readonly CustomMaterialProperty rootMap; + public readonly CustomMaterialProperty flowMap; + public readonly CustomMaterialProperty idMap; + public readonly CustomMaterialProperty diffuseStrength; + public readonly CustomMaterialProperty vertexColorStrength; + public readonly CustomMaterialProperty vertexGreyToColor; + public readonly CustomMaterialProperty activateHairColor; + public readonly CustomMaterialProperty baseColorMapStrength; + public readonly CustomMaterialProperty strandRootColor; + public readonly CustomMaterialProperty strandRootStrength; + public readonly CustomMaterialProperty strandEndColor; + public readonly CustomMaterialProperty strandEndStrength; + public readonly CustomMaterialProperty strandGamma; + public readonly CustomMaterialProperty maximumHighlightAmount; + public readonly CustomMaterialProperty highlightAColor; + public readonly CustomMaterialProperty highlightAStrength; + public readonly CustomMaterialProperty highlightARange; + public readonly CustomMaterialProperty highlightAOverlapEnd; + public readonly CustomMaterialProperty highlightAInvert; + public readonly CustomMaterialProperty highlightAFadeOutStart; + public readonly CustomMaterialProperty highlightAFadeOutRange; + public readonly CustomMaterialProperty highlightAFadeOutPower; + public readonly CustomMaterialProperty highlightAFadeOutAmount; + public readonly CustomMaterialProperty highlightBColor; + public readonly CustomMaterialProperty highlightBStrength; + public readonly CustomMaterialProperty highlightBRange; + public readonly CustomMaterialProperty highlightBOverlapEnd; + public readonly CustomMaterialProperty highlightBInvert; + public readonly CustomMaterialProperty highlightBFadeOutStart; + public readonly CustomMaterialProperty highlightBFadeOutRange; + public readonly CustomMaterialProperty highlightBFadeOutPower; + public readonly CustomMaterialProperty highlightBFadeOutAmount; + public readonly CustomMaterialProperty roughness; + public readonly CustomMaterialProperty roughnessOffset; + public readonly CustomMaterialProperty textureRoughness; + public readonly CustomMaterialProperty metallic; + public readonly CustomMaterialProperty metallicOffset; + public readonly CustomMaterialProperty textureMetallic; + public readonly CustomMaterialProperty specular; + public readonly CustomMaterialProperty textureEmission; + public readonly CustomMaterialProperty emission; + public readonly CustomMaterialProperty emissionEnergy; + public readonly CustomMaterialProperty backlight; + public readonly CustomMaterialProperty albedoToBacklightAmount; + public readonly CustomMaterialProperty textureBacklight; + public readonly CustomMaterialProperty textureAmbientOcclusion; + public readonly CustomMaterialProperty aoLightAffect; + public readonly CustomMaterialProperty ambientOcclusion; + public readonly CustomMaterialProperty aoGamma; + public readonly CustomMaterialProperty rootOcclusionAmount; + public readonly CustomMaterialProperty rootOcclusionRange; + public readonly CustomMaterialProperty endOcclusionAmount; + public readonly CustomMaterialProperty endOcclusionRange; + + public CCHairAlphaBackMaterial() + { + Shader = CCHairAlphaBackShader.shader.Get(); + + enabled = new CustomMaterialProperty( this, CCHairAlphaBackShader.enabled ); + albedo = new CustomMaterialProperty( this, CCHairAlphaBackShader.albedo ); + textureAlbedo = new CustomMaterialProperty( this, CCHairAlphaBackShader.textureAlbedo ); + hslOffset = new CustomMaterialProperty( this, CCHairAlphaBackShader.hslOffset ); + textureBlend = new CustomMaterialProperty( this, CCHairAlphaBackShader.textureBlend ); + blendAmount = new CustomMaterialProperty( this, CCHairAlphaBackShader.blendAmount ); + naturalColors = new CustomMaterialProperty( this, CCHairAlphaBackShader.naturalColors ); + textureOpacity = new CustomMaterialProperty( this, CCHairAlphaBackShader.textureOpacity ); + opacity = new CustomMaterialProperty( this, CCHairAlphaBackShader.opacity ); + opacityGamma = new CustomMaterialProperty( this, CCHairAlphaBackShader.opacityGamma ); + rootMap = new CustomMaterialProperty( this, CCHairAlphaBackShader.rootMap ); + flowMap = new CustomMaterialProperty( this, CCHairAlphaBackShader.flowMap ); + idMap = new CustomMaterialProperty( this, CCHairAlphaBackShader.idMap ); + diffuseStrength = new CustomMaterialProperty( this, CCHairAlphaBackShader.diffuseStrength ); + vertexColorStrength = new CustomMaterialProperty( this, CCHairAlphaBackShader.vertexColorStrength ); + vertexGreyToColor = new CustomMaterialProperty( this, CCHairAlphaBackShader.vertexGreyToColor ); + activateHairColor = new CustomMaterialProperty( this, CCHairAlphaBackShader.activateHairColor ); + baseColorMapStrength = new CustomMaterialProperty( this, CCHairAlphaBackShader.baseColorMapStrength ); + strandRootColor = new CustomMaterialProperty( this, CCHairAlphaBackShader.strandRootColor ); + strandRootStrength = new CustomMaterialProperty( this, CCHairAlphaBackShader.strandRootStrength ); + strandEndColor = new CustomMaterialProperty( this, CCHairAlphaBackShader.strandEndColor ); + strandEndStrength = new CustomMaterialProperty( this, CCHairAlphaBackShader.strandEndStrength ); + strandGamma = new CustomMaterialProperty( this, CCHairAlphaBackShader.strandGamma ); + maximumHighlightAmount = new CustomMaterialProperty( this, CCHairAlphaBackShader.maximumHighlightAmount ); + highlightAColor = new CustomMaterialProperty( this, CCHairAlphaBackShader.highlightAColor ); + highlightAStrength = new CustomMaterialProperty( this, CCHairAlphaBackShader.highlightAStrength ); + highlightARange = new CustomMaterialProperty( this, CCHairAlphaBackShader.highlightARange ); + highlightAOverlapEnd = new CustomMaterialProperty( this, CCHairAlphaBackShader.highlightAOverlapEnd ); + highlightAInvert = new CustomMaterialProperty( this, CCHairAlphaBackShader.highlightAInvert ); + highlightAFadeOutStart = new CustomMaterialProperty( this, CCHairAlphaBackShader.highlightAFadeOutStart ); + highlightAFadeOutRange = new CustomMaterialProperty( this, CCHairAlphaBackShader.highlightAFadeOutRange ); + highlightAFadeOutPower = new CustomMaterialProperty( this, CCHairAlphaBackShader.highlightAFadeOutPower ); + highlightAFadeOutAmount = new CustomMaterialProperty( this, CCHairAlphaBackShader.highlightAFadeOutAmount ); + highlightBColor = new CustomMaterialProperty( this, CCHairAlphaBackShader.highlightBColor ); + highlightBStrength = new CustomMaterialProperty( this, CCHairAlphaBackShader.highlightBStrength ); + highlightBRange = new CustomMaterialProperty( this, CCHairAlphaBackShader.highlightBRange ); + highlightBOverlapEnd = new CustomMaterialProperty( this, CCHairAlphaBackShader.highlightBOverlapEnd ); + highlightBInvert = new CustomMaterialProperty( this, CCHairAlphaBackShader.highlightBInvert ); + highlightBFadeOutStart = new CustomMaterialProperty( this, CCHairAlphaBackShader.highlightBFadeOutStart ); + highlightBFadeOutRange = new CustomMaterialProperty( this, CCHairAlphaBackShader.highlightBFadeOutRange ); + highlightBFadeOutPower = new CustomMaterialProperty( this, CCHairAlphaBackShader.highlightBFadeOutPower ); + highlightBFadeOutAmount = new CustomMaterialProperty( this, CCHairAlphaBackShader.highlightBFadeOutAmount ); + roughness = new CustomMaterialProperty( this, CCHairAlphaBackShader.roughness ); + roughnessOffset = new CustomMaterialProperty( this, CCHairAlphaBackShader.roughnessOffset ); + textureRoughness = new CustomMaterialProperty( this, CCHairAlphaBackShader.textureRoughness ); + metallic = new CustomMaterialProperty( this, CCHairAlphaBackShader.metallic ); + metallicOffset = new CustomMaterialProperty( this, CCHairAlphaBackShader.metallicOffset ); + textureMetallic = new CustomMaterialProperty( this, CCHairAlphaBackShader.textureMetallic ); + specular = new CustomMaterialProperty( this, CCHairAlphaBackShader.specular ); + textureEmission = new CustomMaterialProperty( this, CCHairAlphaBackShader.textureEmission ); + emission = new CustomMaterialProperty( this, CCHairAlphaBackShader.emission ); + emissionEnergy = new CustomMaterialProperty( this, CCHairAlphaBackShader.emissionEnergy ); + backlight = new CustomMaterialProperty( this, CCHairAlphaBackShader.backlight ); + albedoToBacklightAmount = new CustomMaterialProperty( this, CCHairAlphaBackShader.albedoToBacklightAmount ); + textureBacklight = new CustomMaterialProperty( this, CCHairAlphaBackShader.textureBacklight ); + textureAmbientOcclusion = new CustomMaterialProperty( this, CCHairAlphaBackShader.textureAmbientOcclusion ); + aoLightAffect = new CustomMaterialProperty( this, CCHairAlphaBackShader.aoLightAffect ); + ambientOcclusion = new CustomMaterialProperty( this, CCHairAlphaBackShader.ambientOcclusion ); + aoGamma = new CustomMaterialProperty( this, CCHairAlphaBackShader.aoGamma ); + rootOcclusionAmount = new CustomMaterialProperty( this, CCHairAlphaBackShader.rootOcclusionAmount ); + rootOcclusionRange = new CustomMaterialProperty( this, CCHairAlphaBackShader.rootOcclusionRange ); + endOcclusionAmount = new CustomMaterialProperty( this, CCHairAlphaBackShader.endOcclusionAmount ); + endOcclusionRange = new CustomMaterialProperty( this, CCHairAlphaBackShader.endOcclusionRange ); + } + + } + +} \ No newline at end of file diff --git a/Runtime/Reallusion/Shaders/Hair/Variants/CCHairAlphaBackMaterial.cs.uid b/Runtime/Reallusion/Shaders/Hair/Variants/CCHairAlphaBackMaterial.cs.uid new file mode 100644 index 0000000..33725f5 --- /dev/null +++ b/Runtime/Reallusion/Shaders/Hair/Variants/CCHairAlphaBackMaterial.cs.uid @@ -0,0 +1 @@ +uid://dtwfy8fvjlm42 diff --git a/Runtime/Reallusion/Shaders/Hair/Variants/CCHairAlphaMaterial.cs b/Runtime/Reallusion/Shaders/Hair/Variants/CCHairAlphaMaterial.cs new file mode 100644 index 0000000..1874e72 --- /dev/null +++ b/Runtime/Reallusion/Shaders/Hair/Variants/CCHairAlphaMaterial.cs @@ -0,0 +1,33 @@ +using Godot; + +namespace Rokojori +{ + // Generated by ShaderClassGenerator + + public class CCHairAlphaShader + { + public static readonly CachedResource shader = new CachedResource( + "res://addons/rokojori_action_library/Runtime/Reallusion/Shaders/Hair/Variants/CCHairAlpha.gdshader" + ); + + + + } + + [Tool] + public partial class CCHairAlphaMaterial:CustomMaterial + { + + + + + public CCHairAlphaMaterial() + { + Shader = CCHairAlphaShader.shader.Get(); + + + } + + } + +} \ No newline at end of file diff --git a/Runtime/Reallusion/Shaders/Hair/Variants/CCHairAlphaMaterial.cs.uid b/Runtime/Reallusion/Shaders/Hair/Variants/CCHairAlphaMaterial.cs.uid new file mode 100644 index 0000000..fd3dded --- /dev/null +++ b/Runtime/Reallusion/Shaders/Hair/Variants/CCHairAlphaMaterial.cs.uid @@ -0,0 +1 @@ +uid://ftfnp4nst760 diff --git a/Runtime/Reallusion/Shaders/Hair/Variants/CCHairDiscard.gdshader b/Runtime/Reallusion/Shaders/Hair/Variants/CCHairDiscard.gdshader new file mode 100644 index 0000000..4590e12 --- /dev/null +++ b/Runtime/Reallusion/Shaders/Hair/Variants/CCHairDiscard.gdshader @@ -0,0 +1,5 @@ +shader_type spatial; +render_mode blend_mix, depth_draw_always, cull_disabled, diffuse_burley, specular_schlick_ggx, depth_prepass_alpha; + +#define USE_ALPHA_DISCARD +#include "res://addons/rokojori_action_library/Runtime/Reallusion/Shaders/Hair/CCHairBase.gdshaderinc" \ No newline at end of file diff --git a/Runtime/Reallusion/Shaders/Hair/Variants/CCHairDiscard.gdshader.uid b/Runtime/Reallusion/Shaders/Hair/Variants/CCHairDiscard.gdshader.uid new file mode 100644 index 0000000..9c45d36 --- /dev/null +++ b/Runtime/Reallusion/Shaders/Hair/Variants/CCHairDiscard.gdshader.uid @@ -0,0 +1 @@ +uid://bctd3i7qs8its diff --git a/Runtime/Reallusion/Shaders/Hair/Variants/CCHairDiscardMaterial.cs b/Runtime/Reallusion/Shaders/Hair/Variants/CCHairDiscardMaterial.cs new file mode 100644 index 0000000..f9d35d4 --- /dev/null +++ b/Runtime/Reallusion/Shaders/Hair/Variants/CCHairDiscardMaterial.cs @@ -0,0 +1,33 @@ +using Godot; + +namespace Rokojori +{ + // Generated by ShaderClassGenerator + + public class CCHairDiscardShader + { + public static readonly CachedResource shader = new CachedResource( + "res://addons/rokojori_action_library/Runtime/Reallusion/Shaders/CCHairDiscard.gdshader" + ); + + + + } + + [Tool] + public partial class CCHairDiscardMaterial:CustomMaterial + { + + + + + public CCHairDiscardMaterial() + { + Shader = CCHairDiscardShader.shader.Get(); + + + } + + } + +} \ No newline at end of file diff --git a/Runtime/Reallusion/Shaders/Hair/Variants/CCHairDiscardMaterial.cs.uid b/Runtime/Reallusion/Shaders/Hair/Variants/CCHairDiscardMaterial.cs.uid new file mode 100644 index 0000000..033e871 --- /dev/null +++ b/Runtime/Reallusion/Shaders/Hair/Variants/CCHairDiscardMaterial.cs.uid @@ -0,0 +1 @@ +uid://ckgqq6msf3hkp diff --git a/Runtime/Reallusion/Shaders/Hair/Variants/CCHairMaterial.cs b/Runtime/Reallusion/Shaders/Hair/Variants/CCHairMaterial.cs new file mode 100644 index 0000000..e1dd020 --- /dev/null +++ b/Runtime/Reallusion/Shaders/Hair/Variants/CCHairMaterial.cs @@ -0,0 +1,222 @@ +using Godot; + +namespace Rokojori +{ + // Generated by ShaderClassGenerator + + public class CCHairShader + { + public static readonly CachedResource shader = new CachedResource( + "res://addons/rokojori_action_library/Runtime/Reallusion/Shaders/Hair/Variants/CCHair.gdshader" + ); + + public static readonly BoolPropertyName enabled = BoolPropertyName.Create( "enabled" ); + public static readonly ColorPropertyName albedo = ColorPropertyName.Create( "albedo" ); + public static readonly Texture2DPropertyName textureAlbedo = Texture2DPropertyName.Create( "texture_albedo" ); + public static readonly Vector3PropertyName hslOffset = Vector3PropertyName.Create( "hslOffset" ); + public static readonly Texture2DPropertyName textureBlend = Texture2DPropertyName.Create( "texture_blend" ); + public static readonly FloatPropertyName blendAmount = FloatPropertyName.Create( "blendAmount" ); + public static readonly FloatPropertyName naturalColors = FloatPropertyName.Create( "naturalColors" ); + public static readonly Texture2DPropertyName textureOpacity = Texture2DPropertyName.Create( "texture_opacity" ); + public static readonly FloatPropertyName opacity = FloatPropertyName.Create( "opacity" ); + public static readonly FloatPropertyName opacityGamma = FloatPropertyName.Create( "opacityGamma" ); + public static readonly FloatPropertyName alphaDiscardTreshold = FloatPropertyName.Create( "alphaDiscardTreshold" ); + public static readonly Texture2DPropertyName rootMap = Texture2DPropertyName.Create( "rootMap" ); + public static readonly Texture2DPropertyName flowMap = Texture2DPropertyName.Create( "flowMap" ); + public static readonly Texture2DPropertyName idMap = Texture2DPropertyName.Create( "idMap" ); + public static readonly FloatPropertyName diffuseStrength = FloatPropertyName.Create( "diffuseStrength" ); + public static readonly FloatPropertyName vertexColorStrength = FloatPropertyName.Create( "vertexColorStrength" ); + public static readonly ColorPropertyName vertexGreyToColor = ColorPropertyName.Create( "vertexGreyToColor" ); + public static readonly BoolPropertyName activateHairColor = BoolPropertyName.Create( "activateHairColor" ); + public static readonly FloatPropertyName baseColorMapStrength = FloatPropertyName.Create( "baseColorMapStrength" ); + public static readonly ColorPropertyName strandRootColor = ColorPropertyName.Create( "strandRootColor" ); + public static readonly FloatPropertyName strandRootStrength = FloatPropertyName.Create( "strandRootStrength" ); + public static readonly ColorPropertyName strandEndColor = ColorPropertyName.Create( "strandEndColor" ); + public static readonly FloatPropertyName strandEndStrength = FloatPropertyName.Create( "strandEndStrength" ); + public static readonly FloatPropertyName strandGamma = FloatPropertyName.Create( "strandGamma" ); + public static readonly FloatPropertyName maximumHighlightAmount = FloatPropertyName.Create( "maximumHighlightAmount" ); + public static readonly ColorPropertyName highlightAColor = ColorPropertyName.Create( "highlightAColor" ); + public static readonly FloatPropertyName highlightAStrength = FloatPropertyName.Create( "highlightAStrength" ); + public static readonly Vector3PropertyName highlightARange = Vector3PropertyName.Create( "highlightARange" ); + public static readonly FloatPropertyName highlightAOverlapEnd = FloatPropertyName.Create( "highlightAOverlapEnd" ); + public static readonly FloatPropertyName highlightAInvert = FloatPropertyName.Create( "highlightAInvert" ); + public static readonly FloatPropertyName highlightAFadeOutStart = FloatPropertyName.Create( "highlightAFadeOutStart" ); + public static readonly FloatPropertyName highlightAFadeOutRange = FloatPropertyName.Create( "highlightAFadeOutRange" ); + public static readonly FloatPropertyName highlightAFadeOutPower = FloatPropertyName.Create( "highlightAFadeOutPower" ); + public static readonly FloatPropertyName highlightAFadeOutAmount = FloatPropertyName.Create( "highlightAFadeOutAmount" ); + public static readonly ColorPropertyName highlightBColor = ColorPropertyName.Create( "highlightBColor" ); + public static readonly FloatPropertyName highlightBStrength = FloatPropertyName.Create( "highlightBStrength" ); + public static readonly Vector3PropertyName highlightBRange = Vector3PropertyName.Create( "highlightBRange" ); + public static readonly FloatPropertyName highlightBOverlapEnd = FloatPropertyName.Create( "highlightBOverlapEnd" ); + public static readonly FloatPropertyName highlightBInvert = FloatPropertyName.Create( "highlightBInvert" ); + public static readonly FloatPropertyName highlightBFadeOutStart = FloatPropertyName.Create( "highlightBFadeOutStart" ); + public static readonly FloatPropertyName highlightBFadeOutRange = FloatPropertyName.Create( "highlightBFadeOutRange" ); + public static readonly FloatPropertyName highlightBFadeOutPower = FloatPropertyName.Create( "highlightBFadeOutPower" ); + public static readonly FloatPropertyName highlightBFadeOutAmount = FloatPropertyName.Create( "highlightBFadeOutAmount" ); + public static readonly FloatPropertyName roughness = FloatPropertyName.Create( "roughness" ); + public static readonly FloatPropertyName roughnessOffset = FloatPropertyName.Create( "roughnessOffset" ); + public static readonly Texture2DPropertyName textureRoughness = Texture2DPropertyName.Create( "texture_roughness" ); + public static readonly FloatPropertyName metallic = FloatPropertyName.Create( "metallic" ); + public static readonly FloatPropertyName metallicOffset = FloatPropertyName.Create( "metallicOffset" ); + public static readonly Texture2DPropertyName textureMetallic = Texture2DPropertyName.Create( "texture_metallic" ); + public static readonly FloatPropertyName specular = FloatPropertyName.Create( "specular" ); + public static readonly Texture2DPropertyName textureEmission = Texture2DPropertyName.Create( "texture_emission" ); + public static readonly ColorPropertyName emission = ColorPropertyName.Create( "emission" ); + public static readonly FloatPropertyName emissionEnergy = FloatPropertyName.Create( "emission_energy" ); + public static readonly ColorPropertyName backlight = ColorPropertyName.Create( "backlight" ); + public static readonly FloatPropertyName albedoToBacklightAmount = FloatPropertyName.Create( "albedoToBacklightAmount" ); + public static readonly Texture2DPropertyName textureBacklight = Texture2DPropertyName.Create( "texture_backlight" ); + public static readonly Texture2DPropertyName textureAmbientOcclusion = Texture2DPropertyName.Create( "texture_ambient_occlusion" ); + public static readonly FloatPropertyName aoLightAffect = FloatPropertyName.Create( "ao_light_affect" ); + public static readonly FloatPropertyName ambientOcclusion = FloatPropertyName.Create( "ambientOcclusion" ); + public static readonly FloatPropertyName aoGamma = FloatPropertyName.Create( "aoGamma" ); + public static readonly FloatPropertyName rootOcclusionAmount = FloatPropertyName.Create( "rootOcclusionAmount" ); + public static readonly FloatPropertyName rootOcclusionRange = FloatPropertyName.Create( "rootOcclusionRange" ); + public static readonly FloatPropertyName endOcclusionAmount = FloatPropertyName.Create( "endOcclusionAmount" ); + public static readonly FloatPropertyName endOcclusionRange = FloatPropertyName.Create( "endOcclusionRange" ); + + } + + [Tool] + public partial class CCHairMaterial:CustomMaterial + { + + + public readonly CustomMaterialProperty enabled; + public readonly CustomMaterialProperty albedo; + public readonly CustomMaterialProperty textureAlbedo; + public readonly CustomMaterialProperty hslOffset; + public readonly CustomMaterialProperty textureBlend; + public readonly CustomMaterialProperty blendAmount; + public readonly CustomMaterialProperty naturalColors; + public readonly CustomMaterialProperty textureOpacity; + public readonly CustomMaterialProperty opacity; + public readonly CustomMaterialProperty opacityGamma; + public readonly CustomMaterialProperty alphaDiscardTreshold; + public readonly CustomMaterialProperty rootMap; + public readonly CustomMaterialProperty flowMap; + public readonly CustomMaterialProperty idMap; + public readonly CustomMaterialProperty diffuseStrength; + public readonly CustomMaterialProperty vertexColorStrength; + public readonly CustomMaterialProperty vertexGreyToColor; + public readonly CustomMaterialProperty activateHairColor; + public readonly CustomMaterialProperty baseColorMapStrength; + public readonly CustomMaterialProperty strandRootColor; + public readonly CustomMaterialProperty strandRootStrength; + public readonly CustomMaterialProperty strandEndColor; + public readonly CustomMaterialProperty strandEndStrength; + public readonly CustomMaterialProperty strandGamma; + public readonly CustomMaterialProperty maximumHighlightAmount; + public readonly CustomMaterialProperty highlightAColor; + public readonly CustomMaterialProperty highlightAStrength; + public readonly CustomMaterialProperty highlightARange; + public readonly CustomMaterialProperty highlightAOverlapEnd; + public readonly CustomMaterialProperty highlightAInvert; + public readonly CustomMaterialProperty highlightAFadeOutStart; + public readonly CustomMaterialProperty highlightAFadeOutRange; + public readonly CustomMaterialProperty highlightAFadeOutPower; + public readonly CustomMaterialProperty highlightAFadeOutAmount; + public readonly CustomMaterialProperty highlightBColor; + public readonly CustomMaterialProperty highlightBStrength; + public readonly CustomMaterialProperty highlightBRange; + public readonly CustomMaterialProperty highlightBOverlapEnd; + public readonly CustomMaterialProperty highlightBInvert; + public readonly CustomMaterialProperty highlightBFadeOutStart; + public readonly CustomMaterialProperty highlightBFadeOutRange; + public readonly CustomMaterialProperty highlightBFadeOutPower; + public readonly CustomMaterialProperty highlightBFadeOutAmount; + public readonly CustomMaterialProperty roughness; + public readonly CustomMaterialProperty roughnessOffset; + public readonly CustomMaterialProperty textureRoughness; + public readonly CustomMaterialProperty metallic; + public readonly CustomMaterialProperty metallicOffset; + public readonly CustomMaterialProperty textureMetallic; + public readonly CustomMaterialProperty specular; + public readonly CustomMaterialProperty textureEmission; + public readonly CustomMaterialProperty emission; + public readonly CustomMaterialProperty emissionEnergy; + public readonly CustomMaterialProperty backlight; + public readonly CustomMaterialProperty albedoToBacklightAmount; + public readonly CustomMaterialProperty textureBacklight; + public readonly CustomMaterialProperty textureAmbientOcclusion; + public readonly CustomMaterialProperty aoLightAffect; + public readonly CustomMaterialProperty ambientOcclusion; + public readonly CustomMaterialProperty aoGamma; + public readonly CustomMaterialProperty rootOcclusionAmount; + public readonly CustomMaterialProperty rootOcclusionRange; + public readonly CustomMaterialProperty endOcclusionAmount; + public readonly CustomMaterialProperty endOcclusionRange; + + public CCHairMaterial() + { + Shader = CCHairShader.shader.Get(); + + enabled = new CustomMaterialProperty( this, CCHairShader.enabled ); + albedo = new CustomMaterialProperty( this, CCHairShader.albedo ); + textureAlbedo = new CustomMaterialProperty( this, CCHairShader.textureAlbedo ); + hslOffset = new CustomMaterialProperty( this, CCHairShader.hslOffset ); + textureBlend = new CustomMaterialProperty( this, CCHairShader.textureBlend ); + blendAmount = new CustomMaterialProperty( this, CCHairShader.blendAmount ); + naturalColors = new CustomMaterialProperty( this, CCHairShader.naturalColors ); + textureOpacity = new CustomMaterialProperty( this, CCHairShader.textureOpacity ); + opacity = new CustomMaterialProperty( this, CCHairShader.opacity ); + opacityGamma = new CustomMaterialProperty( this, CCHairShader.opacityGamma ); + alphaDiscardTreshold = new CustomMaterialProperty( this, CCHairShader.alphaDiscardTreshold ); + rootMap = new CustomMaterialProperty( this, CCHairShader.rootMap ); + flowMap = new CustomMaterialProperty( this, CCHairShader.flowMap ); + idMap = new CustomMaterialProperty( this, CCHairShader.idMap ); + diffuseStrength = new CustomMaterialProperty( this, CCHairShader.diffuseStrength ); + vertexColorStrength = new CustomMaterialProperty( this, CCHairShader.vertexColorStrength ); + vertexGreyToColor = new CustomMaterialProperty( this, CCHairShader.vertexGreyToColor ); + activateHairColor = new CustomMaterialProperty( this, CCHairShader.activateHairColor ); + baseColorMapStrength = new CustomMaterialProperty( this, CCHairShader.baseColorMapStrength ); + strandRootColor = new CustomMaterialProperty( this, CCHairShader.strandRootColor ); + strandRootStrength = new CustomMaterialProperty( this, CCHairShader.strandRootStrength ); + strandEndColor = new CustomMaterialProperty( this, CCHairShader.strandEndColor ); + strandEndStrength = new CustomMaterialProperty( this, CCHairShader.strandEndStrength ); + strandGamma = new CustomMaterialProperty( this, CCHairShader.strandGamma ); + maximumHighlightAmount = new CustomMaterialProperty( this, CCHairShader.maximumHighlightAmount ); + highlightAColor = new CustomMaterialProperty( this, CCHairShader.highlightAColor ); + highlightAStrength = new CustomMaterialProperty( this, CCHairShader.highlightAStrength ); + highlightARange = new CustomMaterialProperty( this, CCHairShader.highlightARange ); + highlightAOverlapEnd = new CustomMaterialProperty( this, CCHairShader.highlightAOverlapEnd ); + highlightAInvert = new CustomMaterialProperty( this, CCHairShader.highlightAInvert ); + highlightAFadeOutStart = new CustomMaterialProperty( this, CCHairShader.highlightAFadeOutStart ); + highlightAFadeOutRange = new CustomMaterialProperty( this, CCHairShader.highlightAFadeOutRange ); + highlightAFadeOutPower = new CustomMaterialProperty( this, CCHairShader.highlightAFadeOutPower ); + highlightAFadeOutAmount = new CustomMaterialProperty( this, CCHairShader.highlightAFadeOutAmount ); + highlightBColor = new CustomMaterialProperty( this, CCHairShader.highlightBColor ); + highlightBStrength = new CustomMaterialProperty( this, CCHairShader.highlightBStrength ); + highlightBRange = new CustomMaterialProperty( this, CCHairShader.highlightBRange ); + highlightBOverlapEnd = new CustomMaterialProperty( this, CCHairShader.highlightBOverlapEnd ); + highlightBInvert = new CustomMaterialProperty( this, CCHairShader.highlightBInvert ); + highlightBFadeOutStart = new CustomMaterialProperty( this, CCHairShader.highlightBFadeOutStart ); + highlightBFadeOutRange = new CustomMaterialProperty( this, CCHairShader.highlightBFadeOutRange ); + highlightBFadeOutPower = new CustomMaterialProperty( this, CCHairShader.highlightBFadeOutPower ); + highlightBFadeOutAmount = new CustomMaterialProperty( this, CCHairShader.highlightBFadeOutAmount ); + roughness = new CustomMaterialProperty( this, CCHairShader.roughness ); + roughnessOffset = new CustomMaterialProperty( this, CCHairShader.roughnessOffset ); + textureRoughness = new CustomMaterialProperty( this, CCHairShader.textureRoughness ); + metallic = new CustomMaterialProperty( this, CCHairShader.metallic ); + metallicOffset = new CustomMaterialProperty( this, CCHairShader.metallicOffset ); + textureMetallic = new CustomMaterialProperty( this, CCHairShader.textureMetallic ); + specular = new CustomMaterialProperty( this, CCHairShader.specular ); + textureEmission = new CustomMaterialProperty( this, CCHairShader.textureEmission ); + emission = new CustomMaterialProperty( this, CCHairShader.emission ); + emissionEnergy = new CustomMaterialProperty( this, CCHairShader.emissionEnergy ); + backlight = new CustomMaterialProperty( this, CCHairShader.backlight ); + albedoToBacklightAmount = new CustomMaterialProperty( this, CCHairShader.albedoToBacklightAmount ); + textureBacklight = new CustomMaterialProperty( this, CCHairShader.textureBacklight ); + textureAmbientOcclusion = new CustomMaterialProperty( this, CCHairShader.textureAmbientOcclusion ); + aoLightAffect = new CustomMaterialProperty( this, CCHairShader.aoLightAffect ); + ambientOcclusion = new CustomMaterialProperty( this, CCHairShader.ambientOcclusion ); + aoGamma = new CustomMaterialProperty( this, CCHairShader.aoGamma ); + rootOcclusionAmount = new CustomMaterialProperty( this, CCHairShader.rootOcclusionAmount ); + rootOcclusionRange = new CustomMaterialProperty( this, CCHairShader.rootOcclusionRange ); + endOcclusionAmount = new CustomMaterialProperty( this, CCHairShader.endOcclusionAmount ); + endOcclusionRange = new CustomMaterialProperty( this, CCHairShader.endOcclusionRange ); + } + + } + +} \ No newline at end of file diff --git a/Runtime/Reallusion/Shaders/Hair/Variants/CCHairMaterial.cs.uid b/Runtime/Reallusion/Shaders/Hair/Variants/CCHairMaterial.cs.uid new file mode 100644 index 0000000..6abca03 --- /dev/null +++ b/Runtime/Reallusion/Shaders/Hair/Variants/CCHairMaterial.cs.uid @@ -0,0 +1 @@ +uid://cobsamwc8yhsi diff --git a/Runtime/Reallusion/Shaders/Hair/Variants/CCHairScissor.gdshader b/Runtime/Reallusion/Shaders/Hair/Variants/CCHairScissor.gdshader new file mode 100644 index 0000000..f823bc6 --- /dev/null +++ b/Runtime/Reallusion/Shaders/Hair/Variants/CCHairScissor.gdshader @@ -0,0 +1,6 @@ +shader_type spatial; +render_mode blend_mix, depth_draw_opaque, cull_disabled, diffuse_burley, specular_schlick_ggx; + +#define USE_ALPHA_SCISSOR + +#include "res://addons/rokojori_action_library/Runtime/Reallusion/Shaders/Hair/CCHairBase.gdshaderinc" \ No newline at end of file diff --git a/Runtime/Reallusion/Shaders/Hair/Variants/CCHairScissor.gdshader.uid b/Runtime/Reallusion/Shaders/Hair/Variants/CCHairScissor.gdshader.uid new file mode 100644 index 0000000..eb6b58a --- /dev/null +++ b/Runtime/Reallusion/Shaders/Hair/Variants/CCHairScissor.gdshader.uid @@ -0,0 +1 @@ +uid://dnleugjbck7tv diff --git a/Runtime/Reallusion/Shaders/Hair/Variants/CCHairScissorMaterial.cs b/Runtime/Reallusion/Shaders/Hair/Variants/CCHairScissorMaterial.cs new file mode 100644 index 0000000..0f65988 --- /dev/null +++ b/Runtime/Reallusion/Shaders/Hair/Variants/CCHairScissorMaterial.cs @@ -0,0 +1,222 @@ +using Godot; + +namespace Rokojori +{ + // Generated by ShaderClassGenerator + + public class CCHairScissorShader + { + public static readonly CachedResource shader = new CachedResource( + "res://addons/rokojori_action_library/Runtime/Reallusion/Shaders/Hair/Variants/CCHairScissor.gdshader" + ); + + public static readonly BoolPropertyName enabled = BoolPropertyName.Create( "enabled" ); + public static readonly ColorPropertyName albedo = ColorPropertyName.Create( "albedo" ); + public static readonly Texture2DPropertyName textureAlbedo = Texture2DPropertyName.Create( "texture_albedo" ); + public static readonly Vector3PropertyName hslOffset = Vector3PropertyName.Create( "hslOffset" ); + public static readonly Texture2DPropertyName textureBlend = Texture2DPropertyName.Create( "texture_blend" ); + public static readonly FloatPropertyName blendAmount = FloatPropertyName.Create( "blendAmount" ); + public static readonly FloatPropertyName naturalColors = FloatPropertyName.Create( "naturalColors" ); + public static readonly Texture2DPropertyName textureOpacity = Texture2DPropertyName.Create( "texture_opacity" ); + public static readonly FloatPropertyName opacity = FloatPropertyName.Create( "opacity" ); + public static readonly FloatPropertyName opacityGamma = FloatPropertyName.Create( "opacityGamma" ); + public static readonly FloatPropertyName alphaScissorTreshold = FloatPropertyName.Create( "alphaScissorTreshold" ); + public static readonly Texture2DPropertyName rootMap = Texture2DPropertyName.Create( "rootMap" ); + public static readonly Texture2DPropertyName flowMap = Texture2DPropertyName.Create( "flowMap" ); + public static readonly Texture2DPropertyName idMap = Texture2DPropertyName.Create( "idMap" ); + public static readonly FloatPropertyName diffuseStrength = FloatPropertyName.Create( "diffuseStrength" ); + public static readonly FloatPropertyName vertexColorStrength = FloatPropertyName.Create( "vertexColorStrength" ); + public static readonly ColorPropertyName vertexGreyToColor = ColorPropertyName.Create( "vertexGreyToColor" ); + public static readonly BoolPropertyName activateHairColor = BoolPropertyName.Create( "activateHairColor" ); + public static readonly FloatPropertyName baseColorMapStrength = FloatPropertyName.Create( "baseColorMapStrength" ); + public static readonly ColorPropertyName strandRootColor = ColorPropertyName.Create( "strandRootColor" ); + public static readonly FloatPropertyName strandRootStrength = FloatPropertyName.Create( "strandRootStrength" ); + public static readonly ColorPropertyName strandEndColor = ColorPropertyName.Create( "strandEndColor" ); + public static readonly FloatPropertyName strandEndStrength = FloatPropertyName.Create( "strandEndStrength" ); + public static readonly FloatPropertyName strandGamma = FloatPropertyName.Create( "strandGamma" ); + public static readonly FloatPropertyName maximumHighlightAmount = FloatPropertyName.Create( "maximumHighlightAmount" ); + public static readonly ColorPropertyName highlightAColor = ColorPropertyName.Create( "highlightAColor" ); + public static readonly FloatPropertyName highlightAStrength = FloatPropertyName.Create( "highlightAStrength" ); + public static readonly Vector3PropertyName highlightARange = Vector3PropertyName.Create( "highlightARange" ); + public static readonly FloatPropertyName highlightAOverlapEnd = FloatPropertyName.Create( "highlightAOverlapEnd" ); + public static readonly FloatPropertyName highlightAInvert = FloatPropertyName.Create( "highlightAInvert" ); + public static readonly FloatPropertyName highlightAFadeOutStart = FloatPropertyName.Create( "highlightAFadeOutStart" ); + public static readonly FloatPropertyName highlightAFadeOutRange = FloatPropertyName.Create( "highlightAFadeOutRange" ); + public static readonly FloatPropertyName highlightAFadeOutPower = FloatPropertyName.Create( "highlightAFadeOutPower" ); + public static readonly FloatPropertyName highlightAFadeOutAmount = FloatPropertyName.Create( "highlightAFadeOutAmount" ); + public static readonly ColorPropertyName highlightBColor = ColorPropertyName.Create( "highlightBColor" ); + public static readonly FloatPropertyName highlightBStrength = FloatPropertyName.Create( "highlightBStrength" ); + public static readonly Vector3PropertyName highlightBRange = Vector3PropertyName.Create( "highlightBRange" ); + public static readonly FloatPropertyName highlightBOverlapEnd = FloatPropertyName.Create( "highlightBOverlapEnd" ); + public static readonly FloatPropertyName highlightBInvert = FloatPropertyName.Create( "highlightBInvert" ); + public static readonly FloatPropertyName highlightBFadeOutStart = FloatPropertyName.Create( "highlightBFadeOutStart" ); + public static readonly FloatPropertyName highlightBFadeOutRange = FloatPropertyName.Create( "highlightBFadeOutRange" ); + public static readonly FloatPropertyName highlightBFadeOutPower = FloatPropertyName.Create( "highlightBFadeOutPower" ); + public static readonly FloatPropertyName highlightBFadeOutAmount = FloatPropertyName.Create( "highlightBFadeOutAmount" ); + public static readonly FloatPropertyName roughness = FloatPropertyName.Create( "roughness" ); + public static readonly FloatPropertyName roughnessOffset = FloatPropertyName.Create( "roughnessOffset" ); + public static readonly Texture2DPropertyName textureRoughness = Texture2DPropertyName.Create( "texture_roughness" ); + public static readonly FloatPropertyName metallic = FloatPropertyName.Create( "metallic" ); + public static readonly FloatPropertyName metallicOffset = FloatPropertyName.Create( "metallicOffset" ); + public static readonly Texture2DPropertyName textureMetallic = Texture2DPropertyName.Create( "texture_metallic" ); + public static readonly FloatPropertyName specular = FloatPropertyName.Create( "specular" ); + public static readonly Texture2DPropertyName textureEmission = Texture2DPropertyName.Create( "texture_emission" ); + public static readonly ColorPropertyName emission = ColorPropertyName.Create( "emission" ); + public static readonly FloatPropertyName emissionEnergy = FloatPropertyName.Create( "emission_energy" ); + public static readonly ColorPropertyName backlight = ColorPropertyName.Create( "backlight" ); + public static readonly FloatPropertyName albedoToBacklightAmount = FloatPropertyName.Create( "albedoToBacklightAmount" ); + public static readonly Texture2DPropertyName textureBacklight = Texture2DPropertyName.Create( "texture_backlight" ); + public static readonly Texture2DPropertyName textureAmbientOcclusion = Texture2DPropertyName.Create( "texture_ambient_occlusion" ); + public static readonly FloatPropertyName aoLightAffect = FloatPropertyName.Create( "ao_light_affect" ); + public static readonly FloatPropertyName ambientOcclusion = FloatPropertyName.Create( "ambientOcclusion" ); + public static readonly FloatPropertyName aoGamma = FloatPropertyName.Create( "aoGamma" ); + public static readonly FloatPropertyName rootOcclusionAmount = FloatPropertyName.Create( "rootOcclusionAmount" ); + public static readonly FloatPropertyName rootOcclusionRange = FloatPropertyName.Create( "rootOcclusionRange" ); + public static readonly FloatPropertyName endOcclusionAmount = FloatPropertyName.Create( "endOcclusionAmount" ); + public static readonly FloatPropertyName endOcclusionRange = FloatPropertyName.Create( "endOcclusionRange" ); + + } + + [Tool] + public partial class CCHairScissorMaterial:CustomMaterial + { + + + public readonly CustomMaterialProperty enabled; + public readonly CustomMaterialProperty albedo; + public readonly CustomMaterialProperty textureAlbedo; + public readonly CustomMaterialProperty hslOffset; + public readonly CustomMaterialProperty textureBlend; + public readonly CustomMaterialProperty blendAmount; + public readonly CustomMaterialProperty naturalColors; + public readonly CustomMaterialProperty textureOpacity; + public readonly CustomMaterialProperty opacity; + public readonly CustomMaterialProperty opacityGamma; + public readonly CustomMaterialProperty alphaScissorTreshold; + public readonly CustomMaterialProperty rootMap; + public readonly CustomMaterialProperty flowMap; + public readonly CustomMaterialProperty idMap; + public readonly CustomMaterialProperty diffuseStrength; + public readonly CustomMaterialProperty vertexColorStrength; + public readonly CustomMaterialProperty vertexGreyToColor; + public readonly CustomMaterialProperty activateHairColor; + public readonly CustomMaterialProperty baseColorMapStrength; + public readonly CustomMaterialProperty strandRootColor; + public readonly CustomMaterialProperty strandRootStrength; + public readonly CustomMaterialProperty strandEndColor; + public readonly CustomMaterialProperty strandEndStrength; + public readonly CustomMaterialProperty strandGamma; + public readonly CustomMaterialProperty maximumHighlightAmount; + public readonly CustomMaterialProperty highlightAColor; + public readonly CustomMaterialProperty highlightAStrength; + public readonly CustomMaterialProperty highlightARange; + public readonly CustomMaterialProperty highlightAOverlapEnd; + public readonly CustomMaterialProperty highlightAInvert; + public readonly CustomMaterialProperty highlightAFadeOutStart; + public readonly CustomMaterialProperty highlightAFadeOutRange; + public readonly CustomMaterialProperty highlightAFadeOutPower; + public readonly CustomMaterialProperty highlightAFadeOutAmount; + public readonly CustomMaterialProperty highlightBColor; + public readonly CustomMaterialProperty highlightBStrength; + public readonly CustomMaterialProperty highlightBRange; + public readonly CustomMaterialProperty highlightBOverlapEnd; + public readonly CustomMaterialProperty highlightBInvert; + public readonly CustomMaterialProperty highlightBFadeOutStart; + public readonly CustomMaterialProperty highlightBFadeOutRange; + public readonly CustomMaterialProperty highlightBFadeOutPower; + public readonly CustomMaterialProperty highlightBFadeOutAmount; + public readonly CustomMaterialProperty roughness; + public readonly CustomMaterialProperty roughnessOffset; + public readonly CustomMaterialProperty textureRoughness; + public readonly CustomMaterialProperty metallic; + public readonly CustomMaterialProperty metallicOffset; + public readonly CustomMaterialProperty textureMetallic; + public readonly CustomMaterialProperty specular; + public readonly CustomMaterialProperty textureEmission; + public readonly CustomMaterialProperty emission; + public readonly CustomMaterialProperty emissionEnergy; + public readonly CustomMaterialProperty backlight; + public readonly CustomMaterialProperty albedoToBacklightAmount; + public readonly CustomMaterialProperty textureBacklight; + public readonly CustomMaterialProperty textureAmbientOcclusion; + public readonly CustomMaterialProperty aoLightAffect; + public readonly CustomMaterialProperty ambientOcclusion; + public readonly CustomMaterialProperty aoGamma; + public readonly CustomMaterialProperty rootOcclusionAmount; + public readonly CustomMaterialProperty rootOcclusionRange; + public readonly CustomMaterialProperty endOcclusionAmount; + public readonly CustomMaterialProperty endOcclusionRange; + + public CCHairScissorMaterial() + { + Shader = CCHairScissorShader.shader.Get(); + + enabled = new CustomMaterialProperty( this, CCHairScissorShader.enabled ); + albedo = new CustomMaterialProperty( this, CCHairScissorShader.albedo ); + textureAlbedo = new CustomMaterialProperty( this, CCHairScissorShader.textureAlbedo ); + hslOffset = new CustomMaterialProperty( this, CCHairScissorShader.hslOffset ); + textureBlend = new CustomMaterialProperty( this, CCHairScissorShader.textureBlend ); + blendAmount = new CustomMaterialProperty( this, CCHairScissorShader.blendAmount ); + naturalColors = new CustomMaterialProperty( this, CCHairScissorShader.naturalColors ); + textureOpacity = new CustomMaterialProperty( this, CCHairScissorShader.textureOpacity ); + opacity = new CustomMaterialProperty( this, CCHairScissorShader.opacity ); + opacityGamma = new CustomMaterialProperty( this, CCHairScissorShader.opacityGamma ); + alphaScissorTreshold = new CustomMaterialProperty( this, CCHairScissorShader.alphaScissorTreshold ); + rootMap = new CustomMaterialProperty( this, CCHairScissorShader.rootMap ); + flowMap = new CustomMaterialProperty( this, CCHairScissorShader.flowMap ); + idMap = new CustomMaterialProperty( this, CCHairScissorShader.idMap ); + diffuseStrength = new CustomMaterialProperty( this, CCHairScissorShader.diffuseStrength ); + vertexColorStrength = new CustomMaterialProperty( this, CCHairScissorShader.vertexColorStrength ); + vertexGreyToColor = new CustomMaterialProperty( this, CCHairScissorShader.vertexGreyToColor ); + activateHairColor = new CustomMaterialProperty( this, CCHairScissorShader.activateHairColor ); + baseColorMapStrength = new CustomMaterialProperty( this, CCHairScissorShader.baseColorMapStrength ); + strandRootColor = new CustomMaterialProperty( this, CCHairScissorShader.strandRootColor ); + strandRootStrength = new CustomMaterialProperty( this, CCHairScissorShader.strandRootStrength ); + strandEndColor = new CustomMaterialProperty( this, CCHairScissorShader.strandEndColor ); + strandEndStrength = new CustomMaterialProperty( this, CCHairScissorShader.strandEndStrength ); + strandGamma = new CustomMaterialProperty( this, CCHairScissorShader.strandGamma ); + maximumHighlightAmount = new CustomMaterialProperty( this, CCHairScissorShader.maximumHighlightAmount ); + highlightAColor = new CustomMaterialProperty( this, CCHairScissorShader.highlightAColor ); + highlightAStrength = new CustomMaterialProperty( this, CCHairScissorShader.highlightAStrength ); + highlightARange = new CustomMaterialProperty( this, CCHairScissorShader.highlightARange ); + highlightAOverlapEnd = new CustomMaterialProperty( this, CCHairScissorShader.highlightAOverlapEnd ); + highlightAInvert = new CustomMaterialProperty( this, CCHairScissorShader.highlightAInvert ); + highlightAFadeOutStart = new CustomMaterialProperty( this, CCHairScissorShader.highlightAFadeOutStart ); + highlightAFadeOutRange = new CustomMaterialProperty( this, CCHairScissorShader.highlightAFadeOutRange ); + highlightAFadeOutPower = new CustomMaterialProperty( this, CCHairScissorShader.highlightAFadeOutPower ); + highlightAFadeOutAmount = new CustomMaterialProperty( this, CCHairScissorShader.highlightAFadeOutAmount ); + highlightBColor = new CustomMaterialProperty( this, CCHairScissorShader.highlightBColor ); + highlightBStrength = new CustomMaterialProperty( this, CCHairScissorShader.highlightBStrength ); + highlightBRange = new CustomMaterialProperty( this, CCHairScissorShader.highlightBRange ); + highlightBOverlapEnd = new CustomMaterialProperty( this, CCHairScissorShader.highlightBOverlapEnd ); + highlightBInvert = new CustomMaterialProperty( this, CCHairScissorShader.highlightBInvert ); + highlightBFadeOutStart = new CustomMaterialProperty( this, CCHairScissorShader.highlightBFadeOutStart ); + highlightBFadeOutRange = new CustomMaterialProperty( this, CCHairScissorShader.highlightBFadeOutRange ); + highlightBFadeOutPower = new CustomMaterialProperty( this, CCHairScissorShader.highlightBFadeOutPower ); + highlightBFadeOutAmount = new CustomMaterialProperty( this, CCHairScissorShader.highlightBFadeOutAmount ); + roughness = new CustomMaterialProperty( this, CCHairScissorShader.roughness ); + roughnessOffset = new CustomMaterialProperty( this, CCHairScissorShader.roughnessOffset ); + textureRoughness = new CustomMaterialProperty( this, CCHairScissorShader.textureRoughness ); + metallic = new CustomMaterialProperty( this, CCHairScissorShader.metallic ); + metallicOffset = new CustomMaterialProperty( this, CCHairScissorShader.metallicOffset ); + textureMetallic = new CustomMaterialProperty( this, CCHairScissorShader.textureMetallic ); + specular = new CustomMaterialProperty( this, CCHairScissorShader.specular ); + textureEmission = new CustomMaterialProperty( this, CCHairScissorShader.textureEmission ); + emission = new CustomMaterialProperty( this, CCHairScissorShader.emission ); + emissionEnergy = new CustomMaterialProperty( this, CCHairScissorShader.emissionEnergy ); + backlight = new CustomMaterialProperty( this, CCHairScissorShader.backlight ); + albedoToBacklightAmount = new CustomMaterialProperty( this, CCHairScissorShader.albedoToBacklightAmount ); + textureBacklight = new CustomMaterialProperty( this, CCHairScissorShader.textureBacklight ); + textureAmbientOcclusion = new CustomMaterialProperty( this, CCHairScissorShader.textureAmbientOcclusion ); + aoLightAffect = new CustomMaterialProperty( this, CCHairScissorShader.aoLightAffect ); + ambientOcclusion = new CustomMaterialProperty( this, CCHairScissorShader.ambientOcclusion ); + aoGamma = new CustomMaterialProperty( this, CCHairScissorShader.aoGamma ); + rootOcclusionAmount = new CustomMaterialProperty( this, CCHairScissorShader.rootOcclusionAmount ); + rootOcclusionRange = new CustomMaterialProperty( this, CCHairScissorShader.rootOcclusionRange ); + endOcclusionAmount = new CustomMaterialProperty( this, CCHairScissorShader.endOcclusionAmount ); + endOcclusionRange = new CustomMaterialProperty( this, CCHairScissorShader.endOcclusionRange ); + } + + } + +} \ No newline at end of file diff --git a/Runtime/Reallusion/Shaders/Hair/Variants/CCHairScissorMaterial.cs.uid b/Runtime/Reallusion/Shaders/Hair/Variants/CCHairScissorMaterial.cs.uid new file mode 100644 index 0000000..eed5af5 --- /dev/null +++ b/Runtime/Reallusion/Shaders/Hair/Variants/CCHairScissorMaterial.cs.uid @@ -0,0 +1 @@ +uid://b6vf0p7b77yx1 diff --git a/Runtime/Reallusion/Shaders/Hair/Variants/CCHairShadow.gdshader b/Runtime/Reallusion/Shaders/Hair/Variants/CCHairShadow.gdshader new file mode 100644 index 0000000..455981c --- /dev/null +++ b/Runtime/Reallusion/Shaders/Hair/Variants/CCHairShadow.gdshader @@ -0,0 +1,6 @@ +shader_type spatial; +render_mode blend_mix, depth_draw_never, cull_back, unshaded; + +#define USE_SHADOW + +#include "res://addons/rokojori_action_library/Runtime/Reallusion/Shaders/Hair/CCHairBase.gdshaderinc" \ No newline at end of file diff --git a/Runtime/Reallusion/Shaders/Hair/Variants/CCHairShadow.gdshader.uid b/Runtime/Reallusion/Shaders/Hair/Variants/CCHairShadow.gdshader.uid new file mode 100644 index 0000000..a7cfbaf --- /dev/null +++ b/Runtime/Reallusion/Shaders/Hair/Variants/CCHairShadow.gdshader.uid @@ -0,0 +1 @@ +uid://3l0lbjbuso7p diff --git a/Runtime/Reallusion/Shaders/Hair/Variants/CCHairShadowMaterial.cs b/Runtime/Reallusion/Shaders/Hair/Variants/CCHairShadowMaterial.cs new file mode 100644 index 0000000..4e881e3 --- /dev/null +++ b/Runtime/Reallusion/Shaders/Hair/Variants/CCHairShadowMaterial.cs @@ -0,0 +1,33 @@ +using Godot; + +namespace Rokojori +{ + // Generated by ShaderClassGenerator + + public class CCHairShadowShader + { + public static readonly CachedResource shader = new CachedResource( + "res://addons/rokojori_action_library/Runtime/Reallusion/Shaders/CCHairShadow.gdshader" + ); + + + + } + + [Tool] + public partial class CCHairShadowMaterial:CustomMaterial + { + + + + + public CCHairShadowMaterial() + { + Shader = CCHairShadowShader.shader.Get(); + + + } + + } + +} \ No newline at end of file diff --git a/Runtime/Reallusion/Shaders/Hair/Variants/CCHairShadowMaterial.cs.uid b/Runtime/Reallusion/Shaders/Hair/Variants/CCHairShadowMaterial.cs.uid new file mode 100644 index 0000000..c04201a --- /dev/null +++ b/Runtime/Reallusion/Shaders/Hair/Variants/CCHairShadowMaterial.cs.uid @@ -0,0 +1 @@ +uid://mlhre0bdeuci diff --git a/Runtime/Selectors/EvaluateSelector.cs b/Runtime/Selectors/EvaluateSelector.cs new file mode 100644 index 0000000..bd5006b --- /dev/null +++ b/Runtime/Selectors/EvaluateSelector.cs @@ -0,0 +1,51 @@ + +using System.Diagnostics; +using System.Collections; +using System.Collections.Generic; +using System; +using Godot; + + +namespace Rokojori +{ + [Tool] + [GlobalClass] + public partial class EvaluateSelector:Action + { + [Export] + public Node node; + + [Export] + public Selector selector; + + [Export] + public Action onSelected; + + [Export] + public Action onNotSelected; + + protected override void _OnTrigger() + { + this.LogInfo( "Evaluate" ); + + if ( node == null ) + { + this.LogInfo( "node == null" ); + return; + } + + var selected = Selector.IsSelecting( selector, node ); + + this.LogInfo( selected ); + + if ( selected ) + { + Trigger( onSelected ); + } + else + { + Trigger( onNotSelected ); + } + } + } +} \ No newline at end of file diff --git a/Runtime/Selectors/EvaluateSelector.cs.uid b/Runtime/Selectors/EvaluateSelector.cs.uid new file mode 100644 index 0000000..825b55d --- /dev/null +++ b/Runtime/Selectors/EvaluateSelector.cs.uid @@ -0,0 +1 @@ +uid://bi6w6fv52ktp diff --git a/Runtime/Sensors/OnSensor.cs b/Runtime/Sensors/OnSensor.cs index 4e3b2c1..fb56b7c 100644 --- a/Runtime/Sensors/OnSensor.cs +++ b/Runtime/Sensors/OnSensor.cs @@ -4,7 +4,7 @@ using Godot; namespace Rokojori { - [GlobalClass, Icon("res://addons/rokojori_action_library/Icons/OnEvent.svg") ] + [Tool][GlobalClass, Icon("res://addons/rokojori_action_library/Icons/OnEvent.svg") ] public partial class OnSensor: Node { [Export] diff --git a/Runtime/Sensors/SensorManager.cs b/Runtime/Sensors/SensorManager.cs index 4678eb7..5739190 100644 --- a/Runtime/Sensors/SensorManager.cs +++ b/Runtime/Sensors/SensorManager.cs @@ -102,9 +102,9 @@ namespace Rokojori if ( index == -1 ) { - deviceList = Arrays.Add( deviceList, d ); + deviceList = Arrays.AddEntry( deviceList, d ); index = deviceList.Length - 1; - deviceLastInputTimeStamp = Arrays.Add( deviceLastInputTimeStamp, 0 ); + deviceLastInputTimeStamp = Arrays.AddEntry( deviceLastInputTimeStamp, 0 ); } deviceLastInputTimeStamp[ index ] = (float) ( DateTime.Now - _startTime ).TotalSeconds; @@ -266,7 +266,7 @@ namespace Rokojori if ( showRegistratedSensors ) { - registratedSensors = Arrays.Add( registratedSensors, s ); + registratedSensors = Arrays.AddEntry( registratedSensors, s ); } } diff --git a/Runtime/Sensors/TriggerOnSensor.cs b/Runtime/Sensors/TriggerOnSensor.cs index 108fa24..a1bbd85 100644 --- a/Runtime/Sensors/TriggerOnSensor.cs +++ b/Runtime/Sensors/TriggerOnSensor.cs @@ -4,7 +4,7 @@ using Godot; namespace Rokojori { - [GlobalClass, Icon("res://addons/rokojori_action_library/Icons/OnEvent.svg") ] + [Tool][GlobalClass, Icon("res://addons/rokojori_action_library/Icons/OnEvent.svg") ] public partial class TriggerOnSensor: Node, SensorInputHandler { [Export] diff --git a/Runtime/Shading/Generators/Data/Vector2Modifier.cs b/Runtime/Shading/Generators/Data/Vector2Modifier.cs new file mode 100644 index 0000000..4eb55f8 --- /dev/null +++ b/Runtime/Shading/Generators/Data/Vector2Modifier.cs @@ -0,0 +1,14 @@ +using Godot; +using System.Reflection; +using System.Collections.Generic; + +namespace Rokojori +{ + [Tool] + [GlobalClass] + public partial class Vector2Modifier:ShaderGenerationModule + { + + + } +} \ No newline at end of file diff --git a/Runtime/Shading/Generators/Data/Vector2Modifier.cs.uid b/Runtime/Shading/Generators/Data/Vector2Modifier.cs.uid new file mode 100644 index 0000000..e74ef30 --- /dev/null +++ b/Runtime/Shading/Generators/Data/Vector2Modifier.cs.uid @@ -0,0 +1 @@ +uid://bot638uwd8rs4 diff --git a/Runtime/Shading/Generators/Data/Vector3Modifier.cs b/Runtime/Shading/Generators/Data/Vector3Modifier.cs new file mode 100644 index 0000000..0da3cd7 --- /dev/null +++ b/Runtime/Shading/Generators/Data/Vector3Modifier.cs @@ -0,0 +1,13 @@ +using Godot; +using System.Reflection; +using System.Collections.Generic; + +namespace Rokojori +{ + [Tool] + [GlobalClass] + public partial class Vector3Modifier:ShaderGenerationModule + { + + } +} \ No newline at end of file diff --git a/Runtime/Shading/Generators/Data/Vector3Modifier.cs.uid b/Runtime/Shading/Generators/Data/Vector3Modifier.cs.uid new file mode 100644 index 0000000..c880675 --- /dev/null +++ b/Runtime/Shading/Generators/Data/Vector3Modifier.cs.uid @@ -0,0 +1 @@ +uid://bt7pfk461q7de diff --git a/Runtime/Shading/Generators/ShaderCode.cs b/Runtime/Shading/Generators/ShaderCode.cs new file mode 100644 index 0000000..8fc2809 --- /dev/null +++ b/Runtime/Shading/Generators/ShaderCode.cs @@ -0,0 +1,51 @@ +using Godot; +using System.Reflection; +using System.Collections.Generic; + +namespace Rokojori +{ + public class ShaderCodeImports + { + public string importPath; + } + + public class ShaderCodeVariable + { + public string variableName; + } + + public class ShaderCode + { + public string variantName = ""; + public List imports = []; + public List variables = []; + + protected virtual string _GetCode( ShaderGenerationContext context ) + { + return ""; + } + + public string GetCode( ShaderGenerationContext context ) + { + return _GetCode( context ); + } + + + } + + public class StringShaderCode:ShaderCode + { + public string code = ""; + + public StringShaderCode( string code ) + { + this.code = code; + } + + protected override string _GetCode( ShaderGenerationContext context ) + { + return code; + } + } + +} \ No newline at end of file diff --git a/Runtime/Shading/Generators/ShaderCode.cs.uid b/Runtime/Shading/Generators/ShaderCode.cs.uid new file mode 100644 index 0000000..1b3f706 --- /dev/null +++ b/Runtime/Shading/Generators/ShaderCode.cs.uid @@ -0,0 +1 @@ +uid://daaagt1nn34mq diff --git a/Runtime/Shading/Generators/ShaderGenerationContext.cs b/Runtime/Shading/Generators/ShaderGenerationContext.cs new file mode 100644 index 0000000..aef08ad --- /dev/null +++ b/Runtime/Shading/Generators/ShaderGenerationContext.cs @@ -0,0 +1,41 @@ +using Godot; +using System.Reflection; +using System.Collections.Generic; + +namespace Rokojori +{ + public class ShaderGenerationContext + { + public ShaderPhase phase; + + + public List variants = new List(); + + public ShaderGenerationContext() + { + variants.Add( new ShaderVariant() ); + } + + public void Add( List code ) + { + if ( code == null || code.Count == 0 ) + { + return; + } + + var newVariants = new List(); + + for ( int i = 0; i < variants.Count; i++ ) + { + var v = variants[ i ]; + + for ( int j = 0; j < code.Count; j++ ) + { + newVariants.Add( v.Extend( code[ j ] ) ); + } + } + + variants = newVariants; + } + } +} \ No newline at end of file diff --git a/Runtime/Shading/Generators/ShaderGenerationContext.cs.uid b/Runtime/Shading/Generators/ShaderGenerationContext.cs.uid new file mode 100644 index 0000000..7d32035 --- /dev/null +++ b/Runtime/Shading/Generators/ShaderGenerationContext.cs.uid @@ -0,0 +1 @@ +uid://b51vuh2q2df57 diff --git a/Runtime/Shading/Generators/ShaderGenerationModule.cs b/Runtime/Shading/Generators/ShaderGenerationModule.cs new file mode 100644 index 0000000..722323e --- /dev/null +++ b/Runtime/Shading/Generators/ShaderGenerationModule.cs @@ -0,0 +1,138 @@ +using Godot; +using System.Reflection; +using System.Collections.Generic; +using Microsoft.VisualBasic; + +namespace Rokojori +{ + [Tool] + [GlobalClass] + public partial class ShaderGenerationModule:Resource + { + public virtual List GetVariantNames() + { + return new List(){ "" }; + } + + public virtual List GetCode( ShaderGenerationContext context ) + { + return new List(){}; + } + + public List ToCode( params string[] values ) + { + return Lists.From( (ShaderCode)new StringShaderCode( Lists.From( values ).Join( "" ) ) ); + } + + public List ToCode( string value ) + { + return Lists.From( (ShaderCode)new StringShaderCode( value ) ); + } + + public List AsUniformGroup( string name, string value ) + { + var wideName = RegexUtility.UpperCaseAndWide( name ); + var blockCode = value.Indent( " ", false ); + + var code = + @$" + // [ {wideName} ] + group_uniforms {name}; + + {blockCode} + + group_uniforms; + "; + + return ToCode( code.Indent( "" ) ); + + } + + public List ToInnerBlock( string name, string block ) + { + var wideName = RegexUtility.UpperCaseAndWide( name ); + var blockCode = block.Indent( " ", false ); + + var code = + + @$" + + // [ {wideName} ] + + {blockCode} + + "; + + return ToCode( code.Indent( " " ) ); + } + + public List ToCode( List values ) + { + return Lists.From( (ShaderCode)new StringShaderCode( Lists.From( values ).Join( "" ) ) ); + } + + public string Uniform( Vector2Property property ) + { + var name = property.propertyName.propertyName; + var x = property.value.X._G(); + var y = property.value.Y._G(); + + return @$"uniform vec2 {name} = vec2( {x}, {y});"; + } + + public string Uniform( string name, float value ) + { + return @$"uniform float {name} = {value._G()};"; + } + + public string Uniform01( string name, float value ) + { + return Uniform( name, value, 0, 1 ); + } + + public string Uniform( string name, float value, float min, float max ) + { + var mi = min._G(); + var ma = max._G(); + var v = value._G(); + + return @$"uniform float {name}:hint_range( {mi}, {ma}) = {v};"; + } + + public string UniformSampler( string name, string hints ) + { + return @$"uniform sampler2D {name}:{hints};"; + } + + public string Uniform( string name, Color color ) + { + var r = color.R._G(); + var g = color.G._G(); + var b = color.B._G(); + var a = color.A._G(); + + return @$"uniform vec4 {name}:source_color = vec4( {r}, {g}, {b}, {a});"; + + } + + public string Uniform( string name, Vector3 vec ) + { + var x = vec.X._G(); + var y = vec.Y._G(); + var z = vec.Z._G(); + + return @$"uniform vec3 {name} = vec3( {x}, {y}, {z});"; + } + + public string Uniform( string name, Vector4 vec ) + { + var x = vec.X._G(); + var y = vec.Y._G(); + var z = vec.Z._G(); + var w = vec.W._G(); + + return @$"uniform vec4 {name} = vec4( {x}, {y}, {z}, {w});"; + } + } + +} \ No newline at end of file diff --git a/Runtime/Shading/Generators/ShaderGenerationModule.cs.uid b/Runtime/Shading/Generators/ShaderGenerationModule.cs.uid new file mode 100644 index 0000000..a163668 --- /dev/null +++ b/Runtime/Shading/Generators/ShaderGenerationModule.cs.uid @@ -0,0 +1 @@ +uid://con8v7hea5lvw diff --git a/Runtime/Shading/Generators/ShaderGenerator.cs b/Runtime/Shading/Generators/ShaderGenerator.cs new file mode 100644 index 0000000..5ed0d7f --- /dev/null +++ b/Runtime/Shading/Generators/ShaderGenerator.cs @@ -0,0 +1,125 @@ +using Godot; +using System.Reflection; +using System.Collections.Generic; +using System.IO; + +namespace Rokojori +{ + [Tool] + [GlobalClass] + public partial class ShaderGenerator:Node + { + [ExportToolButton( "Create" )] + public Callable CreateButton => Callable.From( + ()=> + { + UpdateShader(); + } + ); + + [Export] + public string path; + + [Export] + public string shaderName; + + [Export] + public Shader shader; + + [Export] + public bool sendGodotUpdateMessage = false; + + public virtual List GetPhases() + { + return new List(); + } + + public virtual List GetShaderGenerationModules( ShaderPhase phase ) + { + return new List(); + } + + public virtual ShaderGenerationContext GenerateShaderVariants() + { + var context = new ShaderGenerationContext(); + + var phases = GetPhases(); + + this.LogInfo( context.variants ); + + phases.ForEach( + ( phase )=> + { + context.phase = phase; + + var modules = GetShaderGenerationModules( phase ); + + this.LogInfo( "PHASE", phase, ">>", context.variants, "MODS:", modules == null ? "-" : ( modules.Map( m => m.GetType().Name ) )); + + if ( modules == null ) + { + return; + } + + modules.ForEach( + ( m )=> + { + var code = m.GetCode( context ); + + this.LogInfo( phase, m.GetType().Name, code ); + + if ( code == null ) + { + return; + } + + context.Add( code ); + } + ); + } + ); + + + + + return context; + } + + public void UpdateShader() + { + var context = GenerateShaderVariants(); + this.LogInfo( "Created variants:", context.variants ); + + var first = true; + + foreach ( var variant in context.variants ) + { + var shaderCode = variant.GetCode( context ); + var absolutePath = path; + + if ( absolutePath.StartsWith( "res://" ) || absolutePath.StartsWith( "user://" ) ) + { + absolutePath = ProjectSettings.GlobalizePath( path ); + } + + this.LogInfo( shaderCode ); + var filePath = FilePath.Join( absolutePath, shaderName + variant.variantName + ".gdshader" ); + FilesSync.SaveUTF8( filePath, shaderCode ); + + if ( sendGodotUpdateMessage ) + { + GodotEditorHelper.UpdateFile( filePath ); + } + + if ( first ) + { + shader = ResourceLoader.Load( filePath ); + } + + first =false; + + } + + } + } +} \ No newline at end of file diff --git a/Runtime/Shading/Generators/ShaderGenerator.cs.uid b/Runtime/Shading/Generators/ShaderGenerator.cs.uid new file mode 100644 index 0000000..6f653a0 --- /dev/null +++ b/Runtime/Shading/Generators/ShaderGenerator.cs.uid @@ -0,0 +1 @@ +uid://ddih1nbj2c8v5 diff --git a/Runtime/Shading/Generators/ShaderPhases.cs b/Runtime/Shading/Generators/ShaderPhases.cs new file mode 100644 index 0000000..300af81 --- /dev/null +++ b/Runtime/Shading/Generators/ShaderPhases.cs @@ -0,0 +1,20 @@ +using Godot; +using System.Reflection; +using System.Collections.Generic; +using System.IO; + +namespace Rokojori +{ + public enum ShaderPhase + { + Header, + RenderMode, + Includes, + Variables, + Functions, + Vertex, + Fragment, + Light + + } +} diff --git a/Runtime/Shading/Generators/ShaderPhases.cs.uid b/Runtime/Shading/Generators/ShaderPhases.cs.uid new file mode 100644 index 0000000..38f8fbc --- /dev/null +++ b/Runtime/Shading/Generators/ShaderPhases.cs.uid @@ -0,0 +1 @@ +uid://curhwtqga38em diff --git a/Runtime/Shading/Generators/ShaderRawModule.cs b/Runtime/Shading/Generators/ShaderRawModule.cs new file mode 100644 index 0000000..01e66a7 --- /dev/null +++ b/Runtime/Shading/Generators/ShaderRawModule.cs @@ -0,0 +1,46 @@ +using Godot; +using System.Reflection; +using System.Collections.Generic; +using System.IO; + +namespace Rokojori +{ + [Tool] + [GlobalClass] + public partial class ShaderRawModule:ShaderGenerationModule + { + [Export] + public string value; + + [Export] + public ShaderPhase phase; + + [Export] + public bool matchPhase = false; + + public ShaderRawModule( string value, ShaderPhase? phase = null ) + { + if ( phase != null ) + { + phase = (ShaderPhase) phase; + matchPhase = true; + } + else + { + matchPhase = false; + } + + this.value = value; + } + + public override List GetCode( ShaderGenerationContext context ) + { + if ( matchPhase && context.phase != phase ) + { + return null; + } + + return Lists.From( (ShaderCode) new StringShaderCode( value ) ); + } + } +} \ No newline at end of file diff --git a/Runtime/Shading/Generators/ShaderRawModule.cs.uid b/Runtime/Shading/Generators/ShaderRawModule.cs.uid new file mode 100644 index 0000000..708a85c --- /dev/null +++ b/Runtime/Shading/Generators/ShaderRawModule.cs.uid @@ -0,0 +1 @@ +uid://ckabfctoioyr7 diff --git a/Runtime/Shading/Generators/ShaderVariant.cs b/Runtime/Shading/Generators/ShaderVariant.cs new file mode 100644 index 0000000..faca9eb --- /dev/null +++ b/Runtime/Shading/Generators/ShaderVariant.cs @@ -0,0 +1,29 @@ +using Godot; +using System.Reflection; +using System.Collections.Generic; + +namespace Rokojori +{ + public class ShaderVariant + { + public string variantName = ""; + public List shaderCode = []; + + public string GetCode( ShaderGenerationContext context ) + { + return shaderCode.Map( s => s.GetCode( context ) ).Join( "" ); + } + + public ShaderVariant Extend( ShaderCode shaderCode ) + { + var variant = new ShaderVariant(); + variant.variantName = variantName + shaderCode.variantName; + + variant.shaderCode = this.shaderCode.Clone(); + variant.shaderCode.Add( shaderCode ); + + return variant; + } + } + +} \ No newline at end of file diff --git a/Runtime/Shading/Generators/ShaderVariant.cs.uid b/Runtime/Shading/Generators/ShaderVariant.cs.uid new file mode 100644 index 0000000..8ad1dae --- /dev/null +++ b/Runtime/Shading/Generators/ShaderVariant.cs.uid @@ -0,0 +1 @@ +uid://d3dqbw7y7nemp diff --git a/Runtime/Shading/Generators/Spatial/Albedo/AlbedoModule.cs b/Runtime/Shading/Generators/Spatial/Albedo/AlbedoModule.cs new file mode 100644 index 0000000..a87ccdf --- /dev/null +++ b/Runtime/Shading/Generators/Spatial/Albedo/AlbedoModule.cs @@ -0,0 +1,44 @@ +using Godot; +using System.Reflection; +using System.Collections.Generic; + +namespace Rokojori +{ + [Tool] + [GlobalClass] + public partial class AlbedoModule:TextureModule + { + public AlbedoModule() + { + _type = TextureChannelType.RGBA; + + _domainName = "albedo"; + _domainScaleName = "albedo"; + + _srgb = true; + } + + [Export] + public TextureFilter filter = TextureFilter.Linear_MipMap_Anisotropic; + + [Export] + public bool useTint = true; + + [Export] + public bool srgb = true; + + [Export] + public bool repeat = true; + + [Export] + public TextureDefault textureDefault = TextureDefault.White; + public override void GrabValues() + { + domainMode = useTint ? DomainMode.Texture_Scale : DomainMode.Texture; + _textureFilter = filter; + _srgb = srgb; + _repeat = repeat; + _textureDefault = textureDefault; + } + } +} \ No newline at end of file diff --git a/Runtime/Shading/Generators/Spatial/Albedo/AlbedoModule.cs.uid b/Runtime/Shading/Generators/Spatial/Albedo/AlbedoModule.cs.uid new file mode 100644 index 0000000..74ec280 --- /dev/null +++ b/Runtime/Shading/Generators/Spatial/Albedo/AlbedoModule.cs.uid @@ -0,0 +1 @@ +uid://cxev8s3qvg8sq diff --git a/Runtime/Shading/Generators/Spatial/ShadingModule.cs b/Runtime/Shading/Generators/Spatial/ShadingModule.cs new file mode 100644 index 0000000..a4b08e5 --- /dev/null +++ b/Runtime/Shading/Generators/Spatial/ShadingModule.cs @@ -0,0 +1,99 @@ +using Godot; +using System.Reflection; +using System.Collections.Generic; + +namespace Rokojori +{ + [Tool] + [GlobalClass] + public partial class ShadingModule:ShaderGenerationModule + { + [Export] + public BaseMaterial3D.ShadingModeEnum shadingMode = BaseMaterial3D.ShadingModeEnum.PerPixel; + + [Export] + public BaseMaterial3D.DiffuseModeEnum diffuseMode = BaseMaterial3D.DiffuseModeEnum.Burley; + + [Export] + public BaseMaterial3D.SpecularModeEnum specularMode = BaseMaterial3D.SpecularModeEnum.SchlickGgx; + + [Export] + public bool disableAmbientLight = false; + + [Export] + public bool disableFog = false; + + [Export] + public bool disableReceivingShadows = false; + + [Export] + public bool shadowToOpacity = false; + + [Export] + public bool wireFrameMode = false; + + public override List GetCode( ShaderGenerationContext context ) + { + if ( ShaderPhase.RenderMode != context.phase ) + { + return null; + } + + var value = ""; + + var shadingModes = new Dictionary(); + shadingModes[ BaseMaterial3D.ShadingModeEnum.PerPixel ] = ""; + shadingModes[ BaseMaterial3D.ShadingModeEnum.PerVertex ] = "vertex_lighting, "; + shadingModes[ BaseMaterial3D.ShadingModeEnum.Unshaded ] = "unshaded, "; + + value += shadingModes[ shadingMode ]; + + + var diffuseModes = new Dictionary(); + diffuseModes[ BaseMaterial3D.DiffuseModeEnum.Burley ] = "diffuse_burley"; + diffuseModes[ BaseMaterial3D.DiffuseModeEnum.Lambert] = "diffuse_lambert"; + diffuseModes[ BaseMaterial3D.DiffuseModeEnum.LambertWrap] = "diffuse_lambert_wrap"; + diffuseModes[ BaseMaterial3D.DiffuseModeEnum.Toon ] = "diffuse_toon"; + + value += diffuseModes[ diffuseMode ] + ", "; + + var specularModes = new Dictionary(); + specularModes[ BaseMaterial3D.SpecularModeEnum.SchlickGgx ] = "specular_schlick_ggx"; + specularModes[ BaseMaterial3D.SpecularModeEnum.Toon ] = "specular_toon"; + specularModes[ BaseMaterial3D.SpecularModeEnum.Disabled ] = "specular_disabled"; + + value += specularModes[ specularMode ] + ", "; + + if ( disableAmbientLight ) + { + value += "ambient_light_disabled, "; + } + + if ( disableFog ) + { + value += "fog_disabled, "; + } + + if ( disableReceivingShadows ) + { + value += "shadows_disabled, "; + } + + if ( disableReceivingShadows ) + { + value += "shadow_to_opacity, "; + } + + if ( wireFrameMode ) + { + value += "wireframe"; + } + + value = RegexUtility.Replace( value, @"\,\s*$", "" ); + + return Lists.From( (ShaderCode) new StringShaderCode( value ) ); + } + + } + +} \ No newline at end of file diff --git a/Runtime/Shading/Generators/Spatial/ShadingModule.cs.uid b/Runtime/Shading/Generators/Spatial/ShadingModule.cs.uid new file mode 100644 index 0000000..6e237be --- /dev/null +++ b/Runtime/Shading/Generators/Spatial/ShadingModule.cs.uid @@ -0,0 +1 @@ +uid://ckll7njnako4c diff --git a/Runtime/Shading/Generators/Spatial/SpatialShaderGenerator.cs b/Runtime/Shading/Generators/Spatial/SpatialShaderGenerator.cs new file mode 100644 index 0000000..9b8556d --- /dev/null +++ b/Runtime/Shading/Generators/Spatial/SpatialShaderGenerator.cs @@ -0,0 +1,113 @@ +using Godot; +using System.Reflection; +using System.Collections.Generic; + +namespace Rokojori +{ + [Tool] + [GlobalClass] + public partial class SpatialShaderGenerator:ShaderGenerator + { + [Export] + public TransparencyModule transparency = new TransparencyModule(); + + [Export] + public ShadingModule shading = new ShadingModule(); + + [Export] + public VertexModule vertex = new VertexModule(); + + [Export] + public UVModule uv = new UVModule(); + + [Export] + public AlbedoModule albedo = new AlbedoModule(); + + + public override List GetPhases() + { + return new List() + { + ShaderPhase.Header, + ShaderPhase.RenderMode, + ShaderPhase.Includes, + ShaderPhase.Variables, + ShaderPhase.Functions, + ShaderPhase.Vertex, + ShaderPhase.Fragment, + ShaderPhase.Light + }; + } + + public override List GetShaderGenerationModules( ShaderPhase phase ) + { + if ( ShaderPhase.Header == phase ) + { + return + [ + new ShaderRawModule( "\n\nshader_type spatial;\n" ) + ]; + } + + if ( ShaderPhase.RenderMode == phase ) + { + return + [ + new ShaderRawModule( "render_mode " ), + transparency, + new ShaderRawModule( ", " ), + shading, + new ShaderRawModule( ";\n\n" ), + ]; + } + + if ( ShaderPhase.Includes == phase || ShaderPhase.Variables == phase || ShaderPhase.Functions == phase ) + { + return + [ + transparency, + shading, + vertex, + uv, + albedo + ]; + } + + if ( ShaderPhase.Vertex == phase ) + { + return new List() + { + new ShaderRawModule( "\nvoid vertex()\n{\n\n" ) + } + .Concat + ( + uv, vertex, albedo + ) + .Concat + ( + new ShaderRawModule( "\n}\n" ) + ); + } + + if ( ShaderPhase.Fragment == phase ) + { + return new List() + { + new ShaderRawModule( "\nvoid fragment()\n{\n\n" ) + } + .Concat + ( + uv, vertex, albedo + ) + .Concat + ( + new ShaderRawModule( "\n}\n" ) + ); + } + + + return null; + + } + } +} \ No newline at end of file diff --git a/Runtime/Shading/Generators/Spatial/SpatialShaderGenerator.cs.uid b/Runtime/Shading/Generators/Spatial/SpatialShaderGenerator.cs.uid new file mode 100644 index 0000000..5ba8253 --- /dev/null +++ b/Runtime/Shading/Generators/Spatial/SpatialShaderGenerator.cs.uid @@ -0,0 +1 @@ +uid://2gudnu1r4pjg diff --git a/Runtime/Shading/Generators/Spatial/TextureModule.cs b/Runtime/Shading/Generators/Spatial/TextureModule.cs new file mode 100644 index 0000000..0cd3442 --- /dev/null +++ b/Runtime/Shading/Generators/Spatial/TextureModule.cs @@ -0,0 +1,151 @@ +using Godot; +using System.Reflection; +using System.Collections.Generic; + +namespace Rokojori +{ + [Tool] + [GlobalClass] + public partial class TextureModule:ShaderGenerationModule + { + public enum TextureChannelType + { + RGBA, + RGB, + ONE + } + + public enum TextureChannelSource + { + R, + G, + B, + A, + CUSTOMIZABLE + } + + public TextureChannelType _type; + public TextureChannelSource _channelSource; + + public bool is1D => _type == TextureChannelType.ONE; + + public string _domainName; + public string _domainValueName; + public string _domainScaleName; + public string _domainOffsetName; + + public bool _srgb = false; + public bool _repeat = true; + + public enum DomainMode + { + Value, + Texture, + Texture_Scale, + Texture_Scale_Offset + } + + public DomainMode domainMode = DomainMode.Texture_Scale_Offset; + public float domainOffsetDefault = 0; + public float domainOffsetMin = -1; + public float domainOffsetMax = 1; + + public float domainValueDefault = 0.5f; + public float domainValueMin = 0; + public float domainValueMax = 1; + + public enum TextureDefault + { + White, + Black + } + + public TextureDefault _textureDefault = TextureDefault.White; + + public TextureFilter _textureFilter = TextureFilter.Linear_MipMap_Anisotropic; + + public enum TextureFilter + { + Nearest, + Nearest_MipMap, + Nearest_MipMap_Anisotropic, + Linear, + Linear_MipMap, + Linear_MipMap_Anisotropic + } + + public virtual void GrabValues() + { + + } + + public override List GetCode( ShaderGenerationContext context ) + { + GrabValues(); + + if ( ShaderPhase.Variables == context.phase ) + { + var textureName = _domainName; + + var valuesDefinition = ""; + var samplerDefinition = ""; + + + if ( DomainMode.Value != domainMode ) + { + var hints = new List(); + + if ( _srgb ) + { + hints.Add( "source_color" ); + } + + hints.Add( TextureDefault.Black == _textureDefault ? "hint_default_black" : "hint_default_white" ); + hints.Add( _repeat ? "repeat_enable" : "repeat_disable" ); + hints.Add( "filter_" + ( _textureFilter + "" ).ToLower() ); + + var textureSamplerName = _domainName + "Texture"; + + samplerDefinition = UniformSampler( textureSamplerName, hints.Join() ); + + if ( domainMode != DomainMode.Texture ) + { + if ( is1D ) + { + valuesDefinition += Uniform01( _domainScaleName, 1.0f ); + } + else + { + valuesDefinition += Uniform( _domainScaleName, Colors.White ); + } + + valuesDefinition +="\n"; + } + } + + if ( DomainMode.Value == domainMode ) + { + valuesDefinition += Uniform( _domainValueName, domainValueDefault, domainValueMin, domainValueMax ); + } + else if ( DomainMode.Texture_Scale_Offset == domainMode ) + { + valuesDefinition += "\n"; + valuesDefinition += Uniform( _domainOffsetName, domainOffsetDefault, domainOffsetMin, domainOffsetMax ); + valuesDefinition += "\n"; + } + + + + + + var code = valuesDefinition + samplerDefinition; + + return AsUniformGroup( textureName, code ); + + } + + return null; + } + } + +} \ No newline at end of file diff --git a/Runtime/Shading/Generators/Spatial/TextureModule.cs.uid b/Runtime/Shading/Generators/Spatial/TextureModule.cs.uid new file mode 100644 index 0000000..3687a6b --- /dev/null +++ b/Runtime/Shading/Generators/Spatial/TextureModule.cs.uid @@ -0,0 +1 @@ +uid://b3t616w6evf6v diff --git a/Runtime/Shading/Generators/Spatial/TransparencyModule.cs b/Runtime/Shading/Generators/Spatial/TransparencyModule.cs new file mode 100644 index 0000000..4bdf012 --- /dev/null +++ b/Runtime/Shading/Generators/Spatial/TransparencyModule.cs @@ -0,0 +1,100 @@ +using Godot; +using System.Reflection; +using System.Collections.Generic; + +namespace Rokojori +{ + [Tool] + [GlobalClass] + public partial class TransparencyModule:ShaderGenerationModule + { + [Export] + public BaseMaterial3D.TransparencyEnum transparency = BaseMaterial3D.TransparencyEnum.Disabled; + + [ExportGroup( "Alpha Scissor")] + [Export] + public float alphaScissorTreshold = 0.5f; + + [ExportGroup( "")] + [Export] + public BaseMaterial3D.BlendModeEnum blendMode = BaseMaterial3D.BlendModeEnum.Mix; + + [Export] + public BaseMaterial3D.CullModeEnum cullMode = BaseMaterial3D.CullModeEnum.Back; + + [Export] + public BaseMaterial3D.DepthDrawModeEnum depthDraw = BaseMaterial3D.DepthDrawModeEnum.OpaqueOnly; + + [Export] + public bool noDepthTest = false; + + public override List GetCode( ShaderGenerationContext context ) + { + if ( ShaderPhase.Fragment == context.phase ) + { + if ( BaseMaterial3D.TransparencyEnum.AlphaScissor == transparency ) + { + return Lists.From( (ShaderCode) new StringShaderCode( + "ALPHA_SCISSOR_THRESHOLD = " + RegexUtility.NumberToString( alphaScissorTreshold ) + ) ); + } + + return null; + + } + + if ( ShaderPhase.RenderMode != context.phase ) + { + return null; + } + + var value = ""; + + var transparencyModes = new Dictionary(); + transparencyModes[ BaseMaterial3D.TransparencyEnum.Disabled ] = ""; + transparencyModes[ BaseMaterial3D.TransparencyEnum.Alpha ] = ""; + transparencyModes[ BaseMaterial3D.TransparencyEnum.AlphaScissor ] = ""; + transparencyModes[ BaseMaterial3D.TransparencyEnum.AlphaHash ] = ""; + transparencyModes[ BaseMaterial3D.TransparencyEnum.AlphaDepthPrePass ] = "depth_prepass_alpha, "; + + value += transparencyModes[ transparency ]; + + + var blendModes = new Dictionary(); + blendModes[ BaseMaterial3D.BlendModeEnum.Mix ] = "blend_mix"; + blendModes[ BaseMaterial3D.BlendModeEnum.Add ] = "blend_add"; + blendModes[ BaseMaterial3D.BlendModeEnum.Mul ] = "blend_mul"; + blendModes[ BaseMaterial3D.BlendModeEnum.Sub ] = "blend_sub"; + blendModes[ BaseMaterial3D.BlendModeEnum.PremultAlpha ] = "blend_premul_alpha"; + + value += blendModes[ blendMode ] + ", "; + + var cullmodes = new Dictionary(); + cullmodes[ BaseMaterial3D.CullModeEnum.Disabled ] = "cull_disabled"; + cullmodes[ BaseMaterial3D.CullModeEnum.Front ] = "cull_front"; + cullmodes[ BaseMaterial3D.CullModeEnum.Back ] = "cull_back"; + + value += cullmodes[ cullMode ] + ", "; + + + var depthModes = new Dictionary(); + depthModes[ BaseMaterial3D.DepthDrawModeEnum.OpaqueOnly ] = "depth_draw_opaque"; + depthModes[ BaseMaterial3D.DepthDrawModeEnum.Always ] = "depth_draw_always"; + depthModes[ BaseMaterial3D.DepthDrawModeEnum.Disabled ] = "depth_draw_never"; + + value += depthModes[ depthDraw ] + ", "; + + + if ( noDepthTest ) + { + value += "depth_test_disabled"; + } + + value = RegexUtility.Replace( value, @"\,\s*$", "" ); + + return Lists.From( (ShaderCode) new StringShaderCode( value ) ); + } + + + } +} \ No newline at end of file diff --git a/Runtime/Shading/Generators/Spatial/TransparencyModule.cs.uid b/Runtime/Shading/Generators/Spatial/TransparencyModule.cs.uid new file mode 100644 index 0000000..fc6b012 --- /dev/null +++ b/Runtime/Shading/Generators/Spatial/TransparencyModule.cs.uid @@ -0,0 +1 @@ +uid://ckstqai24gfu2 diff --git a/Runtime/Shading/Generators/Spatial/UV/UVModifier.cs b/Runtime/Shading/Generators/Spatial/UV/UVModifier.cs new file mode 100644 index 0000000..84a62df --- /dev/null +++ b/Runtime/Shading/Generators/Spatial/UV/UVModifier.cs @@ -0,0 +1,13 @@ +using Godot; +using System.Reflection; +using System.Collections.Generic; + +namespace Rokojori +{ + [Tool] + [GlobalClass] + public partial class UVModifier:ShaderGenerationModule + { + + } +} \ No newline at end of file diff --git a/Runtime/Shading/Generators/Spatial/UV/UVModifier.cs.uid b/Runtime/Shading/Generators/Spatial/UV/UVModifier.cs.uid new file mode 100644 index 0000000..025f856 --- /dev/null +++ b/Runtime/Shading/Generators/Spatial/UV/UVModifier.cs.uid @@ -0,0 +1 @@ +uid://bn3boojq548iy diff --git a/Runtime/Shading/Generators/Spatial/UV/UVModule.cs b/Runtime/Shading/Generators/Spatial/UV/UVModule.cs new file mode 100644 index 0000000..a4e4bf7 --- /dev/null +++ b/Runtime/Shading/Generators/Spatial/UV/UVModule.cs @@ -0,0 +1,45 @@ +using Godot; +using System.Reflection; +using System.Collections.Generic; + +namespace Rokojori +{ + [Tool] + [GlobalClass] + public partial class UVModule:ShaderGenerationModule + { + [Export] + public UVScaleOffset uvScaleOffset = new UVScaleOffset(); + + [Export] + public UVModifier[] modifiers = []; + + public override List GetCode( ShaderGenerationContext context ) + { + var list = new List(); + + var allModifiers = Lists.From( modifiers ).FilterNulls(); + + if ( uvScaleOffset != null ) + { + allModifiers.Insert( 0, uvScaleOffset ); + } + + allModifiers.ForEach( + ( m )=> + { + var code = m.GetCode( context ); + + if ( code == null ) + { + return; + } + + list.Add( code ); + } + ); + + return list; + } + } +} \ No newline at end of file diff --git a/Runtime/Shading/Generators/Spatial/UV/UVModule.cs.uid b/Runtime/Shading/Generators/Spatial/UV/UVModule.cs.uid new file mode 100644 index 0000000..701bc3c --- /dev/null +++ b/Runtime/Shading/Generators/Spatial/UV/UVModule.cs.uid @@ -0,0 +1 @@ +uid://ocri03glwwv7 diff --git a/Runtime/Shading/Generators/Spatial/UV/UVScaleOffset.cs b/Runtime/Shading/Generators/Spatial/UV/UVScaleOffset.cs new file mode 100644 index 0000000..0b84129 --- /dev/null +++ b/Runtime/Shading/Generators/Spatial/UV/UVScaleOffset.cs @@ -0,0 +1,71 @@ +using Godot; +using System.Reflection; +using System.Collections.Generic; + +namespace Rokojori +{ + [Tool] + [GlobalClass] + public partial class UVScaleOffset:UVModifier + { + [Export] + public Vector2Property uvScale = Vector2Property.Create( "uv_scale", Vector2.One ); + + [Export] + public Vector2Property uvOffset = Vector2Property.Create( "uv_offset", Vector2.Zero ); + + [Export] + public Vector2Property uvScrolling = Vector2Property.Create( "uv_scrolling", Vector2.Zero ); + + [Export] + public string target = "UV"; + + + public override List GetCode( ShaderGenerationContext context ) + { + if ( ShaderPhase.Variables == context.phase ) + { + var lines = new List(); + + + Lists.From( uvScale, uvOffset, uvScrolling ).FilterNulls().ForEach( + ( p )=> + { + lines.Add( Uniform( p ) + "\n" ); + } + ); + + + return AsUniformGroup( "UV", lines.Join( "" ) ); + + } + + if ( ShaderPhase.Vertex == context.phase ) + { + var expression = " " + target + " = " + target; + + if ( uvScale != null ) + { + expression += " * " + uvScale.name; + } + + if ( uvOffset != null ) + { + expression += " + " + uvOffset.name; + } + + if ( uvScrolling != null ) + { + expression += " + TIME * " + uvScrolling.name; + } + + expression += ";"; + + return ToCode( expression ); + + } + + return null; + } + } +} \ No newline at end of file diff --git a/Runtime/Shading/Generators/Spatial/UV/UVScaleOffset.cs.uid b/Runtime/Shading/Generators/Spatial/UV/UVScaleOffset.cs.uid new file mode 100644 index 0000000..be110d2 --- /dev/null +++ b/Runtime/Shading/Generators/Spatial/UV/UVScaleOffset.cs.uid @@ -0,0 +1 @@ +uid://7kmku6bld3yt diff --git a/Runtime/Shading/Generators/Spatial/Vertex/VertexModifier.cs b/Runtime/Shading/Generators/Spatial/Vertex/VertexModifier.cs new file mode 100644 index 0000000..79c94f4 --- /dev/null +++ b/Runtime/Shading/Generators/Spatial/Vertex/VertexModifier.cs @@ -0,0 +1,13 @@ +using Godot; +using System.Reflection; +using System.Collections.Generic; + +namespace Rokojori +{ + [Tool] + [GlobalClass] + public partial class VertexModifier:ShaderGenerationModule + { + + } +} \ No newline at end of file diff --git a/Runtime/Shading/Generators/Spatial/Vertex/VertexModifier.cs.uid b/Runtime/Shading/Generators/Spatial/Vertex/VertexModifier.cs.uid new file mode 100644 index 0000000..48e9308 --- /dev/null +++ b/Runtime/Shading/Generators/Spatial/Vertex/VertexModifier.cs.uid @@ -0,0 +1 @@ +uid://dgqkqr4d6nlrm diff --git a/Runtime/Shading/Generators/Spatial/Vertex/VertexModifierModule.cs.uid b/Runtime/Shading/Generators/Spatial/Vertex/VertexModifierModule.cs.uid new file mode 100644 index 0000000..f39ffeb --- /dev/null +++ b/Runtime/Shading/Generators/Spatial/Vertex/VertexModifierModule.cs.uid @@ -0,0 +1 @@ +uid://m63lib33qcs2 diff --git a/Runtime/Shading/Generators/Spatial/Vertex/VertexModule.cs b/Runtime/Shading/Generators/Spatial/Vertex/VertexModule.cs new file mode 100644 index 0000000..6800931 --- /dev/null +++ b/Runtime/Shading/Generators/Spatial/Vertex/VertexModule.cs @@ -0,0 +1,46 @@ +using Godot; +using System.Reflection; +using System.Collections.Generic; + +namespace Rokojori +{ + [Tool] + [GlobalClass] + public partial class VertexModule:ShaderGenerationModule + { + [Export] + public VertexWind wind = new VertexWind(); + + + [Export] + public VertexModifier[] modifiers = []; + + public override List GetCode( ShaderGenerationContext context ) + { + var list = new List(); + + var allModifiers = Lists.From( modifiers ).FilterNulls(); + + if ( wind != null ) + { + allModifiers.Insert( 0, wind ); + } + + allModifiers.ForEach( + ( m )=> + { + var code = m.GetCode( context ); + + if ( code == null ) + { + return; + } + + list.Add( code ); + } + ); + + return list; + } + } +} \ No newline at end of file diff --git a/Runtime/Shading/Generators/Spatial/Vertex/VertexModule.cs.uid b/Runtime/Shading/Generators/Spatial/Vertex/VertexModule.cs.uid new file mode 100644 index 0000000..d5a008c --- /dev/null +++ b/Runtime/Shading/Generators/Spatial/Vertex/VertexModule.cs.uid @@ -0,0 +1 @@ +uid://drc5hdnwme7be diff --git a/Runtime/Shading/Generators/Spatial/Vertex/VertexWind.cs b/Runtime/Shading/Generators/Spatial/Vertex/VertexWind.cs new file mode 100644 index 0000000..168242f --- /dev/null +++ b/Runtime/Shading/Generators/Spatial/Vertex/VertexWind.cs @@ -0,0 +1,77 @@ +using Godot; +using System.Reflection; +using System.Collections.Generic; + +namespace Rokojori +{ + [Tool] + [GlobalClass] + public partial class VertexWind:VertexModifier + { + [Export] + public bool enabled = true; + + [Export] + public bool sampleAngleFromNoise = true; + + [Export] + public bool heightCompensation = true; + + + public override List GetCode( ShaderGenerationContext context ) + { + if ( ShaderPhase.Includes == context.phase ) + { + return ToCode( "#include \"res://addons/rokojori_action_library/Runtime/Shading/Library/Wind.gdshaderinc\"" ); + } + + if ( ShaderPhase.Variables == context.phase ) + { + return AsUniformGroup( "Wind", + + @" + uniform float windStrength = 0; + uniform vec2 windSpeed = vec2(1,1); + uniform float windScale = 1; + uniform sampler2D windNoise; + uniform vec2 windNoiseAngleOffset; + uniform vec2 windNoiseStrengthOffset = vec2( 0.1234, 0.56789 ); + uniform float windStart = 0; + uniform float windEnd = 1; + uniform float windWeightCurve:hint_range(0,1) = 0.5f; + uniform float windHeightCompensation :hint_range(0,1) = 0.5f; + " + + ); + + } + + if ( ShaderPhase.Vertex == context.phase ) + { + + return ToInnerBlock( "Wind", + + @" + applyWind( + TIME, MODEL_MATRIX, VERTEX, + + windStrength, + windSpeed, + windScale, + windNoise, + windNoiseAngleOffset, + windNoiseStrengthOffset, + windStart, + windEnd, + windWeightCurve, + windHeightCompensation + ); + " + + ); + } + + return null; + } + } +} \ No newline at end of file diff --git a/Runtime/Shading/Generators/Spatial/Vertex/VertexWind.cs.uid b/Runtime/Shading/Generators/Spatial/Vertex/VertexWind.cs.uid new file mode 100644 index 0000000..ea4ff54 --- /dev/null +++ b/Runtime/Shading/Generators/Spatial/Vertex/VertexWind.cs.uid @@ -0,0 +1 @@ +uid://c72tabs5laald diff --git a/Runtime/Shading/Library/Cameras.gdshaderinc b/Runtime/Shading/Library/Cameras.gdshaderinc index df255ba..ee34f5b 100644 --- a/Runtime/Shading/Library/Cameras.gdshaderinc +++ b/Runtime/Shading/Library/Cameras.gdshaderinc @@ -1,5 +1,7 @@ // #include "res://addons/rokojori_action_library/Runtime/Shading/Library/Cameras.gdshaderinc" +#include "res://addons/rokojori_action_library/Runtime/Shading/Library/Transform.gdshaderinc" + bool cameraContainsLayerIndex( int layerIndex, uint _CAMERA_VISIBLE_LAYERS ) { uint layer = uint( 1 << ( layerIndex - 1 ) ); @@ -10,4 +12,18 @@ bool cameraHasOnlyLayerIndex( int layerIndex, uint _CAMERA_VISIBLE_LAYERS ) { uint layer = uint( 1 << ( layerIndex - 1 ) ); return _CAMERA_VISIBLE_LAYERS == layer; -} \ No newline at end of file +} + +float cameraDistanceLocal( vec3 localPosition, vec3 _CAMERA_POSITION_WORLD, mat4 _MODEL_MATRIX ) +{ + vec3 worldPosition = localToWorld( localPosition, _MODEL_MATRIX ); + + return length( worldPosition - _CAMERA_POSITION_WORLD ); +} + +float cameraDistanceAmount( vec3 localPosition, vec3 _CAMERA_POSITION_WORLD, mat4 _MODEL_MATRIX, float close, float far ) +{ + float distance = cameraDistanceLocal( localPosition, _CAMERA_POSITION_WORLD, _MODEL_MATRIX ); + float mapped = ( distance - close ) / ( far - close ); + return clamp( mapped, 0, 1 ); +} diff --git a/Runtime/Shading/Library/Colors.gdshaderinc b/Runtime/Shading/Library/Colors.gdshaderinc index c3de4c4..24d064d 100644 --- a/Runtime/Shading/Library/Colors.gdshaderinc +++ b/Runtime/Shading/Library/Colors.gdshaderinc @@ -16,12 +16,53 @@ vec3 RGBtoHCV( vec3 rgb ) } -vec3 RGBtoHSL( vec3 rgb ) +vec3 RGBtoHSL( vec3 c ) { - vec3 HCV = RGBtoHCV( rgb ); - float L = HCV.z - HCV.y * 0.5; - float S = HCV.y / ( 1.0 - abs( L * 2.0 - 1.0 ) + HSL_EPSILON ); - return vec3( HCV.x, S, L ); + float h = 0.0; + float s = 0.0; + float l = 0.0; + + float cmin = min( min( c.r, c.g ), c.b ); + float cmax = max( max( c.r, c.g ), c.b ); + + l = ( cmin + cmax ) / 2.0; + + if ( cmin == cmax ) + { + s = 0.0; + h = 0.0; + } + else + { + float delta = cmax - cmin; + + s = ( l <= 0.5 ) ? ( delta / ( cmax + cmin ) ) : ( delta / ( 2.0 - ( cmax + cmin ) ) ); + + h = 0.0; + + if ( c.r == cmax ) + { + h = ( c.g - c.b ) / delta; + } + else if ( c.g == cmax ) + { + h = 2.0 + ( c.b - c.r ) / delta; + } + else if ( c.b == cmax ) + { + h = 4.0 + ( c.r - c.g ) / delta; + } + + h = h / 6.0; + + if ( h > 1.0 ) + { + h -= 1.0; + } + + } + + return vec3( h, s, l ); } vec3 hueToRGB( float hue ) @@ -29,11 +70,16 @@ vec3 hueToRGB( float hue ) float R = abs( hue * 6.0 - 3.0 ) - 1.0; float G = 2.0 - abs( hue * 6.0 - 2.0 ); float B = 2.0 - abs( hue * 6.0 - 4.0 ); - return clamp( vec3( R,G,B ),0,1 ); + return clamp( vec3( R,G,B ), 0, 1 ); } vec3 HSLtoRGB( vec3 hsl ) { + if ( hsl.y == 0.0 ) + { + return vec3( hsl.z, hsl.z, hsl.z ); + } + vec3 rgb = hueToRGB( hsl.x ); float C = ( 1.0 - abs( 2.0 * hsl.z - 1.0 )) * hsl.y; return ( rgb - 0.5 ) * C + hsl.z; @@ -49,6 +95,8 @@ vec3 adjustHSL( vec3 color, vec3 hslAdjustment ) return HSLtoRGB( hsl ); } + + vec3 toLinear( vec3 sRGB ) { return mix( pow( (sRGB + vec3( 0.055 )) * ( 1.0 / ( 1.0 + 0.055 )),vec3( 2.4 )),sRGB * ( 1.0 / 12.92 ),lessThan( sRGB,vec3( 0.04045 )) ); @@ -160,6 +208,7 @@ vec4 fade( vec4 rgba, float fade ) return vec4( rgba.rgb, rgba.a * fade ); } + vec4 straightToPremultipliedColor( vec4 color ) { return vec4( color.rgb * color.a, color.a ); @@ -167,19 +216,11 @@ vec4 straightToPremultipliedColor( vec4 color ) vec4 premultipliedToStraightColor( vec4 color ) { - color.a = max( color.a, 0.000001f ); - - return vec4( color.rgb / color.a, color.a ); + return color.a == 0.0 ? color : vec4( color.rgb / color.a, color.a ); } -vec4 blendMode_alpha( vec4 top, vec4 bottom ) -{ - float alpha = top.a + bottom.a * ( 1.0 - top.a ); - vec3 color = top.rgb * top.a + bottom.rgb * bottom.a * ( 1.0 - top.a ); - return vec4( color, alpha ); -} vec4 mixThreeColors( vec4 a, vec4 b, vec4 c, float t ) @@ -200,12 +241,110 @@ vec3 gamma( vec3 color, float gamma ) return color; } +vec4 gamma( vec4 color, float gamma ) +{ + color.r = pow( color.r, gamma ); + color.g = pow( color.g, gamma ); + color.b = pow( color.b, gamma ); + color.a = color.a; + + return color; +} + vec3 gammaSRGB( vec3 color ) { return gamma( color, 2.2 ); } +vec4 gammaSRGB( vec4 color ) +{ + return gamma( color, 2.2 ); +} + vec3 gammaSRGBInverse( vec3 color ) { return gamma( color, 1.0/2.2 ); +} + +vec4 gammaSRGBInverse( vec4 color ) +{ + return gamma( color, 1.0/2.2 ); +} + +vec3 desaturate( vec3 color ) +{ + vec3 weight = vec3( 1.0, 1.0, 1.0 ) / 3.0; + + float luminance = color.r * weight.r + color.g * weight.g + color.b * weight.b; + + return vec3( luminance ); +} + +vec3 desaturate( vec3 color, float amount ) +{ + return mix( color, desaturate( color ), amount ); +} + +vec4 desaturate( vec4 color ) +{ + return vec4( desaturate( color.rgb ), color.a ); +} + +vec4 desaturate( vec4 color, float amount ) +{ + return mix( color, desaturate( color ), amount ); +} + +/* BLEND MODES */ + +vec4 blendMode_alpha( vec4 bottom, vec4 top ) +{ + float fade = ( 1.0 - top.a ); + float alpha = top.a + bottom.a * fade; + + vec4 bottomPM = straightToPremultipliedColor( bottom ); + vec4 topPM = straightToPremultipliedColor( top ); + + vec3 color = topPM.rgb + bottomPM.rgb * fade; + + return vec4( color, 1 ) / alpha; +} + + +vec4 blendMode_colorHSL( vec4 bottom, vec4 top ) +{ + vec3 topHSL = RGBtoHSL( top.rgb ); + vec3 bottomHSL = RGBtoHSL( bottom.rgb ); + + vec3 resultHSL = vec3( topHSL.x, topHSL.y, bottomHSL.z ); + vec3 resultRBG = clamp( HSLtoRGB( resultHSL ), 0, 1 ); + vec4 result = bottom.a == 0.0 ? bottom : vec4( resultRBG, top.a ); + + return blendMode_alpha( bottom, result ); +} + +vec4 blendMode_colorHSL( vec4 bottom, vec4 top, float topOpacity ) +{ + vec4 blendedColor = blendMode_colorHSL( bottom, top ); + blendedColor.a *= topOpacity; + return blendMode_alpha( bottom, blendedColor ); +} + +vec4 blendMode_colorHSV( vec4 bottom, vec4 top ) +{ + vec3 topHSL = RGBtoHSV( top.rgb ); + vec3 bottomHSL = RGBtoHSV( bottom.rgb ); + + vec3 resultHSL = vec3( topHSL.x, topHSL.y, bottomHSL.z ); + vec3 resultRBG = clamp( HSVtoRGB( resultHSL ), 0, 1 ); + vec4 result = bottom.a == 0.0 ? bottom : vec4( resultRBG, top.a ); + + return blendMode_alpha( bottom, result ); +} + +vec4 blendMode_colorHSV( vec4 bottom, vec4 top, float topOpacity ) +{ + vec4 blendedColor = blendMode_colorHSV( bottom, top ); + blendedColor.a *= topOpacity; + return blendMode_alpha( bottom, blendedColor ); } \ No newline at end of file diff --git a/Runtime/Shading/Library/Depth.gdshaderinc b/Runtime/Shading/Library/Depth.gdshaderinc index 4e08152..ab7225f 100644 --- a/Runtime/Shading/Library/Depth.gdshaderinc +++ b/Runtime/Shading/Library/Depth.gdshaderinc @@ -14,12 +14,19 @@ vec3 getDepthViewPositiontAtScreen( sampler2D _depthTexture, vec2 screenUV, mat4 return screenToView( screenUV, depthValue, _INV_PROJECTION_MATRIX ).xyz; } -bool isVisibleAt( sampler2D _depthTexture, vec3 viewPosition, mat4 _PROJECTION_MATRIX, mat4 _INV_PROJECTION_MATRIX ) +vec3 getDepthViewPositionAtViewPosition( sampler2D _depthTexture, vec3 viewPosition, mat4 _PROJECTION_MATRIX, mat4 _INV_PROJECTION_MATRIX ) { vec2 screenPosition = viewToScreen( viewPosition, _PROJECTION_MATRIX ); vec3 depthViewPosition = getDepthViewPositiontAtScreen( _depthTexture, screenPosition, _INV_PROJECTION_MATRIX ); + return depthViewPosition; +} + +bool isVisibleAt( sampler2D _depthTexture, vec3 viewPosition, mat4 _PROJECTION_MATRIX, mat4 _INV_PROJECTION_MATRIX ) +{ + vec3 depthViewPosition = getDepthViewPositionAtViewPosition( _depthTexture, viewPosition, _PROJECTION_MATRIX, _INV_PROJECTION_MATRIX ); + float visible = viewPosition.z - depthViewPosition.z; return visible > 0.0; diff --git a/Runtime/Shading/Library/Fonts.gdshaderinc b/Runtime/Shading/Library/Fonts.gdshaderinc new file mode 100644 index 0000000..228c9a7 --- /dev/null +++ b/Runtime/Shading/Library/Fonts.gdshaderinc @@ -0,0 +1,107 @@ +// #include "res://addons/rokojori_action_library/Runtime/Shading/Library/Fonts.gdshaderinc" + +const int _space_ = 32; +const int _0_ = 48; +const int _1_ = 49; +const int _2_ = 50; +const int _3_ = 51; +const int _4_ = 52; +const int _5_ = 53; +const int _6_ = 54; +const int _7_ = 55; +const int _8_ = 56; +const int _9_ = 57; +const int _colon_ = 58; +const int _semicolon_ = 59; +const int _smaller_ = 60; +const int _equals_ = 61; +const int _bigger_ = 62; +const int _questionMark_ = 63; +const int _at_ = 64; +const int _A_ = 65; +const int _B_ = 66; +const int _C_ = 67; +const int _D_ = 68; +const int _E_ = 69; +const int _F_ = 70; +const int _G_ = 71; +const int _H_ = 72; +const int _I_ = 73; +const int _J_ = 74; +const int _K_ = 75; +const int _L_ = 76; +const int _M_ = 77; +const int _N_ = 78; +const int _O_ = 79; +const int _P_ = 80; +const int _Q_ = 81; +const int _R_ = 82; +const int _S_ = 83; +const int _T_ = 84; +const int _U_ = 85; +const int _V_ = 86; +const int _W_ = 87; +const int _X_ = 88; +const int _Y_ = 89; +const int _Z_ = 90; +const int _squareBracketsOpen_ = 91; +const int _backSlash_ = 92; +const int _squareBracketsClose_ = 93; +const int _triangle_ = 94; +const int ___ = 95; +const int _apostroph_ = 96; +const int _a_ = 97; +const int _b_ = 98; +const int _c_ = 99; +const int _d_ = 100; +const int _e_ = 101; +const int _f_ = 102; +const int _g_ = 103; +const int _h_ = 104; +const int _i_ = 105; +const int _j_ = 106; +const int _k_ = 107; +const int _l_ = 108; +const int _m_ = 109; +const int _n_ = 110; +const int _o_ = 111; +const int _p_ = 112; +const int _q_ = 113; +const int _r_ = 114; +const int _s_ = 115; +const int _t_ = 116; +const int _u_ = 117; +const int _v_ = 118; +const int _w_ = 119; +const int _x_ = 120; +const int _y_ = 121; +const int _z_ = 122; +const int _curlyBracketsOpen_ = 123; +const int _stroke_ = 124; +const int _curlyBracketsClose_ = 125; +const int _tilde_ = 126; + +vec3 renderMonoFontAsciiChar( sampler2D fontTable16x16, vec2 uv, int asciiCode ) +{ + int fontTableIndex = asciiCode - 32; + int fontTableX = fontTableIndex % 16; + int fontTableY = fontTableIndex / 16; + + vec2 fontTableUV = ( vec2( fontTableX, fontTableY ) + uv ) / 16.0; + + return textureLod( fontTable, fontTableUV, 0 ); +} + +vec3 renderMonoFontAsciiWord( sampler2D fontTable16x16, vec2 uv, int[] word ) +{ + int wordLength = word.length(); + float wordU = uv.x * wordLength; + + int characterIndex = int( floor( wordU ) ); + int character = word[ characterIndex ]; + + float characterU = wordU - float( characterIndex ); + + return renderMonoFontAsciiChar( fontTable16x16, vec2( characterU, uv.y ), character ); +} + diff --git a/Runtime/Shading/Library/Fonts.gdshaderinc.uid b/Runtime/Shading/Library/Fonts.gdshaderinc.uid new file mode 100644 index 0000000..32cac07 --- /dev/null +++ b/Runtime/Shading/Library/Fonts.gdshaderinc.uid @@ -0,0 +1 @@ +uid://db8micgyytpin diff --git a/Runtime/Shading/Library/Math.gdshaderinc b/Runtime/Shading/Library/Math.gdshaderinc index bf9da50..48bba43 100644 --- a/Runtime/Shading/Library/Math.gdshaderinc +++ b/Runtime/Shading/Library/Math.gdshaderinc @@ -87,4 +87,16 @@ float snapCeiled( float value, float snappingDistance ) float snapFloored( float value, float snappingDistance ) { return floor( value / snappingDistance ) * snappingDistance; +} + +float rangeAmount( float x, vec3 range) +{ + float a0 = range.x; + float a1 = range.y; + float a2 = range.z; + + float range01 = smoothstep( a0, a1, x ); + float range02 = 1.0 - smoothstep( a1, a2, x ); + + return mix( range01, range02, step( a1, x) ); } \ No newline at end of file diff --git a/Runtime/Shading/Library/Normals.gdshaderinc b/Runtime/Shading/Library/Normals.gdshaderinc new file mode 100644 index 0000000..5381e5d --- /dev/null +++ b/Runtime/Shading/Library/Normals.gdshaderinc @@ -0,0 +1,20 @@ +// #include "res://addons/rokojori_action_library/Runtime/Shading/Library/Normals.gdshaderinc" + +vec3 scaleNormalMap( vec3 normal, float scale ) +{ + normal -= vec3( 0.5 ); + normal *= scale; + normal += vec3( 0.5 ); + + return normal; +} + +vec3 addNormalMaps( vec3 a, vec3 b ) +{ + a -= vec3( 0.5 ); + b -= vec3( 0.5 ); + + vec3 result = a + b; + + return result + 0.5; +} \ No newline at end of file diff --git a/Runtime/Shading/Library/Normals.gdshaderinc.uid b/Runtime/Shading/Library/Normals.gdshaderinc.uid new file mode 100644 index 0000000..028ce95 --- /dev/null +++ b/Runtime/Shading/Library/Normals.gdshaderinc.uid @@ -0,0 +1 @@ +uid://bsyxuywet0mhj diff --git a/Runtime/Shading/Library/Textures.gdshaderinc b/Runtime/Shading/Library/Textures.gdshaderinc index 7508632..d86aca9 100644 --- a/Runtime/Shading/Library/Textures.gdshaderinc +++ b/Runtime/Shading/Library/Textures.gdshaderinc @@ -1,5 +1,72 @@ // #include "res://addons/rokojori_action_library/Runtime/Shading/Library/Textures.gdshaderinc" +vec3 sampleRGB( sampler2D sampler, vec2 uv ) +{ + return texture( sampler, uv ).rgb; +} + +vec3 sampleRGB( sampler2D sampler, vec2 uv, vec4 tint ) +{ + return texture( sampler, uv ).rgb * tint.rgb; +} + +float sampleAlphaUnclamped( sampler2D opacitySampler, sampler2D albedoSampler, vec2 uv, vec4 albedo, float scale ) +{ + float sampledOpacity = texture( opacitySampler, uv ).r; + float sampledAlpha = texture( albedoSampler, uv ).a * albedo.a; + + return sampledOpacity * sampledAlpha * scale; +} + +float sampleAlpha( sampler2D opacitySampler, sampler2D albedoSampler, vec2 uv, vec4 albedo, float scale ) +{ + float alpha = sampleAlphaUnclamped( opacitySampler, albedoSampler, uv, albedo, scale ); + + return clamp( alpha, 0, 1 ); +} + + +float sampleRedUnclamped( sampler2D sampler, vec2 uv, float scale, float offset ) +{ + float value = texture( sampler, uv ).r; + + return value * scale + offset; +} + +float sampleRedBlurredUnclamped( sampler2D sampler, vec2 uv, float scale, float offset, float blur ) +{ + float value = textureLod( sampler, uv, blur ).r; + + return value * scale + offset; +} + +float sampleRed( sampler2D sampler, vec2 uv, float scale, float offset ) +{ + float value = sampleRedUnclamped( sampler, uv, scale, offset ); + return clamp( value, 0, 1 ); +} + +vec3 sampleEmission( sampler2D sampler, vec2 uv, float emissionScale, vec4 emissionOffset ) +{ + vec3 value = texture( sampler, uv ).rgb; + + return ( value + emissionOffset.rgb ) * emissionScale; +} + +float sampleOcclusionUnclamped( sampler2D sampler, vec2 uv, float amount, float offset ) +{ + float value = texture( sampler, uv ).r; + return mix( 1, value, amount ) + offset; +} + +float sampleOcclusion( sampler2D sampler, vec2 uv, float scale, float offset ) +{ + float value = sampleOcclusionUnclamped( sampler, uv, scale, offset ); + return clamp( value, 0, 1 ); +} + + + vec4 triplanarTexture( sampler2D sampler, vec3 weights, vec3 triplanerPosition ) { vec4 sample = vec4( 0.0 ); diff --git a/Runtime/Shading/Library/Transform.gdshaderinc b/Runtime/Shading/Library/Transform.gdshaderinc index 29b6be6..bdca2ea 100644 --- a/Runtime/Shading/Library/Transform.gdshaderinc +++ b/Runtime/Shading/Library/Transform.gdshaderinc @@ -134,6 +134,11 @@ vec2 viewToScreen( vec3 view, mat4 _PROJECTION_MATRIX ) return clipToScreen( clip ); } +vec2 localToScreen( vec3 local, mat4 _MODELVIEW_MATRIX, mat4 _PROJECTION_MATRIX ) +{ + vec3 view = localToView( local, _MODELVIEW_MATRIX ); + return viewToScreen( view, _PROJECTION_MATRIX ); +} vec2 worldToScreen( vec3 world, mat4 _VIEW_MATRIX, mat4 _PROJECTION_MATRIX ) { @@ -352,6 +357,8 @@ mat3 scalePivot_m3( vec2 scale, vec2 pivot ) return translate_m3( -pivot ) * scale_m3( scale ) * translate_m3( pivot ); } + + mat3 rotate_m3( float radiansAngle ) { float c = cos( radiansAngle ); @@ -400,6 +407,11 @@ vec2 applyMatrix_m3v2( mat3 matrix, vec2 point ) return vec2( ox, oy ); } +vec2 scale( vec2 position, vec2 pivot, vec2 scale ) +{ + return applyMatrix_m3v2( scalePivot_m3( scale, pivot ), position ); +} + vec2 applyMatrixBase_m3v2( mat3 matrix, vec2 point ) { float x = point.x; diff --git a/Runtime/Shading/Library/Wind.gdshaderinc b/Runtime/Shading/Library/Wind.gdshaderinc new file mode 100644 index 0000000..5e35ad3 --- /dev/null +++ b/Runtime/Shading/Library/Wind.gdshaderinc @@ -0,0 +1,33 @@ +// #include "res://addons/rokojori_action_library/Runtime/Shading/Library/Wind.gdshaderinc" + +#include "res://addons/rokojori_action_library/Runtime/Shading/Library/Math.gdshaderinc" +#include "res://addons/rokojori_action_library/Runtime/Shading/Library/Transform.gdshaderinc" + +void applyWind( + float _TIME, + mat4 _MODEL_MATRIX, + inout vec3 _VERTEX, + float _windStrength, + vec2 _windSpeed, + float _windScale, + sampler2D _windNoise, + vec2 _windNoiseAngleOffset, + vec2 _windNoiseStrengthOffset, + float _windStart, + float _windEnd, + float _windWeightCurve, + float _windHeightCompensation + ) +{ + float _windAmount = normalizeToRange01( _VERTEX.y, _windStart, _windEnd ); + float rawWindAmount = _windAmount; + _windAmount = mix( _windAmount, _windAmount * _windAmount, _windWeightCurve ); + vec3 worldVertex = localToWorld( _VERTEX, _MODEL_MATRIX ); + vec2 _windUV = _TIME * _windSpeed + worldVertex.xz * _windScale; + float angle = texture( _windNoise, _windUV + _windNoiseAngleOffset).r * PI * 2.0; + float strength = texture( _windNoise, _windUV + _windNoiseStrengthOffset ).r * _windStrength; + vec2 circle = onCircle( angle ) * strength; + _VERTEX = worldToLocal( worldVertex + vec3( circle.x, 0, circle.y ) * _windAmount, _MODEL_MATRIX ); + float minY = min( _VERTEX.y, 0 ); + _VERTEX.y = mix( _VERTEX.y, max( minY, _VERTEX.y - strength * _windAmount), _windHeightCompensation * 4.0f ); +} \ No newline at end of file diff --git a/Runtime/Shading/Library/Wind.gdshaderinc.uid b/Runtime/Shading/Library/Wind.gdshaderinc.uid new file mode 100644 index 0000000..9d8cf7a --- /dev/null +++ b/Runtime/Shading/Library/Wind.gdshaderinc.uid @@ -0,0 +1 @@ +uid://bgd2vct1gr34o diff --git a/Runtime/Shading/Materials/CustomMaterialProperty.cs b/Runtime/Shading/Materials/CustomMaterialProperty.cs index a80e15a..400b17d 100644 --- a/Runtime/Shading/Materials/CustomMaterialProperty.cs +++ b/Runtime/Shading/Materials/CustomMaterialProperty.cs @@ -12,7 +12,7 @@ namespace Rokojori _name = n; } - CustomMaterial _material; + protected CustomMaterial _material; ShaderPropertyName _name; public S GetPropertyName() where S:ShaderPropertyName @@ -29,6 +29,16 @@ namespace Rokojori { _name._Set( _material, value ); } + + public void AssignFor( CustomMaterial material, T value ) + { + _name._Set( material, value ); + } + + public void AssignFor( List materials, T value ) + { + materials.ForEach( m => AssignFor( m, value ) ); + } } } \ No newline at end of file diff --git a/Runtime/Shading/Materials/Materials.cs b/Runtime/Shading/Materials/Materials.cs index 4175652..51e7b62 100644 --- a/Runtime/Shading/Materials/Materials.cs +++ b/Runtime/Shading/Materials/Materials.cs @@ -24,7 +24,22 @@ namespace Rokojori return 1; } - public static List GetAll( Node node, int index = 0 ) where M:Material + public static List ResolveNextPasses( Material material ) + { + var list = new List(); + + var it = material; + + while ( it != null ) + { + list.Add( it ); + it = it.NextPass; + } + + return list; + } + + public static List GetAll( Node node ) where M:Material { var list = new List(); @@ -32,7 +47,7 @@ namespace Rokojori for ( int i = 0; i < count; i++ ) { - list.Add( Get( node, index ) ); + list.Add( Get( node, i ) ); } return list; @@ -196,10 +211,13 @@ namespace Rokojori return; } - GetLastMaterial( gi.MaterialOverlay ).NextPass = material; + GetLastMaterial( gi.MaterialOverlay ).NextPass = material; + + return; } + } public static void RemoveOverlay( Node node, Material material, bool forceTop = true ) diff --git a/Runtime/Shading/Properties/ColorPropertyName.cs b/Runtime/Shading/Properties/ColorPropertyName.cs index 5747247..dea289f 100644 --- a/Runtime/Shading/Properties/ColorPropertyName.cs +++ b/Runtime/Shading/Properties/ColorPropertyName.cs @@ -8,6 +8,8 @@ namespace Rokojori [GlobalClass] public partial class ColorPropertyName : ShaderPropertyName { + public static readonly ColorPropertyName albedo = Create( "albedo" ); + public void Set( Material material, Color value ) { _Set( material, value ); diff --git a/Runtime/Shading/Properties/Properties/ColorProperty.cs b/Runtime/Shading/Properties/Properties/ColorProperty.cs index 1fa0a97..0b5e1d0 100644 --- a/Runtime/Shading/Properties/Properties/ColorProperty.cs +++ b/Runtime/Shading/Properties/Properties/ColorProperty.cs @@ -19,6 +19,11 @@ namespace Rokojori propertyName.Set( material, color ); } + public void ReadFrom( Material material ) + { + color = propertyName.Get( material ); + } + public void ApplyLerped( Material material, Color from, float lerpState ) { var lerpedColor = from.Lerp( color, lerpState ); diff --git a/Runtime/Shading/Properties/Properties/FloatProperty.cs b/Runtime/Shading/Properties/Properties/FloatProperty.cs index 7072822..98d2b19 100644 --- a/Runtime/Shading/Properties/Properties/FloatProperty.cs +++ b/Runtime/Shading/Properties/Properties/FloatProperty.cs @@ -19,6 +19,11 @@ namespace Rokojori propertyName.Set( material, value ); } + public void ReadFrom( Material material ) + { + value = propertyName.Get( material ); + } + public void ApplyLerped( Material material, float from, float lerpState ) { var lerpedValue = Mathf.Lerp( from, value, lerpState ); diff --git a/Runtime/Shading/Properties/Properties/Vector2Property.cs b/Runtime/Shading/Properties/Properties/Vector2Property.cs new file mode 100644 index 0000000..4cc4821 --- /dev/null +++ b/Runtime/Shading/Properties/Properties/Vector2Property.cs @@ -0,0 +1,43 @@ +using Godot; +using System.Reflection; +using System.Collections.Generic; + +namespace Rokojori +{ + [Tool] + [GlobalClass] + public partial class Vector2Property : ShaderProperty + { + [Export] + public Vector2PropertyName propertyName; + + public string name => propertyName.propertyName; + + [Export] + public Vector2 value; + + public override void Apply( Material material ) + { + propertyName.Set( material, value ); + } + + public void ReadFrom( Material material ) + { + value = propertyName.Get( material ); + } + + public void ApplyLerped( Material material, Vector2 from, float lerpState ) + { + var lerpedValue = Math2D.Lerp( from, value, lerpState ); + propertyName.Set( material, lerpedValue ); + } + + public static Vector2Property Create( string name, Vector2 value ) + { + var fp = new Vector2Property(); + fp.propertyName = Vector2PropertyName.Create( name ); + fp.value = value; + return fp; + } + } +} \ No newline at end of file diff --git a/Runtime/Shading/Properties/Properties/Vector2Property.cs.uid b/Runtime/Shading/Properties/Properties/Vector2Property.cs.uid new file mode 100644 index 0000000..c04eed8 --- /dev/null +++ b/Runtime/Shading/Properties/Properties/Vector2Property.cs.uid @@ -0,0 +1 @@ +uid://colw2dxvhfkxy diff --git a/Runtime/Shading/Properties/Texture2DPropertyName.cs b/Runtime/Shading/Properties/Texture2DPropertyName.cs index 6ee42c8..e1677e9 100644 --- a/Runtime/Shading/Properties/Texture2DPropertyName.cs +++ b/Runtime/Shading/Properties/Texture2DPropertyName.cs @@ -8,6 +8,7 @@ namespace Rokojori [GlobalClass] public partial class Texture2DPropertyName : ShaderPropertyName { + public static Texture2DPropertyName albedoTexture = Create( "albedo_texture" ); public void Set( Material material, Texture2D value ) { diff --git a/Runtime/Shading/Shaders/Depth/DepthDistanceAlpha.gdshader b/Runtime/Shading/Shaders/Depth/DepthDistanceAlpha.gdshader new file mode 100644 index 0000000..a86b136 --- /dev/null +++ b/Runtime/Shading/Shaders/Depth/DepthDistanceAlpha.gdshader @@ -0,0 +1,47 @@ +// NOTE: Shader automatically converted from Godot Engine 4.4.stable.mono's StandardMaterial3D. + +shader_type spatial; +render_mode blend_mix, depth_draw_never, cull_back, diffuse_burley, specular_schlick_ggx, depth_test_disabled; + +#include "res://addons/rokojori_action_library/Runtime/Shading/Library/Depth.gdshaderinc" + +uniform vec4 albedo : source_color; +uniform sampler2D albedoTexture : source_color, filter_linear_mipmap, repeat_enable; +uniform sampler2D opacityTexture : source_color, filter_linear_mipmap, repeat_enable; +uniform sampler2D depthTexture: hint_depth_texture; + +uniform vec3 uv1_scale; +uniform vec3 uv1_offset; + +uniform bool checkVisible = false; +uniform float visibilityDistance = 1; +uniform float visibilityDistanceScale = 0.01; + +void vertex() +{ + UV = UV * uv1_scale.xy + uv1_offset.xy; +} + +void fragment() +{ + vec3 viewPosition = VERTEX; + + bool visible = isVisibleAt( depthTexture, viewPosition, PROJECTION_MATRIX, INV_PROJECTION_MATRIX ); + + if ( checkVisible && ! visible ) + { + discard; + } + + vec3 depthViewPosition = getDepthViewPositionAtViewPosition( depthTexture, viewPosition, PROJECTION_MATRIX, INV_PROJECTION_MATRIX ); + float dist = length( depthViewPosition - viewPosition ); + + float dVis = 1.0 - clamp( dist / ( visibilityDistance * visibilityDistanceScale ), 0, 1 ); + + + vec4 sampledAlbedo = texture( albedoTexture, UV ); + vec4 sampledOpacity = texture( opacityTexture, UV ); + + ALBEDO = albedo.rgb * sampledAlbedo.rgb; + ALPHA *= albedo.a * sampledAlbedo.a * sampledOpacity.r * dVis; +} diff --git a/Runtime/Shading/Shaders/Depth/DepthDistanceAlpha.gdshader.uid b/Runtime/Shading/Shaders/Depth/DepthDistanceAlpha.gdshader.uid new file mode 100644 index 0000000..e08f55e --- /dev/null +++ b/Runtime/Shading/Shaders/Depth/DepthDistanceAlpha.gdshader.uid @@ -0,0 +1 @@ +uid://cpgxwdg2n2spo diff --git a/Runtime/Shading/Shaders/Depth/DepthScissorWrite.gdshader b/Runtime/Shading/Shaders/Depth/DepthScissorWrite.gdshader new file mode 100644 index 0000000..99611ae --- /dev/null +++ b/Runtime/Shading/Shaders/Depth/DepthScissorWrite.gdshader @@ -0,0 +1,31 @@ +// NOTE: Shader automatically converted from Godot Engine 4.4.stable.mono's StandardMaterial3D. + +shader_type spatial; +render_mode blend_mix, depth_draw_always, cull_disabled, unshaded; + +uniform vec4 albedo : source_color; +uniform sampler2D texture_albedo : source_color, filter_linear_mipmap, repeat_enable; +uniform float treshold:hint_range(0,1) = 0.1; + +uniform vec3 uv1_scale; +uniform vec3 uv1_offset; +uniform float grow; + +void vertex() +{ + UV = UV * uv1_scale.xy + uv1_offset.xy; + VERTEX += NORMAL * grow; +} + +void fragment() +{ + vec4 opacity = texture( texture_albedo, UV ); + + if ( opacity.r < treshold ) + { + discard; + } + + ALBEDO = albedo.rgb; + //ALPHA = albedo.a; +} diff --git a/Runtime/Shading/Shaders/Depth/DepthScissorWrite.gdshader.uid b/Runtime/Shading/Shaders/Depth/DepthScissorWrite.gdshader.uid new file mode 100644 index 0000000..df37bb5 --- /dev/null +++ b/Runtime/Shading/Shaders/Depth/DepthScissorWrite.gdshader.uid @@ -0,0 +1 @@ +uid://cc51lxupwf6h diff --git a/Runtime/Shading/Tools/DebugCompositor/debug-compositor-font-table.svg b/Runtime/Shading/Tools/DebugCompositor/debug-compositor-font-table.svg new file mode 100644 index 0000000..fdff0d2 --- /dev/null +++ b/Runtime/Shading/Tools/DebugCompositor/debug-compositor-font-table.svg @@ -0,0 +1,2218 @@ + + + + !"#$%&'()*+,-./ +0123456789:;<=>? +@ABCDEFGHIJKLMNO +PQRSTUVWXYZ[\]^_ +`abcdefghijklmno +pqrstuvwxyz{|}~ diff --git a/Runtime/Shading/Tools/DebugCompositor/debug-compositor-font-table.svg.import b/Runtime/Shading/Tools/DebugCompositor/debug-compositor-font-table.svg.import new file mode 100644 index 0000000..c89a132 --- /dev/null +++ b/Runtime/Shading/Tools/DebugCompositor/debug-compositor-font-table.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://x83iyeafv0ao" +path="res://.godot/imported/debug-compositor-font-table.svg-90d2dfaed765a7ea1b519bce11e172cb.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/rokojori_action_library/Runtime/Shading/Tools/DebugCompositor/debug-compositor-font-table.svg" +dest_files=["res://.godot/imported/debug-compositor-font-table.svg-90d2dfaed765a7ea1b519bce11e172cb.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/Runtime/Text/JSON/JSONArray.cs b/Runtime/Text/JSON/JSONArray.cs index bd5f494..03c27f8 100644 --- a/Runtime/Text/JSON/JSONArray.cs +++ b/Runtime/Text/JSON/JSONArray.cs @@ -33,6 +33,13 @@ namespace Rokojori _values.RemoveAt( index ); } + public List AsFloatList() + { + var list = new List(); + values.ForEach( v => list.Add( (float) v.numberValue ) ); + return list; + } + public void Push( JSONData value ) {_values.Add( value );} public void Push( string value ) { Push( new JSONValue( value ) ); } @@ -60,7 +67,7 @@ namespace Rokojori public JSONData Pop() { - return Lists.Pop( _values ); + return Lists.PopLast( _values ); } public override string Stringify( StringifyOptions options ) diff --git a/Runtime/Text/JSON/JSONObject.cs b/Runtime/Text/JSON/JSONObject.cs index 6b9b6ba..d1f60a6 100644 --- a/Runtime/Text/JSON/JSONObject.cs +++ b/Runtime/Text/JSON/JSONObject.cs @@ -33,12 +33,73 @@ namespace Rokojori return index == -1 ? null : _values[ index ]; } + public bool HasKey( string key ) + { + return keys.IndexOf( key ) != -1; + } + public string GetString( string key ){ return Get( key ).stringValue; } public double GetNumber( string key ){ return Get( key ).numberValue; } public int GetInt( string key ){ return Get( key ).intValue; } public float GetFloat( string key ){ return Get( key ).floatValue; } public bool GetBoolean( string key ){ return Get( key ).booleanValue; } + public T ByPath( params string[] path) where T:JSONData + { + JSONData it = this; + + for ( int i = 0; i < path.Length; i++ ) + { + var isLast = i == ( path.Length - 1 ); + + if ( ! ( isLast || it.dataType == JSONDataType.OBJECT || it.dataType == JSONDataType.ARRAY ) ) + { + return null; + } + + if ( it.dataType == JSONDataType.OBJECT ) + { + it = ( (JSONObject)it ).Get( path[ i ] ); + } + else if ( it.dataType == JSONDataType.ARRAY ) + { + var index = RegexUtility.ParseInt( path[ i ], -1 ); + it = ( (JSONArray) it ).Get( index ); + } + + if ( it == null ) + { + return null; + } + } + + return it as T; + } + + public JSONObject GetObject( string key ) + { + var data = Get( key ); + + if ( data == null ) + { + return null; + } + + return data.AsObject(); + } + + public JSONArray GetArray( string key ) + { + var data = Get( key ); + + if ( data == null ) + { + return null; + } + + return data.AsArray(); + } + public T GetEnum( string key ) { var value = System.Enum.Parse( typeof( T ), GetString( key ) ); diff --git a/Runtime/Text/JSON/JSONParser.cs b/Runtime/Text/JSON/JSONParser.cs index befcf98..78273f2 100644 --- a/Runtime/Text/JSON/JSONParser.cs +++ b/Runtime/Text/JSON/JSONParser.cs @@ -146,8 +146,8 @@ namespace Rokojori case LexerType.ARRAY_END: case LexerType.OBJECT_END: { - Lists.Pop( stack ); - current = Lists.Last( stack ); + Lists.PopLast( stack ); + current = Lists.GetLast( stack ); if ( current is JSONArray ) { diff --git a/Runtime/Text/RegexUtility.cs b/Runtime/Text/RegexUtility.cs index 4c12801..2c01d79 100644 --- a/Runtime/Text/RegexUtility.cs +++ b/Runtime/Text/RegexUtility.cs @@ -6,6 +6,7 @@ using System; using System.Globalization; using Godot; +using System.Linq; namespace Rokojori { @@ -18,6 +19,83 @@ namespace Rokojori return new Regex( source, regex.Options ); } + public static string Indent( this string value, string indentation = " ", bool indentFirstLine = true ) + { + var lines = SplitLines( value ); + + var ignoreFirstLine = ! indentFirstLine; + + var linesBefore = lines; + lines = RemoveIntendation( lines ); + + var indentedLines = lines.Map( + l => + { + + if ( ignoreFirstLine ) + { + ignoreFirstLine = false; + return l; + } + else + { + return indentation + l; + } + + + } + ); + + return indentedLines.Join( "\n" ); + } + + public static List RemoveIntendation( string value ) + { + return RemoveIntendation( SplitLines( value ) ); + } + + public static List RemoveIntendation( List lines ) + { + var initial = 1000000; + + var numSpaces = initial; + + for ( int i = 0; i < lines.Count; i++ ) + { + if ( IsNullOrWhiteSpace( lines[ i ] ) ) + { + continue; + } + + numSpaces = Mathf.Min( numSpaces, MatchLength( lines[ i ], @"^\s+" ) ); + } + + if ( numSpaces == initial || numSpaces <= 0 ) + { + return lines; + } + + var outputLines = lines.Map( + ( l )=> + { + if ( IsNullOrWhiteSpace( l ) ) + { + return ""; + } + + return l.Substring( numSpaces ); + } + ); + + + return outputLines; + } + + public static bool IsNullOrWhiteSpace( string s ) + { + return string.IsNullOrWhiteSpace( s ); + } + public static string MakeSourceSticky( string source ) { if ( ! source.StartsWith( "\\G" ) ) @@ -61,6 +139,18 @@ namespace Rokojori return "0"; } + public static string _G( this float value ) + { + var stringValue = NumberToString( value ); + + if ( ! stringValue.Contains( "." ) ) + { + stringValue += ".0"; + } + + return stringValue; + } + public static string _F( this float value ) { return value.ToString( "0.0", CultureInfo.InvariantCulture ); @@ -76,6 +166,26 @@ namespace Rokojori return value.ToString( "0.000", CultureInfo.InvariantCulture ); } + public static string _DDD( this double value ) + { + return value.ToString( "0.000", CultureInfo.InvariantCulture ); + } + + public static string _M( this float meters ) + { + return _FF( meters ) + "m"; + } + + public static string _CM( this float meters ) + { + return _FF( meters * 100 ) + "cm"; + } + + public static string _KM( this float meters ) + { + return _FF( meters / 1000 ) + "km"; + } + public static double ParseDouble( string source, double alternative = 0 ) @@ -166,6 +276,19 @@ namespace Rokojori return new Regex( regex, options ).Match( source ).Success; } + public static int MatchLength( string source, string regex, RegexOptions options = RegexOptions.None, int start = 0 ) + { + var match = new Regex( regex, options ).Match( source, start ); + + if ( ! match.Success ) + { + return 0; + } + + return match.Length; + + } + public static bool MatchingIgnoreCase( string source, string regex ) { return Matching( source, regex, RegexOptions.IgnoreCase ); @@ -430,10 +553,7 @@ namespace Rokojori public static List SplitLines( string source ) { - var array = Regex.Split( source, "\r\n|\r|\n" ); - var list = new List(); - list.AddRange( array ); - return list; + return Regex.Split( source, "\r\n|\r|\n" ).ToList(); } public static string Remove( string source, string regex ) @@ -468,6 +588,24 @@ namespace Rokojori return replaced; } + public static string UpperCaseAndWide( string source ) + { + var sb = new StringBuilder(); + + for ( int i = 0; i < source.Length; i++ ) + { + if ( i != 0 ) + { + sb.Append( " " ); + } + + sb.Append( ( source[ i ] + "" ).ToUpper() ); + + } + + return sb.ToString(); + } + public static string TrimToLastPathFragment( string path ) { var splits = SplitPaths( path ); diff --git a/Runtime/Time/ModulateTimeLineSpeed.cs b/Runtime/Time/ModulateTimeLineSpeed.cs index 78fbe35..0c57bde 100644 --- a/Runtime/Time/ModulateTimeLineSpeed.cs +++ b/Runtime/Time/ModulateTimeLineSpeed.cs @@ -4,7 +4,7 @@ using Godot; namespace Rokojori { - [GlobalClass ] + [Tool][GlobalClass ] public partial class ModulateTimeLineSpeed : SequenceAction { [Export] diff --git a/Runtime/Time/SetTimeLineSpeed.cs b/Runtime/Time/SetTimeLineSpeed.cs index 867f9e2..9671f2f 100644 --- a/Runtime/Time/SetTimeLineSpeed.cs +++ b/Runtime/Time/SetTimeLineSpeed.cs @@ -4,7 +4,7 @@ using Godot; namespace Rokojori { - [GlobalClass ] + [Tool][GlobalClass ] public partial class SetTimeLineSpeed : Action { [Export] diff --git a/Runtime/Tools/Arrays.cs b/Runtime/Tools/Arrays.cs index 3be0f59..557bdc4 100644 --- a/Runtime/Tools/Arrays.cs +++ b/Runtime/Tools/Arrays.cs @@ -5,7 +5,7 @@ using System; namespace Rokojori { - public class Arrays + public static class Arrays { public static T[] Concat( T[] a, T[] b ) { @@ -17,7 +17,7 @@ namespace Rokojori return o; } - public static int IndexOf( T[] values, T other ) + public static int IndexOf( this T[] values, T other ) { return Array.IndexOf( values, other ); } @@ -65,6 +65,21 @@ namespace Rokojori return Array.IndexOf( values, other ) != -1; } + public static bool ContainsAll( T[] values, T[] other ) + { + for ( int i = 0; i < other.Length; i++ ) + { + if ( ! Contains( values, other[ i ] ) ) + { + return false; + } + } + + return true; + } + + + public static bool ContainsEqual( T[] values, T other ) { for ( int i = 0; i < values.Length; i++ ) @@ -78,7 +93,7 @@ namespace Rokojori return false; } - public static T[] Add( T[] values, T other ) + public static T[] AddEntry( T[] values, T other ) { var newValues = new T[ values.Length + 1 ]; @@ -88,6 +103,11 @@ namespace Rokojori return newValues; } + public static T[] Add( this T[] values, T other ) + { + return AddEntry( values, other ); + } + public static T[] RemoveIndex( T[] values, int index ) { if ( index <= -1 || index >= values.Length ) @@ -117,7 +137,7 @@ namespace Rokojori } - public static void ForEach( T[] values, Action callback ) + public static void ForEach( this T[] values, Action callback ) { foreach ( var it in values ) { diff --git a/Runtime/Tools/Async.cs b/Runtime/Tools/Async.cs index 647ad46..0f62720 100644 --- a/Runtime/Tools/Async.cs +++ b/Runtime/Tools/Async.cs @@ -25,6 +25,30 @@ namespace Rokojori return Time.GetTicksMsec() / 1000.0; } + + public static double GetTimeMS() + { + return Time.GetTicksMsec(); + } + + public static double PrintAndUpdateMS( double ms, string info = null ) + { + var now = GetTimeMS(); + var elapsed = now - ms; + + if ( info != null && info != "" ) + { + RJLog.Log( "Info:", info, "| Elapsed:", elapsed._DDD(), "Time:", now._DDD() ); + } + else + { + RJLog.Log( "| Elapsed:", elapsed._DDD(), "Time:", now._DDD() ); + } + + + return now; + } + public static async Task WaitIfExceeded( double last, double waitTime = Async.waitTime ) { var now = Time.GetTicksMsec() / 1000.0; diff --git a/Runtime/Tools/Boxed/FloatValue.cs b/Runtime/Tools/Boxed/FloatValue.cs index d92aac4..9f11fba 100644 --- a/Runtime/Tools/Boxed/FloatValue.cs +++ b/Runtime/Tools/Boxed/FloatValue.cs @@ -26,6 +26,11 @@ namespace Rokojori return fv; } + public static FloatValue Create( double value ) + { + return Create( (float) value ); + } + public static FloatValue Clone( FloatValue value, bool deepClone ) { if ( deepClone ) diff --git a/Runtime/Tools/Dictionaries.cs b/Runtime/Tools/Dictionaries.cs index fd22d1f..973599f 100644 --- a/Runtime/Tools/Dictionaries.cs +++ b/Runtime/Tools/Dictionaries.cs @@ -21,5 +21,7 @@ namespace Rokojori list.ForEach( k => dictionary.Remove( k ) ); } + + } } \ No newline at end of file diff --git a/Runtime/Tools/Lists.cs b/Runtime/Tools/Lists.cs index 1a6498a..58eef5c 100644 --- a/Runtime/Tools/Lists.cs +++ b/Runtime/Tools/Lists.cs @@ -7,6 +7,45 @@ using Godot; namespace Rokojori { + public class ListView + { + List _list; + int _offset; + int _length; + + public ListView( List list, int offset, int length ) + { + _list = list; + _offset = offset; + _length = length; + } + + public T this[ int index ] + { + get => _list[ index - _offset ]; + set => _list[ index - _offset ] = value; + } + + public int Count => _length; + + public void ForEach( Action action ) + { + for ( int i = 0; i < _length; i++ ) + { + action( this[ i ] ); + } + } + + public List GetList() + { + return _list; + } + + public List SubList() + { + return _list.Sub( _offset, _length ); + } + } public static class Lists { @@ -47,7 +86,8 @@ namespace Rokojori } - public static List Clone( List data ) + + public static List Clone( this List data ) { if ( data == null ) { @@ -252,6 +292,72 @@ namespace Rokojori return list; } + public static int Size( List list ) + { + return list == null ? 0 : list.Count; + } + + public static List Sub( this List elements, int start, int length = 0 ) + { + var end = length == 0 ? elements.Count : ( start + length ); + + + var list = new List( end - start ); + + for ( int i = start; i < end; i++ ) + { + list.Add( elements[ i ] ); + } + + return list; + } + + public static void ShuffleMultiple( this List list, int numShuffles, int step = 2 ) + { + for ( int i = 0; i < numShuffles; i++ ) + { + list.Shuffle( step ); + } + } + + public static ListView View( this List list, int start = 0, int length = 0 ) + { + return new ListView( list, start, length == 0 ? ( list.Count - start ) : length); + } + + + + public static void Shuffle( this List list, int step = 2 ) + { + + var listStart = new List(); + var listEnd = new List(); + + for ( int i = 0; i < list.Count; i++ ) + { + if ( i % step == 0 ) + { + listStart.Add( list[ i ] ); + } + else + { + listEnd.Add( list[ i ] ); + } + + } + + list.Clear(); + + list.Add( listStart ).Add( listEnd ); + } + + public static List Add( this List list, List other ) + { + list.AddRange( other ); + return list; + } + + public static List ToList( T[] array ) { var list = new List(); @@ -286,7 +392,7 @@ namespace Rokojori return RemoveAt( list, list.Count - 1 ); } - public static T Pop( List list ) + public static T PopLast( List list ) { if ( list.Count == 0 ){ return default(T); } @@ -295,11 +401,44 @@ namespace Rokojori return element; } - public static T Last( List list ) + public static T Pop( this List list ) + { + return PopLast( list ); + } + + public static T Shift( this List list ) + { + if ( list.Count == 0 ){ return default(T); } + + var element = list[ 0 ]; + list.RemoveAt( 0 ); + return element; + + } + + public static List Create( int size, Func initializer ) + { + var list = new List(); + + for ( int i = 0; i < size; i++ ) + { + list.Add( initializer( i ) ); + } + + return list; + } + + + public static T GetLast( List list ) { return list.Count == 0 ? default(T) : list[ list.Count - 1 ]; } + public static T Last( this List list ) + { + return GetLast( list ); + } + public static void RemoveIncreasingSortedIndices( List list, List increasinglySortedRemovals ) { for ( var i = increasinglySortedRemovals.Count - 1; i >= 0; i-- ) @@ -396,7 +535,7 @@ namespace Rokojori }*/ - public static string Join( List array, string seperator = ", " ) + public static string Join( this List array, string seperator = ", " ) { var sb = new StringBuilder(); @@ -475,6 +614,25 @@ namespace Rokojori } } + public static List Filter( this List list, Func filter ) + { + var filteredList = new List(); + Filter( list, filteredList, filter ); + return filteredList; + } + + public static List Filter( this List list, Func filter ) + { + var filteredList = new List(); + Filter( list, filteredList, filter ); + return filteredList; + } + + public static List FilterNulls( this List list ) + { + return Filter( list, e => e != null ); + } + public static void Filter( List inputList, List list, Func filter ) { for ( int i = 0; i < inputList.Count; i++ ) @@ -486,7 +644,7 @@ namespace Rokojori } } - public static List Filter( List inputList, Func filter ) + public static List FilterWith( List inputList, Func filter ) { var list = new List(); @@ -501,6 +659,7 @@ namespace Rokojori return list; } + public static List FilterType( List inputList ) where R:T { var list = new List(); @@ -521,11 +680,18 @@ namespace Rokojori return list; } - public static void Add( List list, params T[] entries ) + public static void Add( this List list, params T[] entries ) { list.AddRange( entries ); } + public static List Concat( this List list, params T[] entries ) + { + list.AddRange( entries ); + + return list; + } + public static void Insert( List list, T item, int index ) { if ( index >= list.Count ) @@ -552,7 +718,16 @@ namespace Rokojori return default( T ); } - + public static List Map( this List list, Func mapper ) + { + return Map( list, mapper, new List() ); + } + + public static List Map( this List list, Func mapper ) + { + return Map( list, mapper, new List() ); + } + public static List Map( List inputList, Func mapper, List list = null ) { if ( list == null ) diff --git a/Runtime/Tools/ReflectionHelper.cs b/Runtime/Tools/ReflectionHelper.cs index 775a7b6..a925095 100644 --- a/Runtime/Tools/ReflectionHelper.cs +++ b/Runtime/Tools/ReflectionHelper.cs @@ -26,6 +26,16 @@ namespace Rokojori } + public static TEnum StringToEnum( string value ) where TEnum : struct, Enum + { + return (TEnum) (object) ( Enum.TryParse(value, false, out var result) ? result : (TEnum?) null ); + } + + public static TEnum StringToEnum( string value, TEnum fallback ) where TEnum : struct, Enum + { + return (TEnum) (object) ( Enum.TryParse(value, false, out var result) ? result : fallback ); + } + public static int GetEnumSizeInBits( Type enumType ) { if ( ! enumType.IsEnum ) diff --git a/Runtime/UI/MouseModeTool.cs b/Runtime/UI/MouseModeTool.cs index aa1527a..80f113b 100644 --- a/Runtime/UI/MouseModeTool.cs +++ b/Runtime/UI/MouseModeTool.cs @@ -4,7 +4,7 @@ using System; namespace Rokojori { - [GlobalClass] + [Tool][GlobalClass] public partial class MouseModeTool : Node { public enum EditMode diff --git a/Runtime/UI/Nodes/UIImage.cs b/Runtime/UI/Nodes/UIImage.cs index 81f336d..08890b0 100644 --- a/Runtime/UI/Nodes/UIImage.cs +++ b/Runtime/UI/Nodes/UIImage.cs @@ -90,7 +90,7 @@ namespace Rokojori { shaderUINumber = new ShaderUINumber(); shaderUINumber.floatPropertyName = name; - numberProperties = Arrays.Add( numberProperties, shaderUINumber ); + numberProperties = Arrays.AddEntry( numberProperties, shaderUINumber ); } shaderUINumber.number = number; @@ -136,7 +136,7 @@ namespace Rokojori { shaderUIColor = new ShaderUIColor(); shaderUIColor.colorPropertyName = name; - colorProperties = Arrays.Add( colorProperties, shaderUIColor ); + colorProperties = Arrays.AddEntry( colorProperties, shaderUIColor ); } shaderUIColor.color = color; diff --git a/Runtime/VirtualCameras/CameraSlotSelectors/CameraSlotSelector.cs b/Runtime/VirtualCameras/CameraSlotSelectors/CameraSlotSelector.cs new file mode 100644 index 0000000..df8cd40 --- /dev/null +++ b/Runtime/VirtualCameras/CameraSlotSelectors/CameraSlotSelector.cs @@ -0,0 +1,25 @@ + +using System.Diagnostics; +using System.Collections; +using System.Collections.Generic; +using System; +using Godot; + + +namespace Rokojori +{ + [Tool] + [GlobalClass, Icon("res://addons/rokojori_action_library/Icons/SetActiveVirtualCamera3D.svg") ] + public partial class CameraSlotSelector:Action + { + public virtual VirtualCamera3DSlot GetCameraSlot() + { + return VirtualCamera3DManager.Get().activeSlot; + } + + protected override void _OnTrigger() + { + VirtualCamera3DManager.Get().SetActiveSlot( GetCameraSlot() ); + } + } +} \ No newline at end of file diff --git a/Runtime/VirtualCameras/CameraSlotSelectors/CameraSlotSelector.cs.uid b/Runtime/VirtualCameras/CameraSlotSelectors/CameraSlotSelector.cs.uid new file mode 100644 index 0000000..7ae7aef --- /dev/null +++ b/Runtime/VirtualCameras/CameraSlotSelectors/CameraSlotSelector.cs.uid @@ -0,0 +1 @@ +uid://c4p70ngvwt4e5 diff --git a/Runtime/VirtualCameras/CameraSlotSelectors/SetActiveCamera.cs b/Runtime/VirtualCameras/CameraSlotSelectors/SetActiveCamera.cs new file mode 100644 index 0000000..2f69621 --- /dev/null +++ b/Runtime/VirtualCameras/CameraSlotSelectors/SetActiveCamera.cs @@ -0,0 +1,38 @@ + +using System.Diagnostics; +using System.Collections; +using System.Collections.Generic; +using System; +using Godot; + + +namespace Rokojori +{ + [Tool] + [GlobalClass] + public partial class SetActiveCamera:CameraSlotSelector + { + [Export] + public VirtualCamera3D virtualCamera; + + [Export] + public bool createSlotIfNotPresent = true; + + public override VirtualCamera3DSlot GetCameraSlot() + { + var vm = VirtualCamera3DManager.Get(); + var slot = vm.GetSlot( virtualCamera ); + + if ( slot == null ) + { + slot = vm.CreateChild(); + slot.camera = virtualCamera; + + vm.RefreshSlots(); + } + + return slot; + } + + } +} \ No newline at end of file diff --git a/Runtime/VirtualCameras/CameraSlotSelectors/SetActiveCamera.cs.uid b/Runtime/VirtualCameras/CameraSlotSelectors/SetActiveCamera.cs.uid new file mode 100644 index 0000000..444e1bd --- /dev/null +++ b/Runtime/VirtualCameras/CameraSlotSelectors/SetActiveCamera.cs.uid @@ -0,0 +1 @@ +uid://bkrqg4nf7v4u0 diff --git a/Runtime/VirtualCameras/CameraSlotSelectors/SetActiveCameraSlot.cs b/Runtime/VirtualCameras/CameraSlotSelectors/SetActiveCameraSlot.cs new file mode 100644 index 0000000..aaaa45c --- /dev/null +++ b/Runtime/VirtualCameras/CameraSlotSelectors/SetActiveCameraSlot.cs @@ -0,0 +1,24 @@ + +using System.Diagnostics; +using System.Collections; +using System.Collections.Generic; +using System; +using Godot; + + +namespace Rokojori +{ + [Tool] + [GlobalClass] + public partial class SetActiveCameraSlot:CameraSlotSelector + { + [Export] + public VirtualCamera3DSlot slot; + + public override VirtualCamera3DSlot GetCameraSlot() + { + return slot; + } + + } +} \ No newline at end of file diff --git a/Runtime/VirtualCameras/CameraSlotSelectors/SetActiveCameraSlot.cs.uid b/Runtime/VirtualCameras/CameraSlotSelectors/SetActiveCameraSlot.cs.uid new file mode 100644 index 0000000..687d09a --- /dev/null +++ b/Runtime/VirtualCameras/CameraSlotSelectors/SetActiveCameraSlot.cs.uid @@ -0,0 +1 @@ +uid://bnbakwbwmnar6 diff --git a/Runtime/VirtualCameras/CameraSlotSelectors/SetActiveCameraSlotByFlags.cs b/Runtime/VirtualCameras/CameraSlotSelectors/SetActiveCameraSlotByFlags.cs new file mode 100644 index 0000000..7f1d1c3 --- /dev/null +++ b/Runtime/VirtualCameras/CameraSlotSelectors/SetActiveCameraSlotByFlags.cs @@ -0,0 +1,25 @@ + +using System.Diagnostics; +using System.Collections; +using System.Collections.Generic; +using System; +using Godot; + + +namespace Rokojori +{ + [Tool] + [GlobalClass] + public partial class SetActiveCameraSlotByFlags:CameraSlotSelector + { + [Export] + public SelectorFlag[] flags; + + public override VirtualCamera3DSlot GetCameraSlot() + { + var slot = VirtualCamera3DManager.Get().GetSlot( flags ); + return slot; + } + + } +} \ No newline at end of file diff --git a/Runtime/VirtualCameras/CameraSlotSelectors/SetActiveCameraSlotByFlags.cs.uid b/Runtime/VirtualCameras/CameraSlotSelectors/SetActiveCameraSlotByFlags.cs.uid new file mode 100644 index 0000000..bf37eb8 --- /dev/null +++ b/Runtime/VirtualCameras/CameraSlotSelectors/SetActiveCameraSlotByFlags.cs.uid @@ -0,0 +1 @@ +uid://vqkycrg1jo2m diff --git a/Runtime/VirtualCameras/CameraSlotSelectors/SetActiveCameraSlotIndex.cs b/Runtime/VirtualCameras/CameraSlotSelectors/SetActiveCameraSlotIndex.cs new file mode 100644 index 0000000..c43e0c7 --- /dev/null +++ b/Runtime/VirtualCameras/CameraSlotSelectors/SetActiveCameraSlotIndex.cs @@ -0,0 +1,25 @@ + +using System.Diagnostics; +using System.Collections; +using System.Collections.Generic; +using System; +using Godot; + + +namespace Rokojori +{ + [Tool] + [GlobalClass] + public partial class SetActiveCameraSlotIndex:CameraSlotSelector + { + [Export] + public int cameraSlotIndex; + + public override VirtualCamera3DSlot GetCameraSlot() + { + var slot = VirtualCamera3DManager.Get().GetSlot( cameraSlotIndex ); + return slot; + } + + } +} \ No newline at end of file diff --git a/Runtime/VirtualCameras/CameraSlotSelectors/SetActiveCameraSlotIndex.cs.uid b/Runtime/VirtualCameras/CameraSlotSelectors/SetActiveCameraSlotIndex.cs.uid new file mode 100644 index 0000000..8a8219c --- /dev/null +++ b/Runtime/VirtualCameras/CameraSlotSelectors/SetActiveCameraSlotIndex.cs.uid @@ -0,0 +1 @@ +uid://rbglcsb8suif diff --git a/Runtime/VirtualCameras/Effects/Presets/Earth Quake.tres b/Runtime/VirtualCameras/Effects/Presets/Earth Quake.tres new file mode 100644 index 0000000..a076b92 --- /dev/null +++ b/Runtime/VirtualCameras/Effects/Presets/Earth Quake.tres @@ -0,0 +1,44 @@ +[gd_resource type="Resource" script_class="CameraEffect" load_steps=8 format=3 uid="uid://ds6sptirfbytc"] + +[ext_resource type="Script" uid="uid://bw7kbgl2vbeoh" path="res://addons/rokojori_action_library/Runtime/VirtualCameras/Effects/CameraEffectTargetAnimationCurve.cs" id="1_m7t4k"] +[ext_resource type="Script" uid="uid://bmcpy4cqv1lmr" path="res://addons/rokojori_action_library/Runtime/VirtualCameras/Effects/CameraEffect.cs" id="2_ahqbp"] +[ext_resource type="Resource" uid="uid://h6oi6vkj4c2m" path="res://addons/rokojori_action_library/Runtime/Time/TimeLines/RealTime.tres" id="3_iffro"] + +[sub_resource type="Curve" id="Curve_62jxv"] +_limits = [-1.0, 1.0, 0.0, 1.0] +_data = [Vector2(0, 0), 0.0, 5.72558, 0, 1, Vector2(0.0625, 0.357849), 0.0, 0.0, 0, 0, Vector2(0.231707, -0.252644), 0.0, 0.0, 0, 0, Vector2(0.429878, 0.113984), 0.0, 0.0, 0, 0, Vector2(0.564516, 0.326316), 0.0, 0.0, 0, 0, Vector2(0.741935, -0.242105), 0.0, 0.0, 0, 0, Vector2(0.860215, 0.473684), 0.0, 0.0, 0, 0, Vector2(1, 0), -3.38866, 0.0, 1, 0] +point_count = 8 + +[sub_resource type="Resource" id="Resource_esvga"] +script = ExtResource("1_m7t4k") +target = 0 +flipScaleYRandomly = true +duration = 0.5 +durationRandomRange = 0.0 +delay = 0.0 +delayRandomRange = 0.0 +curve = SubResource("Curve_62jxv") +scaleY = 0.05 +scaleRandomRange = 0.1 + +[sub_resource type="Curve" id="Curve_h7nko"] +_limits = [-1.0, 1.0, 0.0, 1.0] +_data = [Vector2(0, 0), 0.0, 2.98837, 0, 1, Vector2(0.102151, 0.305263), -1.30526, -1.30526, 0, 0, Vector2(0.263441, 0.221053), 0.0, 0.0, 0, 0, Vector2(0.333333, -0.263158), 0.0, 0.0, 0, 0, Vector2(0.503049, -0.130435), 0.0, 0.0, 0, 0, Vector2(0.689024, 0.0223267), 0.0, 0.0, 0, 0, Vector2(0.763441, 0.410526), 0.0, 0.0, 0, 0, Vector2(0.822581, -0.305263), 0.0, 0.0, 0, 0, Vector2(1, 0), 1.72057, 0.0, 1, 0] +point_count = 9 + +[sub_resource type="Resource" id="Resource_s8na2"] +script = ExtResource("1_m7t4k") +target = 1 +flipScaleYRandomly = false +duration = 0.5 +durationRandomRange = 0.0 +delay = 0.0 +delayRandomRange = 0.0 +curve = SubResource("Curve_h7nko") +scaleY = 0.05 +scaleRandomRange = 0.1 + +[resource] +script = ExtResource("2_ahqbp") +animations = [SubResource("Resource_esvga"), SubResource("Resource_s8na2")] +timeline = ExtResource("3_iffro") diff --git a/Runtime/VirtualCameras/MouseEditorCamera/Inputs/Sensors/Move Back.tres b/Runtime/VirtualCameras/MouseEditorCamera/Inputs/Sensors/Move Back.tres index d739e03..9fdc9c6 100644 --- a/Runtime/VirtualCameras/MouseEditorCamera/Inputs/Sensors/Move Back.tres +++ b/Runtime/VirtualCameras/MouseEditorCamera/Inputs/Sensors/Move Back.tres @@ -14,10 +14,6 @@ altHold = 2 shiftHold = 2 modifiersMode = 0 continous = false -_value = 0.0 -_wasActive = false -_active = false -_activeTreshold = 0.5 [sub_resource type="Resource" id="Resource_75e6s"] script = ExtResource("1_ikub8") @@ -27,29 +23,17 @@ numVisible = 0 inputIcons = [] useInputIconsFromSensors = true continous = false -_value = 0.0 -_wasActive = false -_active = false -_activeTreshold = 0.5 [sub_resource type="Resource" id="Resource_gmj7t"] script = ExtResource("3_1wc0w") axis = 1 type = 0 continous = false -_value = 0.0 -_wasActive = false -_active = false -_activeTreshold = 0.5 [sub_resource type="Resource" id="Resource_687xx"] script = ExtResource("4_wj7li") button = 12 continous = false -_value = 0.0 -_wasActive = false -_active = false -_activeTreshold = 0.5 [sub_resource type="Resource" id="Resource_unhue"] script = ExtResource("1_ikub8") @@ -59,10 +43,6 @@ numVisible = 1 inputIcons = [] useInputIconsFromSensors = true continous = false -_value = 0.0 -_wasActive = false -_active = false -_activeTreshold = 0.5 [resource] script = ExtResource("1_ikub8") @@ -72,7 +52,3 @@ numVisible = 0 inputIcons = [] useInputIconsFromSensors = true continous = false -_value = 0.0 -_wasActive = false -_active = false -_activeTreshold = 0.5 diff --git a/Runtime/VirtualCameras/MouseEditorCamera/Inputs/Sensors/Move Down.tres b/Runtime/VirtualCameras/MouseEditorCamera/Inputs/Sensors/Move Down.tres index 32e6829..bc17839 100644 --- a/Runtime/VirtualCameras/MouseEditorCamera/Inputs/Sensors/Move Down.tres +++ b/Runtime/VirtualCameras/MouseEditorCamera/Inputs/Sensors/Move Down.tres @@ -13,10 +13,6 @@ altHold = 2 shiftHold = 2 modifiersMode = 0 continous = false -_value = 0.0 -_wasActive = false -_active = false -_activeTreshold = 0.5 [sub_resource type="Resource" id="Resource_jvxvp"] script = ExtResource("1_e8w3r") @@ -26,19 +22,11 @@ numVisible = 0 inputIcons = [] useInputIconsFromSensors = true continous = false -_value = 0.0 -_wasActive = false -_active = false -_activeTreshold = 0.5 [sub_resource type="Resource" id="Resource_3ovg5"] script = ExtResource("3_pyik4") button = 10 continous = false -_value = 0.0 -_wasActive = false -_active = false -_activeTreshold = 0.5 [sub_resource type="Resource" id="Resource_yhdev"] script = ExtResource("1_e8w3r") @@ -48,10 +36,6 @@ numVisible = 0 inputIcons = [] useInputIconsFromSensors = true continous = false -_value = 0.0 -_wasActive = false -_active = false -_activeTreshold = 0.5 [resource] script = ExtResource("1_e8w3r") @@ -61,7 +45,3 @@ numVisible = 0 inputIcons = [] useInputIconsFromSensors = true continous = false -_value = 0.0 -_wasActive = false -_active = false -_activeTreshold = 0.5 diff --git a/Runtime/VirtualCameras/MouseEditorCamera/Inputs/Sensors/Move Forward.tres b/Runtime/VirtualCameras/MouseEditorCamera/Inputs/Sensors/Move Forward.tres index 3053b73..1176f22 100644 --- a/Runtime/VirtualCameras/MouseEditorCamera/Inputs/Sensors/Move Forward.tres +++ b/Runtime/VirtualCameras/MouseEditorCamera/Inputs/Sensors/Move Forward.tres @@ -14,10 +14,6 @@ altHold = 2 shiftHold = 2 modifiersMode = 0 continous = false -_value = 0.0 -_wasActive = false -_active = false -_activeTreshold = 0.5 [sub_resource type="Resource" id="Resource_nj1ud"] script = ExtResource("1_r4ul7") @@ -27,29 +23,17 @@ numVisible = 0 inputIcons = [] useInputIconsFromSensors = true continous = false -_value = 0.0 -_wasActive = false -_active = false -_activeTreshold = 0.5 [sub_resource type="Resource" id="Resource_mxixb"] script = ExtResource("3_nh2m3") axis = 1 type = 1 continous = false -_value = 0.0 -_wasActive = false -_active = false -_activeTreshold = 0.5 [sub_resource type="Resource" id="Resource_c1vyq"] script = ExtResource("3_dyhbp") button = 11 continous = false -_value = 0.0 -_wasActive = false -_active = false -_activeTreshold = 0.5 [sub_resource type="Resource" id="Resource_vhtjx"] script = ExtResource("1_r4ul7") @@ -59,10 +43,6 @@ numVisible = 1 inputIcons = [] useInputIconsFromSensors = true continous = false -_value = 0.0 -_wasActive = false -_active = false -_activeTreshold = 0.5 [resource] script = ExtResource("1_r4ul7") @@ -72,7 +52,3 @@ numVisible = 0 inputIcons = [] useInputIconsFromSensors = true continous = false -_value = 0.0 -_wasActive = false -_active = false -_activeTreshold = 0.5 diff --git a/Runtime/VirtualCameras/MouseEditorCamera/Inputs/Sensors/Move Left.tres b/Runtime/VirtualCameras/MouseEditorCamera/Inputs/Sensors/Move Left.tres index 08dcde1..64e3c30 100644 --- a/Runtime/VirtualCameras/MouseEditorCamera/Inputs/Sensors/Move Left.tres +++ b/Runtime/VirtualCameras/MouseEditorCamera/Inputs/Sensors/Move Left.tres @@ -14,10 +14,6 @@ altHold = 2 shiftHold = 2 modifiersMode = 0 continous = false -_value = 0.0 -_wasActive = false -_active = false -_activeTreshold = 0.5 [sub_resource type="Resource" id="Resource_qts7v"] script = ExtResource("1_w0cyl") @@ -27,29 +23,17 @@ numVisible = 0 inputIcons = [] useInputIconsFromSensors = true continous = false -_value = 0.0 -_wasActive = false -_active = false -_activeTreshold = 0.5 [sub_resource type="Resource" id="Resource_gmj7t"] script = ExtResource("3_ushvr") axis = 0 type = 1 continous = false -_value = 0.0 -_wasActive = false -_active = false -_activeTreshold = 0.5 [sub_resource type="Resource" id="Resource_687xx"] script = ExtResource("4_53tr6") button = 13 continous = false -_value = 0.0 -_wasActive = false -_active = false -_activeTreshold = 0.5 [sub_resource type="Resource" id="Resource_0hx40"] script = ExtResource("1_w0cyl") @@ -59,10 +43,6 @@ numVisible = 1 inputIcons = [] useInputIconsFromSensors = true continous = false -_value = 0.0 -_wasActive = false -_active = false -_activeTreshold = 0.5 [resource] script = ExtResource("1_w0cyl") @@ -72,7 +52,3 @@ numVisible = 0 inputIcons = [] useInputIconsFromSensors = true continous = false -_value = 0.0 -_wasActive = false -_active = false -_activeTreshold = 0.5 diff --git a/Runtime/VirtualCameras/MouseEditorCamera/Inputs/Sensors/Move Right.tres b/Runtime/VirtualCameras/MouseEditorCamera/Inputs/Sensors/Move Right.tres index 0a5579a..fa7bb58 100644 --- a/Runtime/VirtualCameras/MouseEditorCamera/Inputs/Sensors/Move Right.tres +++ b/Runtime/VirtualCameras/MouseEditorCamera/Inputs/Sensors/Move Right.tres @@ -14,10 +14,6 @@ altHold = 2 shiftHold = 2 modifiersMode = 0 continous = false -_value = 0.0 -_wasActive = false -_active = false -_activeTreshold = 0.5 [sub_resource type="Resource" id="Resource_d1suo"] script = ExtResource("1_vdwin") @@ -27,29 +23,17 @@ numVisible = 0 inputIcons = [] useInputIconsFromSensors = true continous = false -_value = 0.0 -_wasActive = false -_active = false -_activeTreshold = 0.5 [sub_resource type="Resource" id="Resource_c7ebh"] script = ExtResource("3_4antj") axis = 0 type = 0 continous = false -_value = 0.0 -_wasActive = false -_active = false -_activeTreshold = 0.5 [sub_resource type="Resource" id="Resource_md70b"] script = ExtResource("4_ucs5r") button = 14 continous = false -_value = 0.0 -_wasActive = false -_active = false -_activeTreshold = 0.5 [sub_resource type="Resource" id="Resource_fhaor"] script = ExtResource("1_vdwin") @@ -59,10 +43,6 @@ numVisible = 1 inputIcons = [] useInputIconsFromSensors = true continous = false -_value = 0.0 -_wasActive = false -_active = false -_activeTreshold = 0.5 [resource] script = ExtResource("1_vdwin") @@ -72,7 +52,3 @@ numVisible = 0 inputIcons = [] useInputIconsFromSensors = true continous = false -_value = 0.0 -_wasActive = false -_active = false -_activeTreshold = 0.5 diff --git a/Runtime/VirtualCameras/MouseEditorCamera/Inputs/Sensors/Move Upward.tres b/Runtime/VirtualCameras/MouseEditorCamera/Inputs/Sensors/Move Upward.tres index 739c4a6..bb9eefb 100644 --- a/Runtime/VirtualCameras/MouseEditorCamera/Inputs/Sensors/Move Upward.tres +++ b/Runtime/VirtualCameras/MouseEditorCamera/Inputs/Sensors/Move Upward.tres @@ -13,10 +13,6 @@ altHold = 2 shiftHold = 2 modifiersMode = 0 continous = false -_value = 0.0 -_wasActive = false -_active = false -_activeTreshold = 0.5 [sub_resource type="Resource" id="Resource_pqldp"] script = ExtResource("1_5263n") @@ -26,19 +22,11 @@ numVisible = 0 inputIcons = [] useInputIconsFromSensors = true continous = false -_value = 0.0 -_wasActive = false -_active = false -_activeTreshold = 0.5 [sub_resource type="Resource" id="Resource_ivi7v"] script = ExtResource("3_ejsq1") button = 9 continous = false -_value = 0.0 -_wasActive = false -_active = false -_activeTreshold = 0.5 [sub_resource type="Resource" id="Resource_0uxqa"] script = ExtResource("1_5263n") @@ -48,10 +36,6 @@ numVisible = 1 inputIcons = [] useInputIconsFromSensors = true continous = false -_value = 0.0 -_wasActive = false -_active = false -_activeTreshold = 0.5 [resource] script = ExtResource("1_5263n") @@ -61,7 +45,3 @@ numVisible = 0 inputIcons = [] useInputIconsFromSensors = true continous = false -_value = 0.0 -_wasActive = false -_active = false -_activeTreshold = 0.5 diff --git a/Runtime/VirtualCameras/MouseEditorCamera/Inputs/Sensors/Zoom In.tres b/Runtime/VirtualCameras/MouseEditorCamera/Inputs/Sensors/Zoom In.tres index 708d1ec..e337f8e 100644 --- a/Runtime/VirtualCameras/MouseEditorCamera/Inputs/Sensors/Zoom In.tres +++ b/Runtime/VirtualCameras/MouseEditorCamera/Inputs/Sensors/Zoom In.tres @@ -9,10 +9,6 @@ script = ExtResource("3_5t03r") axis = 5 type = 0 continous = false -_value = 0.0 -_wasActive = false -_active = false -_activeTreshold = 0.5 [resource] script = ExtResource("1_lnrk8") @@ -22,7 +18,3 @@ numVisible = 0 inputIcons = [] useInputIconsFromSensors = true continous = false -_value = 0.0 -_wasActive = false -_active = false -_activeTreshold = 0.5 diff --git a/Runtime/VirtualCameras/MouseEditorCamera/Inputs/Sensors/Zoom Out.tres b/Runtime/VirtualCameras/MouseEditorCamera/Inputs/Sensors/Zoom Out.tres index 8fe0bb2..ffe8ecf 100644 --- a/Runtime/VirtualCameras/MouseEditorCamera/Inputs/Sensors/Zoom Out.tres +++ b/Runtime/VirtualCameras/MouseEditorCamera/Inputs/Sensors/Zoom Out.tres @@ -9,10 +9,6 @@ script = ExtResource("3_pu70j") axis = 4 type = 0 continous = false -_value = 0.0 -_wasActive = false -_active = false -_activeTreshold = 0.5 [resource] script = ExtResource("1_w21si") @@ -22,7 +18,3 @@ numVisible = 0 inputIcons = [] useInputIconsFromSensors = true continous = false -_value = 0.0 -_wasActive = false -_active = false -_activeTreshold = 0.5 diff --git a/Runtime/VirtualCameras/RemoveCameraSlot.cs b/Runtime/VirtualCameras/RemoveCameraSlot.cs new file mode 100644 index 0000000..07a2efa --- /dev/null +++ b/Runtime/VirtualCameras/RemoveCameraSlot.cs @@ -0,0 +1,25 @@ + +using System.Diagnostics; +using System.Collections; +using System.Collections.Generic; +using System; +using Godot; + + +namespace Rokojori +{ + [Tool] + [GlobalClass, Icon("res://addons/rokojori_action_library/Icons/RemoveVirtualCamera3D.svg") ] + public partial class RemoveCameraSlot:Action + { + [Export] + public VirtualCamera3D virtualCamera3D; + + protected override void _OnTrigger() + { + var vm = VirtualCamera3DManager.Get(); + vm.RemoveSlot( vm.GetSlot( virtualCamera3D ) ); + + } + } +} \ No newline at end of file diff --git a/Runtime/VirtualCameras/RemoveCameraSlot.cs.uid b/Runtime/VirtualCameras/RemoveCameraSlot.cs.uid new file mode 100644 index 0000000..4c79294 --- /dev/null +++ b/Runtime/VirtualCameras/RemoveCameraSlot.cs.uid @@ -0,0 +1 @@ +uid://bd5by40c3crdx diff --git a/Runtime/VirtualCameras/VirtualCamera3DManager.cs b/Runtime/VirtualCameras/VirtualCamera3DManager.cs index c496397..c9afb70 100644 --- a/Runtime/VirtualCameras/VirtualCamera3DManager.cs +++ b/Runtime/VirtualCameras/VirtualCamera3DManager.cs @@ -61,17 +61,44 @@ namespace Rokojori return _cameraSlots[ index ]; } + public VirtualCamera3DSlot GetSlot( VirtualCamera3D virtualCamera3D ) + { + return _cameraSlots.Find( s => s.camera == virtualCamera3D ); + } + + public VirtualCamera3DSlot GetSlot( SelectorFlag[] flags ) + { + return _cameraSlots.Find( s => Arrays.ContainsAll( s.flags, flags ) ); + } + public void SetActiveSlot( VirtualCamera3DSlot slot ) { _cameraSlots.ForEach( c => c.priority = c == slot ? 1 : 0 ); } + public void RefreshSlots() + { + refreshSlots = false; + _cameraSlots = Nodes.GetDirectChildren( this ); + } + + public void RemoveSlot( VirtualCamera3DSlot slot ) + { + if ( slot == null || slot.GetParent() != this ) + { + return; + } + + Nodes.RemoveAndDelete( slot ); + + RefreshSlots(); + } + void LerpCameras( double delta ) { if ( refreshSlots || _cameraSlots == null || _cameraSlots.Count == 0 ) { - refreshSlots = false; - _cameraSlots = Nodes.GetDirectChildren( this ); + RefreshSlots(); } var sumPriority = 0f; diff --git a/Runtime/VirtualCameras/VirtualCamera3DSlot.cs b/Runtime/VirtualCameras/VirtualCamera3DSlot.cs index f743dda..84d308c 100644 --- a/Runtime/VirtualCameras/VirtualCamera3DSlot.cs +++ b/Runtime/VirtualCameras/VirtualCamera3DSlot.cs @@ -19,6 +19,9 @@ namespace Rokojori [Export] public float priority; + [Export] + public SelectorFlag[] flags = []; + CameraEffectRunner cameraEffectRunner = null; float _effectTimePosition = 0; float _smoothedPriority;