Vignette, CoolDowns, Pause, NodeState

This commit is contained in:
Josef 2025-07-22 16:08:22 +02:00
parent 08dbd8681b
commit 839b0bca39
40 changed files with 876 additions and 77 deletions

View File

@ -0,0 +1,36 @@
using Godot;
using System.Collections.Generic;
namespace Rokojori
{
[Tool][GlobalClass]
public partial class PlayMusic:Action
{
[Export]
public AudioStreamPlayer music;
[Export]
public bool stopSiblingPlayers = false;
protected override void _OnTrigger()
{
if ( stopSiblingPlayers )
{
GetParent().ForEachDirectChild<AudioStreamPlayer>(
( p )=>
{
if ( p == music )
{
return;
}
p.Stop();
}
);
}
music.Play();
}
}
}

View File

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

View File

@ -0,0 +1,39 @@
using Godot;
using System.Collections.Generic;
namespace Rokojori
{
[Tool]
[GlobalClass, Icon("res://addons/rokojori_action_library/Icons/ConditionalAction.svg")]
public partial class CoolDown : Action
{
[Export]
public Action action;
[Export]
public Duration coolDownDuration;
bool _isCoolingDown = false;
protected override void _OnTrigger()
{
if ( _isCoolingDown )
{
return;
}
_isCoolingDown = coolDownDuration != null;
Trigger( action );
if ( coolDownDuration != null )
{
TimeLineManager.ScheduleEventIn(
coolDownDuration.timeLine, coolDownDuration.GetDurationInSeconds(),
ev => _isCoolingDown = false
);
}
}
}
}

View File

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

View File

@ -0,0 +1,22 @@
using Godot;
namespace Rokojori
{
[Tool][GlobalClass ]
public partial class SetNodeStateSpecific : Action
{
[Export]
public Node target;
[Export]
public NodeStateConfiguration configuration;
protected override void _OnTrigger()
{
NodeState.Configure( target, configuration );
}
}
}

View File

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

View File

@ -0,0 +1,66 @@
using Godot;
namespace Rokojori
{
[Tool][GlobalClass ]
public partial class MoveTo : SequenceAction, Animator
{
[Export]
public Node3D target;
[Export]
public Node3D goal;
[Export]
public Duration duration;
int _actionID = -1;
int _currentSpanAnimationID = -1;
public void OnAnimatorStart(){}
public void OnAnimatorEnd(){}
public void OnAnimatorCancel(){}
protected override void _OnTrigger()
{
if ( _actionID != -1 )
{
CancelAction( _actionID );
}
var sequenceID = DispatchStart();
_actionID = sequenceID;
AnimationManager.StartAnimation( this, target, AnimationMember.Position );
var startPosition = target.GlobalPosition;
_currentSpanAnimationID = TimeLineManager.ScheduleSpanIn( duration.timeLine, 0, duration.GetDurationInSeconds(),
( TimeLineSpan span, TimeLineSpanUpdateType type )=>
{
if ( span.id != _currentSpanAnimationID )
{
return;
}
if ( ! AnimationManager.IsAnimating( this, target, AnimationMember.Position ) )
{
return;
}
target.GlobalPosition = startPosition.Lerp( goal.GlobalPosition, span.phase );;
if ( TimeLineSpanUpdateType.End == type )
{
AnimationManager.EndAnimation( this, target, AnimationMember.Position );
DispatchEnd( sequenceID );
return;
}
}
).id;
}
}
}

View File

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

View File

@ -37,10 +37,9 @@ namespace Rokojori
return _nodes; return _nodes;
} }
public void OnNodeStateChanged( bool processEnabled, bool inputEnabled, bool physicsEnabled, bool signalsEnabled, public void OnNodeStateChanged()
Node.ProcessModeEnum processMode, bool visible )
{ {
if ( ! processEnabled || ! physicsEnabled || Node.ProcessModeEnum.Disabled == processMode ) if ( ! IsProcessing() || ! IsPhysicsProcessing() || Node.ProcessModeEnum.Disabled == this.ProcessMode )
{ {
this.LogInfo( "Clearing nodes" ); this.LogInfo( "Clearing nodes" );
_nodes.Clear(); _nodes.Clear();

View File

@ -1,5 +1,6 @@
using Godot; using Godot;
using System.Collections.Generic;
namespace Rokojori namespace Rokojori
{ {
@ -9,9 +10,95 @@ namespace Rokojori
[Export] [Export]
public GpuParticles3D particles3D; public GpuParticles3D particles3D;
[Export]
public bool usePooling = false;
[Export]
public float godotFinishedReporingBugOffset = 0.2f;
[Export]
public TimeLine timeLine;
List<GpuParticles3D> _pool = new List<GpuParticles3D>();
List<bool> _emitting = new List<bool>();
protected override void _OnTrigger() protected override void _OnTrigger()
{
if ( ! usePooling )
{ {
particles3D.Restart(); particles3D.Restart();
return;
}
if ( _emitting.Count == 0 )
{
_emitting.Add( false );
}
var p = GetFreeParticles();
if ( p == null )
{
p = DuplicateParticles();
}
this.LogInfo( "Using Particles", p );
var index = IndexOf( p );
_emitting[ index ] = true;
p.OnFinishedOnce(
() =>
{
if ( godotFinishedReporingBugOffset <= 0 )
{
_emitting[ index ] = false;
return;
}
TimeLineManager.ScheduleEventIn(
timeLine,
godotFinishedReporingBugOffset,
t => _emitting[ index ] = false
);
}
);
p.Restart();
}
public int IndexOf( GpuParticles3D p )
{
return p == particles3D ? 0 : _pool.IndexOf( p ) + 1;
}
public bool IsEmitting( GpuParticles3D p )
{
return _emitting[ IndexOf( p ) ];
}
GpuParticles3D GetFreeParticles()
{
if ( ! IsEmitting( particles3D ) )
{
return particles3D;
}
return _pool.Find( p => ! p.Emitting );
}
GpuParticles3D DuplicateParticles()
{
this.LogInfo( "Duplicating Particles" );
var duplicate = particles3D.Duplicate() as GpuParticles3D;
_pool.Add( duplicate );
particles3D.GetParent().AddChild( duplicate );
_emitting.Add( false );
return duplicate;
} }
} }
} }

View File

@ -10,12 +10,18 @@ namespace Rokojori
[Export] [Export]
public Node target; public Node target;
[Export]
public bool queue = true;
protected override void _OnTrigger() protected override void _OnTrigger()
{ {
if ( target != null ) if ( target == null )
{ {
target.SelfDestroy(); return;
} }
target.SelfDestroy( queue );
} }
} }
} }

View File

@ -0,0 +1,59 @@
using Godot;
namespace Rokojori
{
[Tool][GlobalClass ]
public partial class SetPauseState : Action
{
public enum Mode
{
Pause,
Resume,
Toggle
}
[Export]
public Mode mode;
[Export]
public Action onPausing;
[Export]
public Action onResuming;
[Export]
public bool onlyTriggerOnChange = true;
protected override void _OnTrigger()
{
var currentState = GetTree().Paused;
var nextState = Mode.Toggle == mode ? ! currentState : Mode.Pause == mode ? false : true;
this.LogInfo( "SetPauseState", currentState, ">>", nextState );
if ( currentState == nextState && onlyTriggerOnChange )
{
return;
}
this.LogInfo( "Setting Pause State", nextState );
GetTree().Paused = nextState;
if ( nextState )
{
Action.Trigger( onPausing );
}
else
{
Action.Trigger( onResuming );
}
}
}
}

View File

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

33
Runtime/Actions/Solo.cs Normal file
View File

@ -0,0 +1,33 @@
using Godot;
namespace Rokojori
{
[Tool][GlobalClass ]
public partial class Solo:Action
{
[Export]
public Node soloNode;
[Export]
public NodeStateConfiguration soloConfiguration;
[Export]
public NodeStateConfiguration muteConifiguration;
protected override void _OnTrigger()
{
var parent = soloNode.GetParent();
parent.ForEachDirectChild<Node>(
n =>
{
var configuration = soloNode == n ? soloConfiguration : muteConifiguration;
NodeState.Configure( n, configuration );
}
);
}
}
}

View File

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

View File

@ -7,8 +7,8 @@
[sub_resource type="Resource" id="Resource_54hj8"] [sub_resource type="Resource" id="Resource_54hj8"]
script = ExtResource("1_nmdum") script = ExtResource("1_nmdum")
color = Color(1, 0, 0, 1) color = Color(0.859799, 0.542989, 0.696896, 1)
colorMultiply = 1.0 colorMultiply = 4.0
rgbMultiply = 1.0 rgbMultiply = 1.0
alphaMultiply = 1.0 alphaMultiply = 1.0

View File

@ -91,7 +91,7 @@ namespace Rokojori
else if ( TransformTarget.Global_Rotation == transformTarget ) else if ( TransformTarget.Global_Rotation == transformTarget )
{ {
var rotation = target.GlobalRotation; var rotation = target.GlobalRotation;
target.GlobalRotation = value; target.GlobalRotation = value * MathX.DegreesToRadians;
// RJLog.Log( "GlobalRotation = ", rotation, ">>", value, target.GlobalRotation ); // RJLog.Log( "GlobalRotation = ", rotation, ">>", value, target.GlobalRotation );
} }
else if ( TransformTarget.Local_Position == transformTarget ) else if ( TransformTarget.Local_Position == transformTarget )
@ -101,7 +101,7 @@ namespace Rokojori
else if ( TransformTarget.Local_Rotation == transformTarget ) else if ( TransformTarget.Local_Rotation == transformTarget )
{ {
var rotation = target.Rotation; var rotation = target.Rotation;
target.Rotation = value; target.Rotation = value * MathX.DegreesToRadians;
// RJLog.Log( "Rotation = ", rotation, ">>", value, target.Rotation ); // RJLog.Log( "Rotation = ", rotation, ">>", value, target.Rotation );
} }
else if ( TransformTarget.Local_Scale == transformTarget ) else if ( TransformTarget.Local_Scale == transformTarget )

47
Runtime/Events/Signals.cs Normal file
View File

@ -0,0 +1,47 @@
using System.Collections.Generic;
using Godot;
namespace Rokojori
{
public static class Signals
{
public static void OnFinished( this GpuParticles3D particles3D, System.Action action, bool once = false )
{
if ( once )
{
_OnSignalOnce( particles3D, GpuParticles3D.SignalName.Finished, action );
}
else
{
_OnSignal( particles3D, GpuParticles3D.SignalName.Finished, action );
}
}
public static void OnFinishedOnce( this GpuParticles3D particles3D, System.Action action )
{
OnFinished( particles3D, action, true );
}
public static void _OnSignal( Node node, string name, System.Action action )
{
node.Connect( name, Callable.From( action ) );
}
public static void _OnSignalOnce( Node node, string name, System.Action action )
{
Callable? onceAction = null;
onceAction = Callable.From(
()=>
{
action();
node.Disconnect( name, (Callable) onceAction );
}
);
node.Connect( name, (Callable)onceAction );
}
}
}

View File

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

View File

@ -7,13 +7,107 @@ namespace Rokojori
{ {
public interface iNodeState public interface iNodeState
{ {
public void OnNodeStateChanged( bool processEnabled, bool inputEnabled, bool physicsEnabled, bool signalsEnabled, public void OnNodeStateChanged();
Node.ProcessModeEnum processMode, bool visible );
} }
public static class NodeState public static class NodeState
{ {
public static bool IsVisible( this Node n )
{
if ( n is Node3D )
{
return ( n as Node3D ).Visible;
}
if ( n is Node2D )
{
return ( n as Node2D ).Visible;
}
if ( n is CanvasItem )
{
return ( n as CanvasItem ).Visible;
}
return false;
}
public static void Configure( Node target, NodeStateConfiguration configuration )
{
Configure( target,
configuration.processEnabled, configuration.inputEnabled, configuration.physicsEnabled,
configuration.signalsEnabled, configuration.visible, configuration.setProcessMode, configuration.processMode
);
}
public static void SetNodeState( this Node target, NodeStateConfiguration configuration )
{
Configure( target, configuration );
}
public static void Configure(
Node target,
Trillean processEnabled, Trillean inputEnabled,Trillean physicsEnabled,
Trillean signalsEnabled,Trillean visible, bool setProcessMode, Node.ProcessModeEnum processMode
)
{
if ( Trillean.Any != processEnabled )
{
target.SetProcess( TrilleanLogic.ToBool( processEnabled ) );
}
if ( Trillean.Any != inputEnabled )
{
target.SetProcessInput( TrilleanLogic.ToBool( inputEnabled ) );
}
if ( Trillean.Any != physicsEnabled )
{
target.SetPhysicsProcess( TrilleanLogic.ToBool( physicsEnabled ) );
}
if ( Trillean.Any != signalsEnabled )
{
target.SetBlockSignals( ! TrilleanLogic.ToBool( signalsEnabled ) );
}
if ( setProcessMode )
{
target.ProcessMode = processMode;
}
if ( Trillean.Any != visible )
{
var n = target;
var visibleFlag = TrilleanLogic.ToBool( visible );
if ( n is Node3D )
{
( n as Node3D ).Visible = visibleFlag;
}
if ( n is Node2D )
{
( n as Node2D ).Visible = visibleFlag;
}
if ( n is CanvasItem )
{
( n as CanvasItem ).Visible = visibleFlag;
}
}
if ( target is iNodeState ins )
{
ins.OnNodeStateChanged();
}
}
public static void Configure( Node n, bool processEnabled, bool inputEnabled, bool physicsEnabled, bool signalsEnabled, public static void Configure( Node n, bool processEnabled, bool inputEnabled, bool physicsEnabled, bool signalsEnabled,
Node.ProcessModeEnum processMode, bool visible ) Node.ProcessModeEnum processMode, bool visible )
{ {
@ -29,13 +123,6 @@ namespace Rokojori
n.ProcessMode = processMode; n.ProcessMode = processMode;
if ( n is iNodeState ins )
{
ins.OnNodeStateChanged( processEnabled, inputEnabled, physicsEnabled, signalsEnabled,
processMode, visible );
}
if ( n is Node3D ) if ( n is Node3D )
{ {
( n as Node3D ).Visible = visible; ( n as Node3D ).Visible = visible;
@ -51,6 +138,10 @@ namespace Rokojori
( n as CanvasItem ).Visible = visible; ( n as CanvasItem ).Visible = visible;
} }
if ( n is iNodeState ins )
{
ins.OnNodeStateChanged();
}
} }
public static void Set( Node n, bool enabled ) public static void Set( Node n, bool enabled )

View File

@ -0,0 +1,34 @@
using Godot;
using System.Collections.Generic;
using System;
namespace Rokojori
{
[Tool,GlobalClass]
public partial class NodeStateConfiguration:Resource
{
[Export]
public Trillean processEnabled = Trillean.Any;
[Export]
public Trillean inputEnabled = Trillean.Any;
[Export]
public Trillean physicsEnabled = Trillean.Any;
[Export]
public Trillean signalsEnabled = Trillean.Any;
[Export]
public Trillean visible = Trillean.Any;
[Export]
public bool setProcessMode = false;
[Export]
public Node.ProcessModeEnum processMode;
}
}

View File

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

View File

@ -538,7 +538,7 @@ namespace Rokojori
} }
} }
public static void SelfDestroy( this Node node ) public static void SelfDestroy( this Node node, bool queue = true )
{ {
var parent = node.GetParent(); var parent = node.GetParent();
@ -547,8 +547,18 @@ namespace Rokojori
parent.RemoveChild( node ); parent.RemoveChild( node );
} }
node.LogInfo( "Freeing queued:", queue, node);
if ( queue )
{
node.QueueFree(); node.QueueFree();
} }
else
{
node.Free();
}
}

View File

@ -0,0 +1,26 @@
using Godot;
using System.Collections;
using System.Collections.Generic;
using Godot.Collections;
namespace Rokojori
{
[Tool]
[GlobalClass]
public partial class CharacterIsJumping:SceneCondition
{
[Export]
public Jump jump;
public override bool Evaluate()
{
if ( jump == null )
{
return false;
}
return jump.IsJumping();
}
}
}

View File

@ -0,0 +1 @@
uid://5yoyxyejk4ga

View File

@ -12,6 +12,9 @@ namespace Rokojori
[Export] [Export]
public Sensor button; public Sensor button;
[Export]
public Action onJump;
[ExportGroup( "Jump Impulse")] [ExportGroup( "Jump Impulse")]
[Export] [Export]
@ -39,31 +42,41 @@ namespace Rokojori
bool canJump = false; bool canJump = false;
bool jumping = false; bool jumpPressing = false;
bool needsToRelease = false; bool needsToRelease = false;
bool inAir = false;
public bool IsJumping()
{
return inAir;
}
protected override void _OnTrigger() protected override void _OnTrigger()
{ {
if ( body.IsOnFloor() ) if ( body.IsOnFloor() )
{ {
if ( jumping ) if ( inAir )
{ {
jumping = false; inAir = false;
}
if ( jumpPressing )
{
jumpPressing = false;
needsToRelease = true; needsToRelease = true;
} }
} }
if ( ! ( jumping || body.IsOnFloor() ) ) if ( ! ( jumpPressing || body.IsOnFloor() ) )
{ {
return; return;
} }
if ( ! button.isActive ) if ( ! button.isActive )
{ {
jumping = false; jumpPressing = false;
needsToRelease = false; needsToRelease = false;
return; return;
} }
@ -73,10 +86,13 @@ namespace Rokojori
return; return;
} }
if ( ! jumping ) if ( ! jumpPressing )
{ {
jumping = true; jumpPressing = true;
jumpedDuration = 0; jumpedDuration = 0;
inAir = true;
Trigger( onJump );
var jumpDirection = Vector3.Up * jumpImpulseStrength; var jumpDirection = Vector3.Up * jumpImpulseStrength;

View File

@ -505,6 +505,16 @@ namespace Rokojori
return new Vector2( v.Y, v.Z ); return new Vector2( v.Y, v.Z );
} }
public static Vector3 ZeroY( this Vector3 v )
{
return new Vector3( v.X, 0, v.Z );
}
public static Vector3 SetY( this Vector3 v, float y )
{
return new Vector3( v.X, y, v.Z );
}
public static Basis AlignUp( Basis basis, Vector3 upDirection ) public static Basis AlignUp( Basis basis, Vector3 upDirection )
{ {
basis.Y = upDirection; basis.Y = upDirection;

View File

@ -51,22 +51,24 @@ uniform vec4 obstacle1 = vec4( 0, 0, 0, 0 );
uniform vec4 obstacle2 = vec4( 0, 0, 0, 0 ); uniform vec4 obstacle2 = vec4( 0, 0, 0, 0 );
uniform vec4 obstacle3 = vec4( 0, 0, 0, 0 ); uniform vec4 obstacle3 = vec4( 0, 0, 0, 0 );
uniform vec4 obstacle4 = vec4( 0, 0, 0, 0 ); uniform vec4 obstacle4 = vec4( 0, 0, 0, 0 );
uniform float obstacleDeformationPower = 1.0;
uniform float obstacleDeformation = 1.0; uniform float obstacleDeformation = 1.0;
uniform float obstacleScale = 1.0; uniform float obstacleScale = 1.0;
uniform float maxDeformation = 0.3; uniform float maxDeformation = 0.3;
uniform float maxYOffset = 0.1; uniform float maxYOffset = 0.1;
uniform float obstacleYScale = 1.0;
vec3 deform( vec3 worldPosition, vec4 obstacle ) vec3 deform( vec3 worldPosition, vec4 obstacle )
{ {
vec3 direction = worldPosition - obstacle.xyz; vec3 direction = ( worldPosition - obstacle.xyz ) * vec3( 1.0, obstacleYScale, 1.0 );
float d = length( direction ); float d = length( direction );
float size = obstacle.w * obstacleScale; float size = obstacle.w * obstacleScale;
if ( d <size && d >= 0.0 ) if ( d < size && d >= 0.0 )
{ {
float amount = max( 0, ( size - d ) ); float amount = max( 0, ( size - d ) );
amount = pow( amount, obstacleDeformation ); amount = pow( amount, obstacleDeformationPower ) * obstacleDeformation;
return worldPosition + normalize( direction ) * amount; return worldPosition + normalize( direction ) * amount;
} }
@ -108,10 +110,23 @@ void vertex()
albedoColor = mix( albedo.rgb, HSLtoRGB( albedoHSL ), hslVariation.w ); albedoColor = mix( albedo.rgb, HSLtoRGB( albedoHSL ), hslVariation.w );
if ( obstaclesEnabeld )
{
vec3 originalWorldVertex = worldVertex;
worldVertex = deform( worldVertex, obstacle1 );
worldVertex = deform( worldVertex, obstacle2 );
worldVertex = deform( worldVertex, obstacle3 );
worldVertex = deform( worldVertex, obstacle4 );
worldVertex = limitDeform( originalWorldVertex, worldVertex );
}
if ( windEnabled ) if ( windEnabled )
{ {
float windAmount = normalizeToRange01( VERTEX.y, windStart, windEnd ); float windAmount = normalizeToRange01( VERTEX.y, windStart, windEnd );
float rawWindAmount = windAmount; float rawWindAmount = windAmount;
windAmount = mix( windAmount, windAmount * windAmount, windWeightCurve ); windAmount = mix( windAmount, windAmount * windAmount, windWeightCurve );
@ -120,20 +135,11 @@ void vertex()
float strength = texture( windNoise, windUV + windNoiseStrengthOffset ).r * windStrength; float strength = texture( windNoise, windUV + windNoiseStrengthOffset ).r * windStrength;
vec2 circle = onCircle( angle ) * strength; vec2 circle = onCircle( angle ) * strength;
vec3 originalWorldVertex = worldVertex;
worldVertex += vec3( circle.x, 0, circle.y ) * windAmount; worldVertex += vec3( circle.x, 0, circle.y ) * windAmount;
// VERTEX = worldToLocal( worldVertex + vec3( circle.x, 0, circle.y ) * windAmount, MODEL_MATRIX ); // VERTEX = worldToLocal( worldVertex + vec3( circle.x, 0, circle.y ) * windAmount, MODEL_MATRIX );
if ( obstaclesEnabeld )
{
worldVertex = deform( worldVertex, obstacle1 );
worldVertex = deform( worldVertex, obstacle2 );
worldVertex = deform( worldVertex, obstacle3 );
worldVertex = deform( worldVertex, obstacle4 );
worldVertex = limitDeform( originalWorldVertex, worldVertex );
}
VERTEX = worldToLocal( worldVertex, MODEL_MATRIX ); VERTEX = worldToLocal( worldVertex, MODEL_MATRIX );
float minY = min( VERTEX.y, 0 ); // VERTEX.y = mix( VERTEX.y, max( 0, VERTEX.y - strength * windAmount), windHeightCompensation * 2.0f ); float minY = min( VERTEX.y, 0 ); // VERTEX.y = mix( VERTEX.y, max( 0, VERTEX.y - strength * windAmount), windHeightCompensation * 2.0f );

View File

@ -30,7 +30,7 @@ namespace Rokojori
public Node3D[] sourceNodes = []; public Node3D[] sourceNodes = [];
[ExportToolButton( "Combine")] [ExportToolButton( "Combine")]
public Callable CombineButton => Callable.From( Combine ); public Callable CombineButton => Callable.From( ()=>{ Combine(); } );
[ExportGroup( "Mesh")] [ExportGroup( "Mesh")]
[Export] [Export]
@ -105,18 +105,8 @@ namespace Rokojori
{ {
if ( ! _meshGeometryCache.Has( surface.mesh, surface.index ) ) if ( ! _meshGeometryCache.Has( surface.mesh, surface.index ) )
{ {
// var arrayMesh = surface.mesh as ArrayMesh;
// if ( arrayMesh == null )
// {
// arrayMesh = new ArrayMesh();
// var st = new SurfaceTool();
// st.Begin( Mesh.PrimitiveType.Triangles );
// st.CreateFrom( surface.mesh, surface.index );
// st.Commit( arrayMesh );
// }
var mg = MeshGeometry.From( surface.mesh, null, surface.index ); var mg = MeshGeometry.From( surface.mesh, null, surface.index );
mg.EnsureIndices();
_meshGeometryCache.Set( surface.mesh, surface.index, mg ); _meshGeometryCache.Set( surface.mesh, surface.index, mg );
this.LogInfo( "Created mesh with triangles:", mg.numTriangles ); this.LogInfo( "Created mesh with triangles:", mg.numTriangles );
@ -208,6 +198,11 @@ namespace Rokojori
async Task CombineMaterials() async Task CombineMaterials()
{ {
if ( ! combineMaterials )
{
return;
}
_materials.ForEach( _materials.ForEach(
m => m =>
{ {

View File

@ -162,6 +162,43 @@ namespace Rokojori
{ {
list = list == null ? new List<Transformable<MeshSurface>>() : list; list = list == null ? new List<Transformable<MeshSurface>>() : list;
if ( n is CsgShape3D c )
{
// RJLog.Log( "Extracting:", c, c.IsRootShape() );
if ( ! c.IsRootShape() )
{
return list;
}
var meshesData = c.GetMeshes();
// RJLog.Log( "MeshData:", meshesData );
// RJLog.Log( "MeshData 0:",meshesData[ 0 ] );
// RJLog.Log( "MeshData 1:", meshesData[ 1 ] );
var trsf = (Transform3D) meshesData[ 0 ] * c.Transform;
var mesh = (ArrayMesh) meshesData[ 1 ];
var mg = MeshGeometry.From( mesh );
Material material = null;
if ( c is CsgBox3D bx ){ material = bx.Material; }
if ( c is CsgCylinder3D cy ){ material = cy.Material; }
if ( c is CsgMesh3D ms ){ material = ms.Material; }
if ( c is CsgPolygon3D pl ){ material = pl.Material; }
if ( c is CsgSphere3D sp ){ material = sp.Material; }
if ( c is CsgTorus3D tr ){ material = tr.Material; }
RJLog.Log( "MeshInfo ", c, mesh, material, "\n",
"tris:", mg.numTriangles
);
var surface = new MeshSurface( mesh, material, 0, c );
list.Add( new Transformable<MeshSurface>( surface, trsf ) );
}
if ( n is MeshInstance3D mi ) if ( n is MeshInstance3D mi )
{ {
@ -187,6 +224,7 @@ namespace Rokojori
} }
} }
if ( n is MultiMeshInstance3D mmi ) if ( n is MultiMeshInstance3D mmi )
{ {
var owner = mmi; var owner = mmi;

View File

@ -277,7 +277,7 @@ namespace Rokojori
public List<CustomMeshAttributeList> customMeshAttributes = new List<CustomMeshAttributeList>(); public List<CustomMeshAttributeList> customMeshAttributes = new List<CustomMeshAttributeList>();
public int numTriangles => indices.Count / 3; public int numTriangles => indices.Count == 0 && vertices.Count > 0 ? vertices.Count / 3 : indices.Count / 3;
public static MeshGeometry From( MeshInstance3D meshInstance3D ) public static MeshGeometry From( MeshInstance3D meshInstance3D )
@ -285,22 +285,43 @@ namespace Rokojori
return From( (ArrayMesh)meshInstance3D.Mesh, meshInstance3D.GlobalTransform ); return From( (ArrayMesh)meshInstance3D.Mesh, meshInstance3D.GlobalTransform );
} }
public static MeshGeometry CreateWithSurfaceTool( Mesh mesh, Transform3D? trsf = null, int index = 0 )
{
var arrayMesh = new ArrayMesh();
var st = new SurfaceTool();
st.Begin( Mesh.PrimitiveType.Triangles );
st.CreateFrom( mesh, index );
st.Commit( arrayMesh );
return From( arrayMesh, trsf, 0 );
}
public static MeshGeometry From( Mesh mesh, Transform3D? trsf = null, int index = 0 ) public static MeshGeometry From( Mesh mesh, Transform3D? trsf = null, int index = 0 )
{ {
var arrayMesh = mesh as ArrayMesh; var arrayMesh = mesh as ArrayMesh;
if ( arrayMesh == null ) if ( arrayMesh == null )
{ {
arrayMesh = new ArrayMesh(); return CreateWithSurfaceTool( mesh, trsf, index );
var st = new SurfaceTool();
st.Begin( Mesh.PrimitiveType.Triangles );
st.CreateFrom( mesh, index );
st.Commit( arrayMesh );
} }
return From( arrayMesh, trsf, 0 ); return From( arrayMesh, trsf, 0 );
} }
public void EnsureIndices()
{
if ( indices == null || indices.Count == 0 )
{
indices = new List<int>();
for ( int i = 0; i < vertices.Count; i++ )
{
indices.Add( i );
}
}
}
public static MeshGeometry From( ArrayMesh mesh, Transform3D? trsf = null, int index = 0 ) public static MeshGeometry From( ArrayMesh mesh, Transform3D? trsf = null, int index = 0 )
{ {
@ -315,6 +336,8 @@ namespace Rokojori
var vertices = arrays[ (int) Mesh.ArrayType.Vertex ]; var vertices = arrays[ (int) Mesh.ArrayType.Vertex ];
// RJLog.Log( "Verts:", (( Vector3[] )vertices ).Length );
if ( Variant.Type.Nil != vertices.VariantType ) if ( Variant.Type.Nil != vertices.VariantType )
{ {
mg.vertices = new List<Vector3>( vertices.AsVector3Array() ); mg.vertices = new List<Vector3>( vertices.AsVector3Array() );
@ -1532,7 +1555,7 @@ namespace Rokojori
var surfaceArray = new Godot.Collections.Array(); var surfaceArray = new Godot.Collections.Array();
surfaceArray.Resize( (int) Mesh.ArrayType.Max ); surfaceArray.Resize( (int) Mesh.ArrayType.Max );
var flags = Mesh.ArrayFormat.FormatVertex | Mesh.ArrayFormat.FormatIndex; var flags = Mesh.ArrayFormat.FormatVertex;
if ( vertices != null && vertices.Count != 0 ) if ( vertices != null && vertices.Count != 0 )
{ {
@ -1568,6 +1591,18 @@ namespace Rokojori
surfaceArray[ (int) Mesh.ArrayType.Index ] = indices.ToArray(); surfaceArray[ (int) Mesh.ArrayType.Index ] = indices.ToArray();
flags |= Mesh.ArrayFormat.FormatIndex; flags |= Mesh.ArrayFormat.FormatIndex;
} }
else
{
var indexArray = new int[ vertices.Count ];
for ( int i = 0; i < indexArray.Length; i++ )
{
indexArray[ i ] = i;
}
surfaceArray[ (int) Mesh.ArrayType.Index ] = indexArray;
flags |= Mesh.ArrayFormat.FormatIndex;
}
customMeshAttributes.ForEach( customMeshAttributes.ForEach(
c => c =>

View File

@ -29,7 +29,7 @@ void main()
float gray = color.r * 0.2125 + color.g * 0.7154 + color.b * 0.0721; float gray = color.r * 0.2125 + color.g * 0.7154 + color.b * 0.0721;
color.rgb = vec3( gray ); color.rgb = vec3( gray * 0.5);
imageStore( color_image, uv, color ); imageStore( color_image, uv, color );
} }

View File

@ -0,0 +1,61 @@
using Godot;
using Godot.Collections;
using System.Collections.Generic;
namespace Rokojori
{
[Tool]
[GlobalClass]
public partial class VignetteEffect:SingleShaderCompositorEffect
{
public static readonly string shaderPath = Path( "Vignette/VignetteShader.glsl" );
[Export( PropertyHint.Range, "0,1")]
public float amount = 1.0f;
[Export( PropertyHint.Range, "0.1,2")]
public float radius = 0.5f;
[Export]
public float power = 1.0f;
[Export]
public float offset = 1.0f;
[Export]
public Color colorTop;
[Export]
public Color colorBottom;
protected override void OnConfigure()
{
EffectCallbackType = EffectCallbackTypeEnum.PostTransparent;
_shaderPath = shaderPath;
_groupSize = 8;
}
protected override void SetConstants()
{
constants.Set(
amount,
radius,
power,
offset,
(Vector2) context.internalSize
);
}
protected override void RenderView()
{
context.AssignScreenColorTexture();
context.pushConstants = constants;
context.ProcessComputeProgram();
}
}
}

View File

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

View File

@ -0,0 +1,41 @@
#[compute]
#version 450
layout( local_size_x = 16, local_size_y = 16, local_size_z = 1 ) in;
layout( rgba16f, set = 0, binding = 0)
uniform image2D color_image;
layout(push_constant, std430)
uniform Params
{
float amount;
float radius;
float power;
float offset;
vec2 raster_size;
} params;
void main()
{
ivec2 uv = ivec2( gl_GlobalInvocationID.xy );
ivec2 size = ivec2( params.raster_size );
if ( uv.x >= size.x || uv.y >= size.y )
{
return;
}
vec4 color = imageLoad( color_image, uv );
float d = length( uv - size/2 ) / length( size/2 * params.radius );
d = pow( d, params.power );
float amount = clamp( 1.0 - d + params.offset, 0.0, 1.0 );
color.rgb = mix( color.rgb, vec3( 0.01, 0.01, 0.02 ), ( 1.0 - amount ) * params.amount );
imageStore( color_image, uv, color );
}

View File

@ -0,0 +1,14 @@
[remap]
importer="glsl"
type="RDShaderFile"
uid="uid://bnkadrfrp7jbc"
path="res://.godot/imported/VignetteShader.glsl-97e3dee05027b0474da3bfd8cf9341fa.res"
[deps]
source_file="res://addons/rokojori_action_library/Runtime/Rendering/Compositor/CompositorEffects/Vignette/VignetteShader.glsl"
dest_files=["res://.godot/imported/VignetteShader.glsl-97e3dee05027b0474da3bfd8cf9341fa.res"]
[params]

View File

@ -23,6 +23,7 @@ namespace Rokojori
public int size => _floatIndex + _intIndex; public int size => _floatIndex + _intIndex;
public void Set( params object[] objects ) public void Set( params object[] objects )
{ {
Reset(); Reset();

View File

@ -1,4 +1,4 @@
[gd_resource type="Resource" script_class="InputIconsLibrary" load_steps=74 format=3 uid="uid://dq52vhnqr5m6"] [gd_resource type="Resource" script_class="InputIconsLibrary" load_steps=73 format=3 uid="uid://dq52vhnqr5m6"]
[ext_resource type="Script" uid="uid://c3dpplc2slwd5" path="res://addons/rokojori_action_library/Runtime/Sensors/InputIcons/Definitions/DefaultInputIconDefinition.cs" id="1_64knt"] [ext_resource type="Script" uid="uid://c3dpplc2slwd5" path="res://addons/rokojori_action_library/Runtime/Sensors/InputIcons/Definitions/DefaultInputIconDefinition.cs" id="1_64knt"]
[ext_resource type="Script" uid="uid://bx1cm2837cuuc" path="res://addons/rokojori_action_library/Runtime/Sensors/InputIcons/InputIconsLibrary.cs" id="1_urlfx"] [ext_resource type="Script" uid="uid://bx1cm2837cuuc" path="res://addons/rokojori_action_library/Runtime/Sensors/InputIcons/InputIconsLibrary.cs" id="1_urlfx"]
@ -28,7 +28,6 @@
[ext_resource type="Texture2D" uid="uid://dxwnbh3a3fy8w" path="res://addons/rokojori_action_library/Runtime/Sensors/InputIcons/Graphics/GamePad-Left-Shoulder-Button.svg" id="13_omll7"] [ext_resource type="Texture2D" uid="uid://dxwnbh3a3fy8w" path="res://addons/rokojori_action_library/Runtime/Sensors/InputIcons/Graphics/GamePad-Left-Shoulder-Button.svg" id="13_omll7"]
[ext_resource type="Texture2D" uid="uid://1pfyxi7wifn8" path="res://addons/rokojori_action_library/Runtime/Sensors/InputIcons/Graphics/Keyboard-SpaceKey.svg" id="14_6vom6"] [ext_resource type="Texture2D" uid="uid://1pfyxi7wifn8" path="res://addons/rokojori_action_library/Runtime/Sensors/InputIcons/Graphics/Keyboard-SpaceKey.svg" id="14_6vom6"]
[ext_resource type="Texture2D" uid="uid://bgi8cbw57gka0" path="res://addons/rokojori_action_library/Runtime/Sensors/InputIcons/Graphics/GamePad-MainButton.svg" id="14_n68qo"] [ext_resource type="Texture2D" uid="uid://bgi8cbw57gka0" path="res://addons/rokojori_action_library/Runtime/Sensors/InputIcons/Graphics/GamePad-MainButton.svg" id="14_n68qo"]
[ext_resource type="SystemFont" uid="uid://s1pi67tbxu24" path="res://3rdPerson/Inputs/Jost-Font.tres" id="15_co1yv"]
[ext_resource type="Texture2D" uid="uid://cb8ldiej8234h" path="res://addons/rokojori_action_library/Runtime/Sensors/InputIcons/Graphics/GamePad-Axis-Background.svg" id="18_amimm"] [ext_resource type="Texture2D" uid="uid://cb8ldiej8234h" path="res://addons/rokojori_action_library/Runtime/Sensors/InputIcons/Graphics/GamePad-Axis-Background.svg" id="18_amimm"]
[ext_resource type="Texture2D" uid="uid://ddfvjmi7sva6f" path="res://addons/rokojori_action_library/Runtime/Sensors/InputIcons/Graphics/GamePad-Axis-Pressed.svg" id="19_7x4g0"] [ext_resource type="Texture2D" uid="uid://ddfvjmi7sva6f" path="res://addons/rokojori_action_library/Runtime/Sensors/InputIcons/Graphics/GamePad-Axis-Pressed.svg" id="19_7x4g0"]
[ext_resource type="Script" uid="uid://bvj322mokkq63" path="res://addons/rokojori_action_library/Runtime/Localization/LocaleText.cs" id="20_55eoq"] [ext_resource type="Script" uid="uid://bvj322mokkq63" path="res://addons/rokojori_action_library/Runtime/Localization/LocaleText.cs" id="20_55eoq"]
@ -340,7 +339,6 @@ borderBottom = 0.0
[resource] [resource]
script = ExtResource("1_urlfx") script = ExtResource("1_urlfx")
font = ExtResource("15_co1yv")
fontSize = SubResource("Resource_40bf3") fontSize = SubResource("Resource_40bf3")
iconHeightInEm = 1.5 iconHeightInEm = 1.5
mouseInputIcon = SubResource("Resource_34cgw") mouseInputIcon = SubResource("Resource_34cgw")

View File

@ -19,30 +19,44 @@ namespace Rokojori
[Export] [Export]
public Action onEnd; public Action onEnd;
[ExportGroup("Condition")]
[Export]
public Condition condition;
[Export]
public SceneCondition sceneCondition;
public override void _Process( double delta) public override void _Process( double delta)
{ {
var active = sensor.isActive; if ( sensor == null )
var wasActive = sensor.wasActive;
if ( ! active && ! wasActive )
{ {
return; return;
} }
var started = ! wasActive && active; if ( condition != null && ! condition.Evaluate() )
var ended = wasActive && ! active; {
return;
}
if ( started ) if ( sceneCondition != null && ! sceneCondition.Evaluate() )
{
return;
}
if ( sensor.isDown )
{ {
Action.Trigger( onStart ); Action.Trigger( onStart );
} }
if ( active ) if ( sensor.isHold )
{ {
Action.Trigger( onActive ); Action.Trigger( onActive );
} }
if ( ended ) if ( sensor.isUp )
{ {
Action.Trigger( onActive ); Action.Trigger( onActive );
} }

View File

@ -245,8 +245,13 @@ namespace Rokojori
return; return;
} }
var oldFontSize = X_computedFontSizePixels;
X_computedFontSizePixels = UINumber.Compute( this, settings.fontSize ) * fontZoom; X_computedFontSizePixels = UINumber.Compute( this, settings.fontSize ) * fontZoom;
if ( oldFontSize != X_computedFontSizePixels )
{
_fontSizeFlag = true;
}
if ( Theme != null ) if ( Theme != null )
{ {