Outlines
This commit is contained in:
parent
5c4afd2dfe
commit
b866c2ef9e
|
@ -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() );
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ namespace Rokojori
|
|||
public HighlightActionType type;
|
||||
|
||||
[Export]
|
||||
public Highlighter highlighter;
|
||||
public HighlightEffect highlighter;
|
||||
|
||||
[Export]
|
||||
public Node3D[] targets;
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -27,7 +27,7 @@ namespace Rokojori
|
|||
ResourceLoader.Load<T>( _path ) :
|
||||
_converter( ResourceLoader.Load( _path ) );
|
||||
|
||||
RJLog.Log( _path, _resource );
|
||||
// RJLog.Log( _path, _resource );
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ namespace Rokojori
|
|||
|
||||
[ExportGroup("Highlighting")]
|
||||
[Export]
|
||||
public HighlightFlag highlightFlag;
|
||||
public HighlightEffect highlightEffect;
|
||||
|
||||
[Export]
|
||||
public Node3D[] highlightTargets;
|
||||
|
|
|
@ -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 )
|
||||
if ( p.highlightEffect == null || p.highlightTargets == null || p.highlightTargets.Length == 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var highlighterIndex = Arrays.FindIndex( highlighters, ( h )=> h.flag == pointable.highlightFlag );
|
||||
|
||||
if ( highlighterIndex == -1 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var highlighter = highlighters[ highlighterIndex ];
|
||||
|
||||
highlighter.Highlight( type, p.highlightTargets );
|
||||
p.highlightEffect.Highlight( type, p.highlightTargets );
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,6 @@ namespace Rokojori
|
|||
|
||||
public void Update( float delta )
|
||||
{
|
||||
|
||||
sensor.ProcessSensor( this, delta );
|
||||
|
||||
if ( ! sensor.continous && sensor.value == _lastValue )
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -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 );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
"
|
Binary file not shown.
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue