This commit is contained in:
Josef 2025-01-18 21:02:20 +01:00
parent 5c4afd2dfe
commit b866c2ef9e
18 changed files with 376 additions and 119 deletions

View File

@ -51,9 +51,7 @@ namespace Rokojori
actionID = DispatchStart();
var random = LCG.Randomized();
var networkSeed = random.GetSeed();
var random = LCG.WithSeed( networkSeed );
// RJLog.Log( "Setting actionID id", actionID, GetLastSequenceActionID() );

View File

@ -15,7 +15,7 @@ namespace Rokojori
public HighlightActionType type;
[Export]
public Highlighter highlighter;
public HighlightEffect highlighter;
[Export]
public Node3D[] targets;

View File

@ -6,10 +6,234 @@ using Godot;
namespace Rokojori
{
public enum HighlightActionType
{
Start,
End
}
public class HighlightAnimation
{
public Node3D[] targets;
public int tweenID = -1;
public List<Material> materials = new List<Material>();
public float phase;
}
[Tool]
[GlobalClass]
public partial class HighlightEffect:Resource
{
[Export]
public TimeLine timeline;
[Export]
public float inDuration;
[Export]
public Curve inCurve = MathX.Curve( 0, 1 );
[Export]
public float outDuration;
[Export]
public Curve outCurve = MathX.Curve( 0, 1 );
[Export]
public HDRColor color;
public enum MaterialMode
{
Flat_Outline,
Custom_Material
}
[Export]
public MaterialMode materialMode;
[Export]
public Material customMaterial;
[Export]
public ColorPropertyName customColorProperty;
List<HighlightAnimation> _active = new List<HighlightAnimation>();
public void Highlight( HighlightActionType type, Node3D[] targets )
{
if ( HighlightActionType.Start == type )
{
StartHighlight( targets );
}
else if ( HighlightActionType.End == type )
{
EndHighlight( targets );
}
}
void StartHighlight( Node3D[] targets )
{
var animation = _active.Find( a => Arrays.AreEntriesEqual( a.targets, targets ) );
var hdrColor = color.GetHDRColor();
var colorTransparent = ColorX.Fade( hdrColor, 0 );
if ( animation == null )
{
animation = new HighlightAnimation();
animation.targets = targets;
_active.Add( animation );
Material material = null;
if ( MaterialMode.Flat_Outline == materialMode )
{
var outlineMaterial = new OutlineMaterial();
outlineMaterial.albedo.Set( colorTransparent );
material = outlineMaterial;
}
else if ( MaterialMode.Custom_Material == materialMode )
{
material = (Material) customMaterial.Duplicate();
customColorProperty.Set( material, colorTransparent );
}
Arrays.ForEach( targets,
t =>
{
var m = (Material) material.Duplicate( true );
animation.materials.Add( m );
Materials.AddOverlay( t, m );
}
);
}
var startPhase = animation.phase;
animation.tweenID = TimeLineManager.Tween( timeline, inDuration,
( id, type, phase )=>
{
// RJLog.Log( "Start Highlight: ", id, "Active:",animation.tweenID, "Phase:", phase );
if ( animation.tweenID != id )
{
return;
}
animation.phase = MathX.Map( phase, 0, 1, startPhase, 1 );
var p = animation.phase;
if ( inCurve != null )
{
p = inCurve.Sample( p );
}
var tweenColor = ColorX.Fade( hdrColor, p );
if ( TimeLineSpanUpdateType.End == type )
{
tweenColor = hdrColor;
animation.phase = 1;
}
animation.materials.ForEach(
( m )=>
{
if ( MaterialMode.Flat_Outline == materialMode )
{
var outlineMaterial = ( OutlineMaterial ) m;
outlineMaterial.albedo.Set( tweenColor );
}
else if ( MaterialMode.Custom_Material == materialMode )
{
customColorProperty.Set( m, tweenColor);
}
}
);
}
);
}
void EndHighlight( Node3D[] targets )
{
var animation = _active.Find( a => Arrays.AreEntriesEqual( a.targets, targets ) );
if ( animation == null )
{
// RJLog.Log( "No animation found:", targets );
return;
}
var startPhase = animation.phase;
var hdrColor = ColorX.Fade( color.GetHDRColor(), startPhase );
var colorTransparent = ColorX.Fade( hdrColor, 0 );
animation.tweenID = TimeLineManager.Tween( timeline, outDuration,
( id, type, phase )=>
{
// RJLog.Log( "End Highlight: ", id, "Active:",animation.tweenID, "Phase:", phase );
if ( animation.tweenID != id )
{
return;
}
animation.phase = MathX.Map( phase, 0, 1, startPhase, 0 );
var p = animation.phase;
if ( outCurve != null )
{
p = outCurve.Sample( p );
}
var tweenColor = ColorX.Fade( hdrColor, p );
if ( TimeLineSpanUpdateType.End == type )
{
tweenColor = colorTransparent;
animation.phase = 0;
for ( int i = 0; i < animation.targets.Length; i ++ )
{
Materials.RemoveOverlay( targets[ i ], animation.materials[ i ] );
}
_active.Remove( animation );
}
else
{
animation.materials.ForEach(
( m )=>
{
if ( MaterialMode.Flat_Outline == materialMode )
{
var outlineMaterial = ( OutlineMaterial ) m;
outlineMaterial.albedo.Set( tweenColor );
}
else if ( MaterialMode.Custom_Material == materialMode )
{
customColorProperty.Set( m, tweenColor );
}
}
);
}
}
);
}
}
}

View File

@ -1,65 +0,0 @@
using System.Collections;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Text;
using Godot;
namespace Rokojori
{
public enum HighlightActionType
{
Start,
End
}
public class HighlightTargets
{
public Node3D[] targets;
public int activeAnimationTarget = -1;
public List<Material> originalMaterial;
public List<Material> animationMaterial;
}
[Tool]
[GlobalClass]
public partial class Highlighter:Node
{
[Export]
public HighlightFlag flag;
[Export]
public Material material;
List<HighlightTargets> _activeTargets = new List<HighlightTargets>();
public void Highlight( HighlightActionType type, Node3D[] targets )
{
if ( HighlightActionType.End == type )
{
var t = _activeTargets.Find( a => a.targets == targets );
if ( t == null )
{
return;
}
// Get materials
// Animate
// Swap Original Material;
// Remove Materials;
}
else if ( HighlightActionType.Start == type )
{
// Create target
// Create materials
// Swap animation materials
// Animate
}
}
}
}

View File

@ -0,0 +1,20 @@
[gd_resource type="Resource" script_class="HighlightEffect" load_steps=5 format=3 uid="uid://dadr1kd14m7g3"]
[ext_resource type="Script" path="res://addons/rokojori_action_library/Runtime/Animation/HDRColor.cs" id="1_sk831"]
[ext_resource type="Script" path="res://addons/rokojori_action_library/Runtime/Animation/Highlight/HighlightEffect.cs" id="2_pq63c"]
[ext_resource type="Resource" uid="uid://h6oi6vkj4c2m" path="res://addons/rokojori_action_library/Runtime/Time/TimeLines/RealTime.tres" id="3_8mahg"]
[sub_resource type="Resource" id="Resource_27v41"]
script = ExtResource("1_sk831")
color = Color(1, 1, 1, 1)
colorMultiply = 1.0
rgbMultiply = 1.0
alphaMultiply = 1.0
[resource]
script = ExtResource("2_pq63c")
timeline = ExtResource("3_8mahg")
inDuration = 0.1
outDuration = 0.1
color = SubResource("Resource_27v41")
materialMode = 0

View File

@ -34,6 +34,17 @@ namespace Rokojori
return new Color( c.X, c.Y, c.Z, c.W );
}
public static Color Fade( Color color, float fade )
{
color.A = color.A * fade;
return color;
}
public static Color SetAlpha( Color color, float alpha )
{
color.A = alpha;
return color;
}
}
}

View File

@ -27,7 +27,7 @@ namespace Rokojori
ResourceLoader.Load<T>( _path ) :
_converter( ResourceLoader.Load( _path ) );
RJLog.Log( _path, _resource );
// RJLog.Log( _path, _resource );
}

View File

@ -15,17 +15,34 @@ namespace Rokojori
[Export]
public Sensor button;
public override void _Ready()
{
SensorManager.Register( this, button );
}
public override void _ExitTree()
{
SensorManager.Unregister( this, button );
}
public void _OnSensor( SensorEvent se )
{
if ( pointer == null || pointer.pointable == null )
{
return;
}
if ( ! se.isDown )
{
return;
}
var interactable = Nodes.Find<Interactable>( pointer.pointable.GetParent() );
if ( interactable == null )
{
return;
}

View File

@ -26,7 +26,7 @@ namespace Rokojori
[ExportGroup("Highlighting")]
[Export]
public HighlightFlag highlightFlag;
public HighlightEffect highlightEffect;
[Export]
public Node3D[] highlightTargets;

View File

@ -15,9 +15,6 @@ namespace Rokojori
[Export]
public Caster caster;
[Export]
public Highlighter[] highlighters;
public override void _Process( double delta )
{
if ( caster == null )
@ -55,21 +52,12 @@ namespace Rokojori
void Highlight( HighlightActionType type, Pointable p )
{
if ( p.highlightFlag == null || p.highlightTargets == null || p.highlightTargets.Length == 0 )
{
return;
}
var highlighterIndex = Arrays.FindIndex( highlighters, ( h )=> h.flag == pointable.highlightFlag );
if ( highlighterIndex == -1 )
if ( p.highlightEffect == null || p.highlightTargets == null || p.highlightTargets.Length == 0 )
{
return;
}
var highlighter = highlighters[ highlighterIndex ];
highlighter.Highlight( type, p.highlightTargets );
p.highlightEffect.Highlight( type, p.highlightTargets );
}
}

View File

@ -20,8 +20,7 @@ namespace Rokojori
}
public void Update( float delta )
{
{
sensor.ProcessSensor( this, delta );
if ( ! sensor.continous && sensor.value == _lastValue )

View File

@ -0,0 +1,50 @@
using Godot;
namespace Rokojori
{
public class Outline
{
public static readonly CachedResource<Shader> shader = new CachedResource<Shader>(
"res://addons/rokojori_action_library/Runtime/Shading/Shaders/Effects/Outline/Outline.gdshader"
);
public static readonly ColorPropertyName albedo = ColorPropertyName.Create( "albedo" );
public static readonly FloatPropertyName size = FloatPropertyName.Create( "size" );
public static readonly FloatPropertyName sizeCloseScale = FloatPropertyName.Create( "sizeCloseScale" );
public static readonly FloatPropertyName sizeFarScale = FloatPropertyName.Create( "sizeFarScale" );
public static readonly FloatPropertyName closeDistance = FloatPropertyName.Create( "closeDistance" );
public static readonly FloatPropertyName farDistance = FloatPropertyName.Create( "farDistance" );
}
public partial class OutlineMaterial:CustomMaterial
{
public static readonly CachedResource<OutlineMaterial> BoldYellow = CustomMaterial.Cached<OutlineMaterial>(
"res://addons/rokojori_action_library/Runtime/Shading/Shaders/Effects/Outline/Outline Bold Yellow.material"
);
public static readonly CachedResource<OutlineMaterial> ThinWhite = CustomMaterial.Cached<OutlineMaterial>(
"res://addons/rokojori_action_library/Runtime/Shading/Shaders/Effects/Outline/Outline Thin White.material"
);
public readonly CustomMaterialProperty<Color> albedo;
public readonly CustomMaterialProperty<float> size;
public readonly CustomMaterialProperty<float> sizeCloseScale;
public readonly CustomMaterialProperty<float> sizeFarScale;
public readonly CustomMaterialProperty<float> closeDistance;
public readonly CustomMaterialProperty<float> farDistance;
public OutlineMaterial()
{
Shader = Outline.shader.Get();
albedo = new CustomMaterialProperty<Color>( this, Outline.albedo );
size = new CustomMaterialProperty<float>( this, Outline.size );
sizeCloseScale = new CustomMaterialProperty<float>( this, Outline.sizeCloseScale );
sizeFarScale = new CustomMaterialProperty<float>( this, Outline.sizeFarScale );
closeDistance = new CustomMaterialProperty<float>( this, Outline.closeDistance );
farDistance = new CustomMaterialProperty<float>( this, Outline.farDistance );
}
}
}

View File

@ -0,0 +1,27 @@
shader_type spatial;
render_mode blend_mix, world_vertex_coords, depth_draw_opaque, cull_front, diffuse_burley, specular_schlick_ggx, unshaded;
#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"
uniform vec4 albedo : source_color;
uniform float size:hint_range(0,10) = 1;
uniform float sizeCloseScale : hint_range(0,10) = 1;
uniform float sizeFarScale : hint_range(0,10) = 0.5;
uniform float closeDistance = 20;
uniform float farDistance = 40;
void vertex()
{
float cameraDistance = distance( VERTEX, CAMERA_POSITION_WORLD );
float outlineSize = size * mapClamped( cameraDistance, closeDistance, farDistance, sizeCloseScale, sizeFarScale );
VERTEX += NORMAL * outlineSize/500.0 * cameraDistance;
}
void fragment()
{
ALBEDO = albedo.rgb;
ALPHA = albedo.a;
}

View File

@ -1,31 +0,0 @@
[gd_resource type="Shader" format=3 uid="uid://bmgpmbthlfon3"]
[resource]
code = "// NOTE: Shader automatically converted from Godot Engine 4.3.stable.mono's StandardMaterial3D.
shader_type spatial;
render_mode blend_mix, world_vertex_coords, depth_draw_opaque, cull_front, diffuse_burley, specular_schlick_ggx, unshaded;
#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\"
uniform vec4 albedo : source_color;
uniform float sizeClose : hint_range(0,100) = 1;
uniform float sizeFar : hint_range(0,100) =1;
uniform float closeDistance = 5;
uniform float farDistance = 100;
void vertex()
{
float cameraDistance = distance( VERTEX, CAMERA_POSITION_WORLD );
float size = mapClamped( cameraDistance, closeDistance, farDistance, sizeClose, sizeFar );
VERTEX += NORMAL * size/500.0 * cameraDistance;
}
void fragment()
{
ALBEDO = albedo.rgb;
}
"

View File

@ -72,6 +72,25 @@ namespace Rokojori
runner.Modulate( c, onReady );
}
public static int Tween( TimeLine timeline, float duration, Action<int,TimeLineSpanUpdateType,float> callback )
{
timeline = TimeLine.IfNull_ReplaceByGameTime( timeline );
var startTime = GetPosition( timeline );
var spanID = TimeLineScheduler.ScheduleSpanIn( timeline, 0, duration,
( int id, TimeLineSpanUpdateType type )=>
{
var timeNow = GetPosition( timeline );
var elapsed = timeNow - startTime;
var phase = Mathf.Clamp( elapsed / duration, 0, 1 );
callback( id, type, phase );
}
);
return spanID;
}
void UpdateRealTime( double engineDelta )
{
var now = DateTime.Now;