Camera/Adjustments Udpates
This commit is contained in:
parent
72ab6d5df4
commit
5ede8f7dff
|
|
@ -0,0 +1,40 @@
|
|||
|
||||
#if TOOLS
|
||||
|
||||
using Godot;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Rokojori;
|
||||
|
||||
[Tool]
|
||||
public partial class DeduplicatingExportPlugin : EditorExportPlugin
|
||||
{
|
||||
private HashSet<string> _seenPaths = new HashSet<string>();
|
||||
|
||||
public override string _GetName() => "RokojoriDeduplicatingExport";
|
||||
|
||||
public override void _ExportBegin( string[] features, bool isDebug, string path, uint flags )
|
||||
{
|
||||
_seenPaths.Clear();
|
||||
GD.Print( "[DeduplicatingExport] Export started: ", path );
|
||||
}
|
||||
|
||||
public override void _ExportFile( string path, string type, string[] features )
|
||||
{
|
||||
if ( ! _seenPaths.Add( path ) )
|
||||
{
|
||||
GD.Print( "[DeduplicatingExport] SKIPPED (duplicate): ", path );
|
||||
Skip();
|
||||
return;
|
||||
}
|
||||
|
||||
GD.Print( "[DeduplicatingExport] included: ", path );
|
||||
}
|
||||
|
||||
public override void _ExportEnd()
|
||||
{
|
||||
GD.Print( "[DeduplicatingExport] Export ended. Total unique files: ", _seenPaths.Count );
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1 @@
|
|||
uid://2vyvvmkop2ec
|
||||
|
|
@ -64,6 +64,7 @@ public partial class RokojoriPlugin: EditorPlugin
|
|||
{
|
||||
GizmoDrawerPlugin gizmoDrawerPlugin = new GizmoDrawerPlugin();
|
||||
GodotEditorInspectorTools inspectorTools = new GodotEditorInspectorTools();
|
||||
DeduplicatingExportPlugin deduplicatingExportPlugin = new DeduplicatingExportPlugin();
|
||||
|
||||
public static readonly string path = "res://addons/rokojori_action_library";
|
||||
|
||||
|
|
@ -163,6 +164,7 @@ public partial class RokojoriPlugin: EditorPlugin
|
|||
this.LogInfo();
|
||||
|
||||
AddNode3DGizmoPlugin( gizmoDrawerPlugin );
|
||||
AddExportPlugin( deduplicatingExportPlugin );
|
||||
|
||||
inspectorTools.rokojoriPlugin = this;
|
||||
inspectorTools.AddPlugins();
|
||||
|
|
@ -173,6 +175,7 @@ public partial class RokojoriPlugin: EditorPlugin
|
|||
this.LogInfo();
|
||||
|
||||
RemoveNode3DGizmoPlugin( gizmoDrawerPlugin );
|
||||
RemoveExportPlugin( deduplicatingExportPlugin );
|
||||
|
||||
inspectorTools.rokojoriPlugin = this;
|
||||
inspectorTools.RemovePlugins();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,51 @@
|
|||
using Rokojori;
|
||||
using Godot;
|
||||
|
||||
namespace Rokojori;
|
||||
|
||||
[GlobalClass,Tool]
|
||||
public partial class AdjustmentsDesigner: Node
|
||||
{
|
||||
[Export]
|
||||
public AdjustmentsStack stack = new AdjustmentsStack();
|
||||
|
||||
[Export]
|
||||
public bool autoUpdate = false;
|
||||
|
||||
[Export]
|
||||
public WorldEnvironment environment;
|
||||
|
||||
[ExportToolButton( "Update Adjustments" )]
|
||||
public Callable updateAdjustmentsButton => Callable.From(
|
||||
()=>
|
||||
{
|
||||
ProcessStack();
|
||||
}
|
||||
);
|
||||
|
||||
public override void _Process( double delta )
|
||||
{
|
||||
if ( ! Engine.IsEditorHint() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! autoUpdate )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ProcessStack();
|
||||
|
||||
}
|
||||
|
||||
void ProcessStack()
|
||||
{
|
||||
stack.GenerateAdjustmentsTexture();
|
||||
|
||||
if ( environment != null )
|
||||
{
|
||||
environment.Environment.AdjustmentColorCorrection = stack.adjustmentsTexture;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
uid://8yy5v376kadx
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
using Rokojori;
|
||||
using Godot;
|
||||
|
||||
namespace Rokojori;
|
||||
|
||||
[GlobalClass,Tool]
|
||||
public abstract partial class AdjustmentsFilter: Resource
|
||||
{
|
||||
[Export( PropertyHint.Range, "0,1" )]
|
||||
public float amount;
|
||||
|
||||
[Export]
|
||||
public bool enabled = true;
|
||||
|
||||
|
||||
[Export]
|
||||
public AdjustmentsMask[] masks;
|
||||
|
||||
public virtual void PrepareFilter()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public Color GetFiltered( Color rgb )
|
||||
{
|
||||
if ( ! enabled )
|
||||
{
|
||||
return rgb ;
|
||||
}
|
||||
|
||||
var filtered = _FilterColor( rgb );
|
||||
|
||||
var mask = amount;
|
||||
|
||||
if ( masks != null && masks.Length > 0 )
|
||||
{
|
||||
var maskStack = 0f;
|
||||
|
||||
for ( int i = 0; i < masks.Length; i++ )
|
||||
{
|
||||
var maskIndex = ( masks.Length - 1 ) - i ;
|
||||
var maskValue = masks[ maskIndex ].GetMask( rgb );
|
||||
var maskBefore = i == 0 ? null : masks[ maskIndex + 1 ];
|
||||
|
||||
maskStack = AdjustmentsMask.Blend( maskBefore, maskStack, masks[ maskIndex ], maskValue );
|
||||
}
|
||||
|
||||
mask *= maskStack;
|
||||
}
|
||||
|
||||
|
||||
return rgb.Lerp( filtered, mask );
|
||||
|
||||
}
|
||||
|
||||
abstract protected Color _FilterColor( Color rgb );
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
uid://3orxcbnth5i6
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
using Rokojori;
|
||||
using Godot;
|
||||
|
||||
namespace Rokojori;
|
||||
|
||||
[GlobalClass,Tool]
|
||||
public abstract partial class AdjustmentsMask: Resource
|
||||
{
|
||||
public enum Mode
|
||||
{
|
||||
Add,
|
||||
Subtract,
|
||||
Multiply,
|
||||
Divide,
|
||||
Max,
|
||||
Min
|
||||
}
|
||||
|
||||
[Export]
|
||||
public Mode mode = Mode.Multiply;
|
||||
|
||||
public abstract float GetMask( Color rgb );
|
||||
|
||||
public static float Blend( AdjustmentsMask bottom, float bottomMask, AdjustmentsMask top, float topMask )
|
||||
{
|
||||
if ( bottom == null )
|
||||
{
|
||||
return bottomMask;
|
||||
}
|
||||
|
||||
if ( Mode.Add == top.mode )
|
||||
{
|
||||
return bottomMask + topMask;
|
||||
}
|
||||
|
||||
if ( Mode.Subtract == top.mode )
|
||||
{
|
||||
return bottomMask - topMask;
|
||||
}
|
||||
|
||||
if ( Mode.Multiply == top.mode )
|
||||
{
|
||||
return bottomMask * topMask;
|
||||
}
|
||||
|
||||
if ( Mode.Divide == top.mode )
|
||||
{
|
||||
return bottomMask / topMask;
|
||||
}
|
||||
|
||||
if ( Mode.Max == top.mode )
|
||||
{
|
||||
return Mathf.Max( bottomMask, topMask );
|
||||
}
|
||||
|
||||
if ( Mode.Min == top.mode )
|
||||
{
|
||||
return Mathf.Min( bottomMask, topMask );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
uid://b7m05qa3ygvy2
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
using Rokojori;
|
||||
using Godot;
|
||||
|
||||
namespace Rokojori;
|
||||
|
||||
[GlobalClass,Tool]
|
||||
public partial class AdjustmentsStack: Resource
|
||||
{
|
||||
[Export]
|
||||
public AdjustmentsFilter[] filters = [];
|
||||
|
||||
[Export( PropertyHint.Range, "0,1" )]
|
||||
public float amount = 1;
|
||||
|
||||
[Export]
|
||||
public bool enabled = true;
|
||||
|
||||
[Export]
|
||||
public int adjustmentSize = 33;
|
||||
|
||||
[Export]
|
||||
public Texture3D adjustmentsTexture;
|
||||
|
||||
public void GenerateAdjustmentsTexture()
|
||||
{
|
||||
filters.ForEach( f => f.PrepareFilter() );
|
||||
|
||||
var luts = new Godot.Collections.Array<Image>();
|
||||
|
||||
for ( int i = 0; i < adjustmentSize; i++ )
|
||||
{
|
||||
luts.Add( Image.CreateEmpty( adjustmentSize, adjustmentSize, false, Image.Format.Rgb8 ) );
|
||||
}
|
||||
|
||||
for ( int bi = 0; bi < adjustmentSize; bi++ )
|
||||
{
|
||||
var image = luts[ bi ];
|
||||
|
||||
var b = bi / ( adjustmentSize - 1f );
|
||||
|
||||
for ( int ri = 0; ri < adjustmentSize; ri++ )
|
||||
{
|
||||
var r = ri / ( adjustmentSize - 1f );
|
||||
|
||||
for ( int gi = 0; gi < adjustmentSize; gi++ )
|
||||
{
|
||||
var g = gi / ( adjustmentSize - 1f );
|
||||
var filtered = GetFilteredColor( new Color( r, g, b ) );
|
||||
image.SetPixel( ri, gi, filtered );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var texture = new ImageTexture3D();
|
||||
|
||||
if ( adjustmentsTexture is ImageTexture3D existing && existing.GetWidth() == adjustmentSize )
|
||||
{
|
||||
existing.Update( luts );
|
||||
}
|
||||
else
|
||||
{
|
||||
texture.Create( Image.Format.Rgb8, adjustmentSize, adjustmentSize, adjustmentSize, false, luts );
|
||||
adjustmentsTexture = texture;
|
||||
}
|
||||
}
|
||||
|
||||
public Color GetFilteredColor( Color rgb )
|
||||
{
|
||||
if ( ! enabled )
|
||||
{
|
||||
return rgb;
|
||||
}
|
||||
|
||||
var originalRGB = rgb;
|
||||
|
||||
filters.ForEach( f => { rgb = f.GetFiltered( rgb ); } );
|
||||
|
||||
|
||||
return originalRGB.Lerp( rgb, amount );
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
uid://bdubaufaxcujo
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
using Rokojori;
|
||||
using Godot;
|
||||
|
||||
namespace Rokojori;
|
||||
|
||||
[GlobalClass,Tool]
|
||||
public partial class AdjustmentsCurvesFilter: AdjustmentsFilter
|
||||
{
|
||||
[Export]
|
||||
public ColorChannelType driverChannel = ColorChannelType.Lightness;
|
||||
|
||||
[Export]
|
||||
public ColorChannelType targetChannel = ColorChannelType.Lightness;
|
||||
|
||||
[Export]
|
||||
public Curve curve;
|
||||
|
||||
public enum MappingMode
|
||||
{
|
||||
Auto,
|
||||
Map,
|
||||
Add
|
||||
}
|
||||
|
||||
[Export]
|
||||
public MappingMode mappingMode = MappingMode.Auto;
|
||||
|
||||
protected override Color _FilterColor( Color rgb )
|
||||
{
|
||||
var driverValue = ColorX.GetNormalizedChannel( rgb, driverChannel );
|
||||
|
||||
var targetValue = curve.Sample( driverValue );
|
||||
|
||||
var mapping = ResolveMappingMode();
|
||||
|
||||
if ( MappingMode.Map == mapping )
|
||||
{
|
||||
return ColorX.SetNormalizedChannel( rgb, targetChannel, targetValue );
|
||||
}
|
||||
else if ( MappingMode.Add == mapping )
|
||||
{
|
||||
var sourceValue = ColorX.GetNormalizedChannel( rgb, targetChannel );
|
||||
|
||||
if ( MappingMode.Auto == mappingMode )
|
||||
{
|
||||
var min = curve.MinValue;
|
||||
var max = curve.MaxValue;
|
||||
targetValue = MathX.MapClamped( targetValue, min, max, -1, 1 );
|
||||
}
|
||||
|
||||
return ColorX.SetNormalizedChannel( rgb, targetChannel, targetValue + sourceValue );
|
||||
}
|
||||
|
||||
return rgb;
|
||||
}
|
||||
|
||||
MappingMode ResolveMappingMode()
|
||||
{
|
||||
if ( MappingMode.Auto == mappingMode )
|
||||
{
|
||||
return driverChannel == targetChannel ? MappingMode.Map : MappingMode.Add;
|
||||
}
|
||||
|
||||
return mappingMode;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
uid://bhegakbwte7hf
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
using Rokojori;
|
||||
using Godot;
|
||||
|
||||
namespace Rokojori;
|
||||
|
||||
[GlobalClass,Tool]
|
||||
public partial class AdjustmentsHueShifter: AdjustmentsFilter
|
||||
{
|
||||
|
||||
[Export]
|
||||
public AdjustmentsHueShifterBand band0 = new AdjustmentsHueShifterBand();
|
||||
|
||||
[Export]
|
||||
public AdjustmentsHueShifterBand band1 = new AdjustmentsHueShifterBand();
|
||||
|
||||
[Export]
|
||||
public AdjustmentsHueShifterBand band2 = new AdjustmentsHueShifterBand();
|
||||
|
||||
|
||||
AdjustmentsHueShifterBand combined = new AdjustmentsHueShifterBand();
|
||||
|
||||
[Export]
|
||||
public bool debug = false;
|
||||
|
||||
[Export]
|
||||
public int numZero = 0;
|
||||
|
||||
public override void PrepareFilter()
|
||||
{
|
||||
numZero = 0;
|
||||
}
|
||||
|
||||
protected override Color _FilterColor( Color rgb )
|
||||
{
|
||||
|
||||
var mask0 = band0 == null ? 0f : band0.GetMask( rgb );
|
||||
var mask1 = band1 == null ? 0f : band1.GetMask( rgb );
|
||||
var mask2 = band2 == null ? 0f : band2.GetMask( rgb );
|
||||
|
||||
var sum = mask0 + mask1 + mask2;
|
||||
|
||||
if ( sum <= 0 )
|
||||
{
|
||||
if ( debug )
|
||||
{
|
||||
numZero ++;
|
||||
// RJLog.Log( "Sum to small of masks", mask0, mask1, mask2 );
|
||||
}
|
||||
|
||||
return rgb;
|
||||
}
|
||||
|
||||
|
||||
|
||||
combined.ResetValues();
|
||||
|
||||
combined.AddChanges( band0, mask0 );
|
||||
combined.AddChanges( band1, mask1 );
|
||||
combined.AddChanges( band2, mask2 );
|
||||
|
||||
// RJLog.Log( "mask", mask0, mask1, mask2,
|
||||
// "hue", combined.hueOffset,
|
||||
// "temp", combined.tempratureOffset,
|
||||
// "sat", combined.saturationOffset,
|
||||
// "light", combined.lightnessOffset
|
||||
// );
|
||||
|
||||
return combined.ProcessColor( rgb );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
uid://b06d5aqfu7aoq
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
using Rokojori;
|
||||
using Godot;
|
||||
|
||||
namespace Rokojori;
|
||||
|
||||
[GlobalClass,Tool]
|
||||
public partial class AdjustmentsHueShifterBand: Resource
|
||||
{
|
||||
|
||||
[Export( PropertyHint.Range, "-60,420")]
|
||||
public float sourceHue = 0;
|
||||
|
||||
[Export( PropertyHint.Range, "0,360")]
|
||||
public float sourceWidth = 30;
|
||||
|
||||
[Export( PropertyHint.Range, "0,1")]
|
||||
public float amount = 1f;
|
||||
|
||||
[Export( PropertyHint.Range, "-180,180")]
|
||||
public float hueOffset = 0;
|
||||
|
||||
[Export( PropertyHint.Range, "-180,180")]
|
||||
public float tempratureOffset = 0;
|
||||
|
||||
[Export( PropertyHint.Range, "-100,100")]
|
||||
public float saturationOffset = 0;
|
||||
|
||||
[Export( PropertyHint.Range, "-100,100")]
|
||||
public float lightnessOffset = 0;
|
||||
|
||||
|
||||
|
||||
|
||||
public void ResetValues()
|
||||
{
|
||||
hueOffset = 0;
|
||||
|
||||
tempratureOffset = 0;
|
||||
|
||||
saturationOffset = 0;
|
||||
|
||||
lightnessOffset = 0;
|
||||
}
|
||||
|
||||
[Export]
|
||||
public float fixedMask = 0;
|
||||
|
||||
public float GetMask( Color color )
|
||||
{
|
||||
if ( fixedMask > 0 )
|
||||
{
|
||||
return fixedMask * amount;
|
||||
}
|
||||
|
||||
var hue = HSLColor.FromRGBA( color ).h;
|
||||
|
||||
var difference = Mathf.Abs( MathX.AngleDifferenceDegrees( sourceHue, hue ) );
|
||||
|
||||
return MathX.Clamp01( 1f - Mathf.Min( 1f, difference / sourceWidth ) ) * amount;
|
||||
}
|
||||
|
||||
public void AddChanges( AdjustmentsHueShifterBand band, float mask )
|
||||
{
|
||||
if ( band == null || mask == 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
hueOffset += band.hueOffset * mask;
|
||||
|
||||
tempratureOffset += band.tempratureOffset * mask;
|
||||
|
||||
saturationOffset += band.saturationOffset * mask;
|
||||
|
||||
lightnessOffset += band.lightnessOffset * mask;
|
||||
}
|
||||
|
||||
public Color ProcessColor( Color color )
|
||||
{
|
||||
var hsl = HSLColor.FromRGBA( color );
|
||||
hsl.h = MathX.Repeat( hsl.h + hueOffset, 360f );
|
||||
|
||||
hsl = hsl.ShiftTemperature( tempratureOffset, saturationOffset / 100f, lightnessOffset/ 100f );
|
||||
|
||||
return hsl;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
uid://cmddo8mo0qulp
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
using Rokojori;
|
||||
using Godot;
|
||||
|
||||
namespace Rokojori;
|
||||
|
||||
[GlobalClass,Tool]
|
||||
public partial class AdjustmentstGradientTint: AdjustmentsFilter
|
||||
{
|
||||
[Export]
|
||||
public GradientTexture1D gradient;
|
||||
|
||||
[Export]
|
||||
public LumaMode lumaMode = LumaMode.Lightness;
|
||||
|
||||
[Export]
|
||||
public ColorBlendModeType colorBlendMode = ColorBlendModeType.Alpha;
|
||||
|
||||
|
||||
protected override Color _FilterColor( Color rgb )
|
||||
{
|
||||
var luma = Luma.Get( rgb, lumaMode );
|
||||
|
||||
var tint = gradient.Gradient.Sample( luma );
|
||||
var amount = tint.A;
|
||||
rgb.A = 1.0f;
|
||||
|
||||
return ColorBlendMode.Blend( colorBlendMode, rgb, tint );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
uid://c5wqcbyxi6fgf
|
||||
|
|
@ -22,6 +22,7 @@ namespace Rokojori
|
|||
[Export]
|
||||
public float pitch;
|
||||
|
||||
|
||||
[Export]
|
||||
public ThirdPersonCameraSettings settings;
|
||||
|
||||
|
|
@ -99,11 +100,15 @@ namespace Rokojori
|
|||
|
||||
var smoothedPitch = Smoothing.Apply( settings.pitchSmoothing, pitch, delta );
|
||||
|
||||
|
||||
|
||||
var pitchState = MathX.NormalizeClamped( pitch, settings.minPitch, settings.maxPitch );
|
||||
var distance = settings.distanceForPitch.Sample( pitchState ) * settings.distanceScale;
|
||||
|
||||
var smoothedDistance = Smoothing.Apply( settings.distanceSmoothing, distance, delta );
|
||||
FOV = settings.fovOffset + ( settings.fovForPitch?.Sample( pitchState ) ?? 0f );
|
||||
|
||||
cameraPosition = targetPosition + Math3D.YawPitchRotation( smoothedYaw, smoothedPitch ) * Vector3.Forward * distance;
|
||||
cameraPosition = targetPosition + Math3D.YawPitchRotation( smoothedYaw, smoothedPitch ) * Vector3.Forward * smoothedDistance;
|
||||
|
||||
cameraForward = ( targetPosition - cameraPosition ).Normalized();
|
||||
// LookAt( targetPosition, Vector3.Up, true );
|
||||
|
|
|
|||
|
|
@ -12,14 +12,16 @@ namespace Rokojori
|
|||
[Export]
|
||||
public Smoothing targetFollowSmoothing = new FrameSmoothing();
|
||||
|
||||
|
||||
|
||||
[Export]
|
||||
public Smoothing yawSmoothing = new FrameSmoothing();
|
||||
|
||||
[Export]
|
||||
public Smoothing pitchSmoothing = new FrameSmoothing();
|
||||
|
||||
[Export]
|
||||
public Smoothing distanceSmoothing = new FrameSmoothing();
|
||||
|
||||
|
||||
[Export]
|
||||
public ThirdPersonCameraData[] deviceData = [];
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,16 @@ namespace Rokojori
|
|||
Alpha,
|
||||
Add,
|
||||
Multiply,
|
||||
Replace
|
||||
|
||||
Screen,
|
||||
Overlay,
|
||||
|
||||
HardLight,
|
||||
SoftLight,
|
||||
|
||||
Color,
|
||||
Hue,
|
||||
Saturation
|
||||
}
|
||||
|
||||
public class ColorBlendMode
|
||||
|
|
@ -17,41 +26,60 @@ namespace Rokojori
|
|||
{
|
||||
switch ( type )
|
||||
{
|
||||
case ColorBlendModeType.Alpha: return Alpha( bottom, top );
|
||||
case ColorBlendModeType.Multiply: return Multiply( bottom, top );
|
||||
case ColorBlendModeType.Add: return Add( bottom, top );
|
||||
case ColorBlendModeType.Replace: return Replace( bottom, top );
|
||||
case ColorBlendModeType.Alpha: return ColorX.Blend( bottom, top );
|
||||
case ColorBlendModeType.Multiply: return ColorX.BlendMultiply( bottom, top );
|
||||
case ColorBlendModeType.Add: return ColorX.BlendAdd( bottom, top );
|
||||
|
||||
case ColorBlendModeType.Screen: return ColorX.BlendScreen( bottom, top );
|
||||
case ColorBlendModeType.Overlay: return ColorX.BlendScreen( bottom, top );
|
||||
|
||||
case ColorBlendModeType.HardLight: return ColorX.BlendHardLight( bottom, top );
|
||||
case ColorBlendModeType.SoftLight: return ColorX.BlendSoftLight( bottom, top );
|
||||
|
||||
case ColorBlendModeType.Color: return ColorX.BlendColor( bottom, top );
|
||||
case ColorBlendModeType.Hue: return ColorX.BlendHue( bottom, top );
|
||||
case ColorBlendModeType.Saturation: return ColorX.BlendSaturation( bottom, top );
|
||||
}
|
||||
|
||||
return new Color( 1, 1, 1, 1 );
|
||||
}
|
||||
|
||||
public static Color Alpha( Color bottom, Color top )
|
||||
{
|
||||
var a = top.A + bottom.A * ( 1f - top.A );
|
||||
// public static Color Alpha( Color bottom, Color top )
|
||||
// {
|
||||
// var a = top.A + bottom.A * ( 1f - top.A );
|
||||
|
||||
var colorBottom = ColorX.RGB( bottom );
|
||||
var colorTop = ColorX.RGB( top );
|
||||
// var colorBottom = ColorX.RGB( bottom );
|
||||
// var colorTop = ColorX.RGB( top );
|
||||
|
||||
var colorRGB = ( colorTop * top.A + colorBottom * bottom.A * ( 1f - top.A ) ) / a;
|
||||
// var colorRGB = ( colorTop * top.A + colorBottom * bottom.A * ( 1f - top.A ) ) / a;
|
||||
|
||||
return ColorX.Create( colorRGB, a );
|
||||
}
|
||||
// return ColorX.Create( colorRGB, a );
|
||||
// }
|
||||
|
||||
public static Color Multiply( Color bottom, Color top )
|
||||
{
|
||||
return bottom * top;
|
||||
}
|
||||
// Color Multiply( Color bottom, Color top )
|
||||
// {
|
||||
// if ( bottom.A <= 0.0 )
|
||||
// {
|
||||
// return top;
|
||||
// }
|
||||
|
||||
// return Alpha( bottom, MultiplyFunction( bottom.rgb, top.rgb ), top.a ) );
|
||||
// }
|
||||
|
||||
public static Color Add( Color bottom, Color top )
|
||||
{
|
||||
return bottom + top;
|
||||
}
|
||||
// public static Color MultiplyFunction( Color bottom, Color top )
|
||||
// {
|
||||
// return bottom * top;
|
||||
// }
|
||||
|
||||
public static Color Replace( Color bottom, Color top )
|
||||
{
|
||||
return top;
|
||||
}
|
||||
// public static Color AddFunction( Color bottom, Color top )
|
||||
// {
|
||||
// return bottom + top;
|
||||
// }
|
||||
|
||||
// public static Color ReplaceFunction( Color bottom, Color top )
|
||||
// {
|
||||
// return top;
|
||||
// }
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -11,7 +11,7 @@ namespace Rokojori
|
|||
Blue,
|
||||
Hue,
|
||||
Saturation,
|
||||
Luminance,
|
||||
Lightness,
|
||||
Alpha
|
||||
}
|
||||
|
||||
|
|
@ -77,7 +77,7 @@ namespace Rokojori
|
|||
return $"RGBtoHSL( {source} ).y";
|
||||
}
|
||||
|
||||
if ( ColorChannelType.Luminance == colorChannelType )
|
||||
if ( ColorChannelType.Lightness == colorChannelType )
|
||||
{
|
||||
return $"RGBtoHSL( {source} ).u";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,6 +40,18 @@ namespace Rokojori
|
|||
return new Vector3( rgba.X, rgba.Y, rgba.Z );
|
||||
}
|
||||
|
||||
public static float GetNormalizedChannel( this Color color, ColorChannelType colorChannelType )
|
||||
{
|
||||
var channel = color.GetChannel( colorChannelType );
|
||||
|
||||
if ( ColorChannelType.Hue == colorChannelType )
|
||||
{
|
||||
channel /= 360.0f;
|
||||
}
|
||||
|
||||
return channel;
|
||||
}
|
||||
|
||||
public static float GetChannel( this Color color, ColorChannelType colorChannelType )
|
||||
{
|
||||
if ( ColorChannelType.Red == colorChannelType )
|
||||
|
|
@ -75,7 +87,7 @@ namespace Rokojori
|
|||
return hsl.s;
|
||||
}
|
||||
|
||||
if ( ColorChannelType.Luminance == colorChannelType )
|
||||
if ( ColorChannelType.Lightness == colorChannelType )
|
||||
{
|
||||
return hsl.l;
|
||||
}
|
||||
|
|
@ -84,6 +96,16 @@ namespace Rokojori
|
|||
|
||||
}
|
||||
|
||||
public static Color SetNormalizedChannel( this Color color, ColorChannelType colorChannelType, float value )
|
||||
{
|
||||
if ( ColorChannelType.Hue == colorChannelType )
|
||||
{
|
||||
value *= 360.0f;
|
||||
}
|
||||
|
||||
return color.SetChannel( colorChannelType, value );
|
||||
}
|
||||
|
||||
public static Color SetChannel( this Color color, ColorChannelType colorChannelType, float value )
|
||||
{
|
||||
if ( ColorChannelType.Red == colorChannelType )
|
||||
|
|
@ -121,7 +143,7 @@ namespace Rokojori
|
|||
color = hsl;
|
||||
}
|
||||
|
||||
if ( ColorChannelType.Luminance == colorChannelType )
|
||||
if ( ColorChannelType.Lightness == colorChannelType )
|
||||
{
|
||||
hsl.l = value;
|
||||
color = hsl;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,53 @@
|
|||
using Godot;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Rokojori.Extensions;
|
||||
namespace Rokojori;
|
||||
|
||||
public enum LumaMode
|
||||
{
|
||||
Lightness,
|
||||
Luminosity_709,
|
||||
Luminosity_601,
|
||||
Average,
|
||||
Min,
|
||||
Max
|
||||
}
|
||||
|
||||
public class Luma
|
||||
{
|
||||
public static float Get( Color rgb, LumaMode mode )
|
||||
{
|
||||
if ( LumaMode.Lightness == mode )
|
||||
{
|
||||
return HSLColor.FromRGBA( rgb ).l;
|
||||
}
|
||||
|
||||
if ( LumaMode.Luminosity_709 == mode )
|
||||
{
|
||||
return rgb.R * 0.2126f + rgb.G * 0.7152f + rgb.B * 0.0722f;
|
||||
}
|
||||
|
||||
if ( LumaMode.Luminosity_601 == mode )
|
||||
{
|
||||
return rgb.R * 0.299f + rgb.G * 0.587f + rgb.B * 0.114f;
|
||||
}
|
||||
|
||||
if ( LumaMode.Average == mode )
|
||||
{
|
||||
return ( rgb.R + rgb.G + rgb.B ) / 3f;
|
||||
}
|
||||
|
||||
if ( LumaMode.Min == mode )
|
||||
{
|
||||
return MathX.Min( rgb.R, rgb.G, rgb.B );
|
||||
}
|
||||
|
||||
if ( LumaMode.Max == mode )
|
||||
{
|
||||
return MathX.Max( rgb.R, rgb.G, rgb.B );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
uid://wxxtcur80snr
|
||||
|
|
@ -245,7 +245,10 @@ namespace Rokojori
|
|||
}
|
||||
|
||||
|
||||
|
||||
public static float AngleDifferenceDegrees( float degreesA, float degreesB )
|
||||
{
|
||||
return Mathf.AngleDifference( degreesA * DegreesToRadians, degreesB * DegreesToRadians ) * RadiansToDegrees;
|
||||
}
|
||||
|
||||
public static float AngleDelta( float degreesA, float degreesB)
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue