Color Correction Update
This commit is contained in:
parent
491ab8b92c
commit
b8fea8ce40
|
@ -20,6 +20,11 @@ namespace Rokojori
|
|||
return RokojoriPlugin.path + "/" + path;
|
||||
}
|
||||
|
||||
public static string GlobalizedPath( string path )
|
||||
{
|
||||
return ProjectSettings.GlobalizePath( Path( path ) );
|
||||
}
|
||||
|
||||
static readonly string RokojoriRootAutoLoad = "RokojoriRootAutoLoad";
|
||||
static readonly string RokojoriRootAutoLoadPath = Path( "Runtime/Godot/Root.cs" );
|
||||
static readonly string RokojoriProjectInternalPath = "res://.rokojori";
|
||||
|
@ -38,7 +43,34 @@ namespace Rokojori
|
|||
|
||||
}
|
||||
|
||||
void EnsureHiddenProjectPath( string resPath )
|
||||
static string CreateTemporaryFilePath()
|
||||
{
|
||||
var directory = RokojoriCachePath + "/temp";
|
||||
|
||||
EnsureHiddenProjectPath( directory );
|
||||
var id = IDGenerator.GenerateID();
|
||||
|
||||
return directory + "/" + id;
|
||||
|
||||
}
|
||||
|
||||
public static string SaveTemporaryJSON( object json )
|
||||
{
|
||||
var path = ProjectSettings.GlobalizePath( CreateTemporaryFilePath() );
|
||||
var result = FilesSync.SaveJSON( path, json );
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
public static string SaveTemporaryUTF8( string text )
|
||||
{
|
||||
var path = ProjectSettings.GlobalizePath( CreateTemporaryFilePath() );
|
||||
var result = FilesSync.SaveUTF8( path, text );
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
static void EnsureHiddenProjectPath( string resPath )
|
||||
{
|
||||
var gdIgnorePath = resPath + "/.gdignore" ;
|
||||
FilesSync.EnsureDirectoryExists( ProjectSettings.GlobalizePath( resPath ) );
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
using Godot;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Rokojori
|
||||
{
|
||||
public enum ColorChannelType
|
||||
{
|
||||
Red,
|
||||
Green,
|
||||
Blue,
|
||||
Hue,
|
||||
Saturation,
|
||||
Luminance,
|
||||
Alpha
|
||||
}
|
||||
}
|
|
@ -5,6 +5,130 @@ namespace Rokojori
|
|||
{
|
||||
public static class ColorX
|
||||
{
|
||||
public static float GetChannel( this Color color, ColorChannelType colorChannelType )
|
||||
{
|
||||
if ( ColorChannelType.Red == colorChannelType )
|
||||
{
|
||||
return color.R;
|
||||
}
|
||||
|
||||
if ( ColorChannelType.Green == colorChannelType )
|
||||
{
|
||||
return color.G;
|
||||
}
|
||||
|
||||
if ( ColorChannelType.Blue == colorChannelType )
|
||||
{
|
||||
return color.B;
|
||||
}
|
||||
|
||||
if ( ColorChannelType.Alpha == colorChannelType )
|
||||
{
|
||||
return color.A;
|
||||
}
|
||||
|
||||
var hsl = HSLColor.FromRGBA( color );
|
||||
|
||||
|
||||
if ( ColorChannelType.Hue == colorChannelType )
|
||||
{
|
||||
return hsl.h;
|
||||
}
|
||||
|
||||
if ( ColorChannelType.Saturation == colorChannelType )
|
||||
{
|
||||
return hsl.s;
|
||||
}
|
||||
|
||||
if ( ColorChannelType.Luminance == colorChannelType )
|
||||
{
|
||||
return hsl.l;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
public static Color SetChannel( this Color color, ColorChannelType colorChannelType, float value )
|
||||
{
|
||||
if ( ColorChannelType.Red == colorChannelType )
|
||||
{
|
||||
color.R = value;
|
||||
}
|
||||
|
||||
if ( ColorChannelType.Green == colorChannelType )
|
||||
{
|
||||
color.G = value;
|
||||
}
|
||||
|
||||
if ( ColorChannelType.Blue == colorChannelType )
|
||||
{
|
||||
color.B = value;
|
||||
}
|
||||
|
||||
if ( ColorChannelType.Alpha == colorChannelType )
|
||||
{
|
||||
color.A = value;
|
||||
}
|
||||
|
||||
var hsl = HSLColor.FromRGBA( color );
|
||||
|
||||
|
||||
if ( ColorChannelType.Hue == colorChannelType )
|
||||
{
|
||||
hsl.h = value;
|
||||
color = hsl;
|
||||
}
|
||||
|
||||
if ( ColorChannelType.Saturation == colorChannelType )
|
||||
{
|
||||
hsl.s = value;
|
||||
color = hsl;
|
||||
}
|
||||
|
||||
if ( ColorChannelType.Luminance == colorChannelType )
|
||||
{
|
||||
hsl.l = value;
|
||||
color = hsl;
|
||||
}
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
|
||||
public static float SRGBtoLinear( float value )
|
||||
{
|
||||
return value < 0.04045f ? value * ( 1.0f / 12.92f ) :
|
||||
Mathf.Pow( ( value + 0.055f) * ( 1f / ( 1f + 0.055f ) ), 2.4f );
|
||||
}
|
||||
|
||||
public static Color SRGBtoLinear( this Color color )
|
||||
{
|
||||
return new Color(
|
||||
SRGBtoLinear( color.R ),
|
||||
SRGBtoLinear( color.G ),
|
||||
SRGBtoLinear( color.B ),
|
||||
color.A
|
||||
);
|
||||
}
|
||||
|
||||
public static float LinearToSRGB( float value )
|
||||
{
|
||||
return value < 0.0031308f ? 12.92f * value :
|
||||
( 1.0f + 0.055f ) * Mathf.Pow( value, 1.0f / 2.4f ) - 0.055f;
|
||||
}
|
||||
|
||||
public static Color LinearToSRGB( this Color color )
|
||||
{
|
||||
return new Color(
|
||||
LinearToSRGB( color.R ),
|
||||
LinearToSRGB( color.G ),
|
||||
LinearToSRGB( color.B ),
|
||||
color.A
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public static Color From( List<float> floats, float basis = 1.0f )
|
||||
{
|
||||
if ( floats.Count == 1 )
|
||||
|
@ -90,16 +214,6 @@ namespace Rokojori
|
|||
);
|
||||
}
|
||||
|
||||
public static Color linearToSRGB( this Color color )
|
||||
{
|
||||
return color.Gamma( 1.0f / 2.2f );
|
||||
}
|
||||
|
||||
public static Color srgbToLinear( this Color color )
|
||||
{
|
||||
return color.Gamma( 2.2f );
|
||||
}
|
||||
|
||||
public static Vector3 ToVector3( this Color color )
|
||||
{
|
||||
return new Vector3( color.R, color.G, color.B );
|
||||
|
|
|
@ -126,10 +126,35 @@ namespace Rokojori
|
|||
|
||||
public static HSLColor Lerp( HSLColor x, HSLColor y, float t )
|
||||
{
|
||||
float h = Mathf.LerpAngle( x.h, y.h, t );
|
||||
float s = Mathf.Lerp( x.s, y.s, t );
|
||||
float l = Mathf.Lerp( x.l, y.l, t );
|
||||
float a = Mathf.Lerp( x.a, y.a, t );
|
||||
return Lerp( x, y, Vector4.One * t );
|
||||
}
|
||||
|
||||
public static HSLColor Lerp( HSLColor x, HSLColor y, Vector4 t )
|
||||
{
|
||||
float h = MathX.LerpAngleDegrees( x.h, y.h, t.X );
|
||||
float s = Mathf.Lerp( x.s, y.s, t.Y );
|
||||
float l = Mathf.Lerp( x.l, y.l, t.Z );
|
||||
float a = Mathf.Lerp( x.a, y.a, t.W);
|
||||
|
||||
return new HSLColor( h, s, l, a );
|
||||
}
|
||||
|
||||
public static HSLColor LerpWithHueInRGB( HSLColor x, HSLColor y, float t )
|
||||
{
|
||||
return LerpWithHueInRGB( x, y, Vector4.One * t );
|
||||
}
|
||||
|
||||
public static float BlendHueInRGB( HSLColor x, HSLColor y, float weight )
|
||||
{
|
||||
return HSLColor.FromRGBA( ColorX.Lerp( x.ToRGBA(), y.ToRGBA(), weight ) ).h;
|
||||
}
|
||||
|
||||
public static HSLColor LerpWithHueInRGB( HSLColor x, HSLColor y, Vector4 v )
|
||||
{
|
||||
float h = BlendHueInRGB( x, y, v.X );
|
||||
float s = Mathf.Lerp( x.s, y.s, v.W );
|
||||
float l = Mathf.Lerp( x.l, y.l, v.Z );
|
||||
float a = Mathf.Lerp( x.a, y.a, v.W );
|
||||
|
||||
return new HSLColor( h, s, l, a );
|
||||
}
|
||||
|
|
|
@ -8,6 +8,29 @@ namespace Rokojori
|
|||
{
|
||||
public class FilesSync
|
||||
{
|
||||
public static void Delete( string path )
|
||||
{
|
||||
if ( string.IsNullOrWhiteSpace( path ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( File.Exists( path ) )
|
||||
{
|
||||
File.Delete( path );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! Directory.Exists( path ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Directory.Delete( path, recursive: true );
|
||||
|
||||
}
|
||||
|
||||
public static bool DirectoryExists( string path )
|
||||
{
|
||||
return Directory.Exists( path );
|
||||
|
|
|
@ -146,7 +146,10 @@ namespace Rokojori
|
|||
return Mathf.Atan2( circle.Y, circle.X );
|
||||
}
|
||||
|
||||
|
||||
public static float LerpAngleDegrees( float a, float b, float weight )
|
||||
{
|
||||
return Mathf.LerpAngle( DegreesToRadians * a, DegreesToRadians * b, weight ) * RadiansToDegrees;
|
||||
}
|
||||
|
||||
public static int MultiIndexToFlatIndex( List<int> indices, List<int> sizes )
|
||||
{
|
||||
|
@ -206,7 +209,7 @@ namespace Rokojori
|
|||
public static float AngleDelta( float degreesA, float degreesB)
|
||||
{
|
||||
var angleDelta = degreesB - degreesA;
|
||||
angleDelta = (angleDelta + 180f) % 360f - 180f;
|
||||
angleDelta = ( angleDelta + 180f ) % 360f - 180f;
|
||||
return angleDelta;
|
||||
}
|
||||
|
||||
|
@ -452,15 +455,17 @@ namespace Rokojori
|
|||
return curve;
|
||||
}
|
||||
|
||||
public static Curve Curve( float y0, float y1, float minValue = 0, float maxValue = 1 )
|
||||
public static Curve Curve( float y0, float y1, float minValue = 0, float maxValue = 1, float minX = 0, float maxX = 1 )
|
||||
{
|
||||
var curve = new Curve();
|
||||
curve.AddPoint( new Vector2( 0, y0 ) );
|
||||
curve.AddPoint( new Vector2( 1, y1 ) );
|
||||
curve.AddPoint( new Vector2( minX, y0 ) );
|
||||
curve.AddPoint( new Vector2( maxX, y1 ) );
|
||||
|
||||
curve.SetPointRightMode( 0, Godot.Curve.TangentMode.Linear );
|
||||
curve.SetPointLeftMode( 1, Godot.Curve.TangentMode.Linear );
|
||||
|
||||
curve.MinDomain = minX;
|
||||
curve.MaxDomain = maxX;
|
||||
curve.MinValue = minValue;
|
||||
curve.MaxValue = maxValue;
|
||||
|
||||
|
|
|
@ -70,7 +70,7 @@ namespace Rokojori
|
|||
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 );
|
||||
mg.AddPoint( position, color.SRGBtoLinear(), normal.SRGBtoLinear().ToVector3() * 2.0f - Vector3.One, 0 );
|
||||
|
||||
// this.LogInfo( "Created point at:", index, position );
|
||||
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Godot;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
||||
namespace Rokojori
|
||||
{
|
||||
[Tool]
|
||||
[GlobalClass]
|
||||
public partial class TextureChanneMixelChannelSetting:Resource
|
||||
{
|
||||
[Export]
|
||||
public bool isAssigned = true;
|
||||
|
||||
[Export]
|
||||
public float notAssignedValue = 0;
|
||||
|
||||
[Export]
|
||||
public bool output_sRGB = true;
|
||||
|
||||
public enum ColorSource
|
||||
{
|
||||
Red, Green, Blue, Alpha
|
||||
}
|
||||
|
||||
[Export]
|
||||
public ColorSource source_channel;
|
||||
|
||||
[Export]
|
||||
public bool source_sRGB = true;
|
||||
|
||||
[Export]
|
||||
public Curve source_modifier;
|
||||
|
||||
float GetChannel( Color color, ColorSource colorSource )
|
||||
{
|
||||
if ( ColorSource.Red == colorSource )
|
||||
{
|
||||
return color.R;
|
||||
}
|
||||
|
||||
if ( ColorSource.Green == colorSource )
|
||||
{
|
||||
return color.G;
|
||||
}
|
||||
|
||||
if ( ColorSource.Blue == colorSource )
|
||||
{
|
||||
return color.B;
|
||||
}
|
||||
|
||||
if ( ColorSource.Alpha == colorSource )
|
||||
{
|
||||
return color.A;
|
||||
}
|
||||
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
public float GetValue( Color sourceColor )
|
||||
{
|
||||
if ( ! isAssigned )
|
||||
{
|
||||
return notAssignedValue;
|
||||
}
|
||||
|
||||
var value = GetChannel( sourceColor, source_channel );
|
||||
|
||||
if ( source_modifier == null && source_sRGB == output_sRGB )
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
if ( source_sRGB )
|
||||
{
|
||||
value = ColorX.SRGBtoLinear( value );
|
||||
}
|
||||
|
||||
if ( source_modifier != null )
|
||||
{
|
||||
value = source_modifier.Sample( value );
|
||||
}
|
||||
|
||||
if ( output_sRGB )
|
||||
{
|
||||
value = ColorX.LinearToSRGB( value );
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
uid://dae58ep6ml38n
|
|
@ -0,0 +1,93 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Godot;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Rokojori
|
||||
{
|
||||
[Tool]
|
||||
[GlobalClass]
|
||||
public partial class TextureChannelMixer:Action
|
||||
{
|
||||
[Export]
|
||||
public string inputTexturePath;
|
||||
|
||||
[Export]
|
||||
public string outputTexturePath;
|
||||
|
||||
[Export]
|
||||
public ImageSaveSettings outputFormat;
|
||||
|
||||
[Export]
|
||||
public TextureChannelMixerPreset preset;
|
||||
|
||||
[ExportGroup("Channel Adjustments")]
|
||||
[Export]
|
||||
public float redMultiply = 1;
|
||||
|
||||
[Export]
|
||||
public float redOffset = 0;
|
||||
|
||||
[Export]
|
||||
public float greenMultiply = 1;
|
||||
|
||||
[Export]
|
||||
public float greenOffset = 0;
|
||||
|
||||
[Export]
|
||||
public float blueMultiply = 1;
|
||||
|
||||
[Export]
|
||||
public float blueOffset = 0;
|
||||
|
||||
[Export]
|
||||
public float alphaMultiply = 1;
|
||||
|
||||
[Export]
|
||||
public float alphaOffset = 0;
|
||||
|
||||
|
||||
protected override void _OnTrigger()
|
||||
{
|
||||
if ( preset == null ||
|
||||
preset.red == null ||
|
||||
preset.green == null ||
|
||||
preset.blue == null ||
|
||||
preset.alpha == null
|
||||
)
|
||||
{
|
||||
this.LogError( "The preset is not correctly setup for each channel. Add a preset and for each channel add a setting" );
|
||||
return;
|
||||
}
|
||||
|
||||
var texture = ResourceLoader.Load<Texture2D>( inputTexturePath );
|
||||
var sourceBuffer = TextureCombinerBuffer.From( texture );
|
||||
var outputBuffer = TextureCombinerBuffer.Create( sourceBuffer.width, sourceBuffer.height );
|
||||
|
||||
this.LogInfo( "Processing:", inputTexturePath, ">>", sourceBuffer.numPixels + " pixels" );
|
||||
|
||||
for ( int i = 0; i < sourceBuffer.numPixels; i++ )
|
||||
{
|
||||
var sourceColor = sourceBuffer.GetIndexed( i );
|
||||
var outputColor = new Color(
|
||||
preset.red.GetValue( sourceColor ) * redMultiply + redOffset,
|
||||
preset.green.GetValue( sourceColor ) * greenMultiply + greenOffset,
|
||||
preset.blue.GetValue( sourceColor ) * blueMultiply + blueOffset,
|
||||
preset.alpha.GetValue( sourceColor ) * alphaMultiply + redOffset
|
||||
);
|
||||
|
||||
outputBuffer.SetIndexed( i, outputColor );
|
||||
}
|
||||
|
||||
this.LogInfo( "Saving:", outputTexturePath );
|
||||
|
||||
var it = outputBuffer.CreateImageTexture( preset.alpha.isAssigned, false );
|
||||
|
||||
var image = it.GetImage();
|
||||
outputFormat.Save( image, outputTexturePath );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
uid://chalyifwnlyjr
|
|
@ -0,0 +1,26 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Godot;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
||||
namespace Rokojori
|
||||
{
|
||||
[Tool]
|
||||
[GlobalClass]
|
||||
public partial class TextureChannelMixerPreset:Resource
|
||||
{
|
||||
[Export]
|
||||
public TextureChanneMixelChannelSetting red;
|
||||
|
||||
[Export]
|
||||
public TextureChanneMixelChannelSetting green;
|
||||
|
||||
[Export]
|
||||
public TextureChanneMixelChannelSetting blue;
|
||||
|
||||
[Export]
|
||||
public TextureChanneMixelChannelSetting alpha;
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
uid://cixw1u0gkbovt
|
|
@ -0,0 +1,48 @@
|
|||
[gd_resource type="Resource" script_class="TextureChannelMixerPreset" load_steps=7 format=3 uid="uid://bcswdpbt3yanm"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://dae58ep6ml38n" path="res://addons/rokojori_action_library/Runtime/Procedural/Textures/ChannelMixer/TextureChanneMixelChannelSetting.cs" id="1_g25py"]
|
||||
[ext_resource type="Script" uid="uid://cixw1u0gkbovt" path="res://addons/rokojori_action_library/Runtime/Procedural/Textures/ChannelMixer/TextureChannelMixerPreset.cs" id="2_esgkr"]
|
||||
|
||||
[sub_resource type="Resource" id="Resource_cwohu"]
|
||||
script = ExtResource("1_g25py")
|
||||
isAssigned = true
|
||||
notAssignedValue = 1.0
|
||||
output_sRGB = true
|
||||
source_channel = 3
|
||||
source_sRGB = true
|
||||
metadata/_custom_type_script = "uid://dae58ep6ml38n"
|
||||
|
||||
[sub_resource type="Resource" id="Resource_d3h5b"]
|
||||
script = ExtResource("1_g25py")
|
||||
isAssigned = false
|
||||
notAssignedValue = 0.0
|
||||
output_sRGB = true
|
||||
source_channel = 2
|
||||
source_sRGB = true
|
||||
metadata/_custom_type_script = "uid://dae58ep6ml38n"
|
||||
|
||||
[sub_resource type="Resource" id="Resource_t47sh"]
|
||||
script = ExtResource("1_g25py")
|
||||
isAssigned = false
|
||||
notAssignedValue = 0.0
|
||||
output_sRGB = true
|
||||
source_channel = 1
|
||||
source_sRGB = true
|
||||
metadata/_custom_type_script = "uid://dae58ep6ml38n"
|
||||
|
||||
[sub_resource type="Resource" id="Resource_idsat"]
|
||||
script = ExtResource("1_g25py")
|
||||
isAssigned = false
|
||||
notAssignedValue = 0.0
|
||||
output_sRGB = true
|
||||
source_channel = 0
|
||||
source_sRGB = true
|
||||
metadata/_custom_type_script = "uid://dae58ep6ml38n"
|
||||
|
||||
[resource]
|
||||
script = ExtResource("2_esgkr")
|
||||
red = SubResource("Resource_idsat")
|
||||
green = SubResource("Resource_t47sh")
|
||||
blue = SubResource("Resource_d3h5b")
|
||||
alpha = SubResource("Resource_cwohu")
|
||||
metadata/_custom_type_script = "uid://cixw1u0gkbovt"
|
|
@ -0,0 +1,48 @@
|
|||
[gd_resource type="Resource" script_class="TextureChannelMixerPreset" load_steps=7 format=3 uid="uid://dnqy2sbr145a5"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://dae58ep6ml38n" path="res://addons/rokojori_action_library/Runtime/Procedural/Textures/ChannelMixer/TextureChanneMixelChannelSetting.cs" id="1_rj4fv"]
|
||||
[ext_resource type="Script" uid="uid://cixw1u0gkbovt" path="res://addons/rokojori_action_library/Runtime/Procedural/Textures/ChannelMixer/TextureChannelMixerPreset.cs" id="2_8vvu2"]
|
||||
|
||||
[sub_resource type="Resource" id="Resource_35ry6"]
|
||||
script = ExtResource("1_rj4fv")
|
||||
isAssigned = false
|
||||
notAssignedValue = 1.0
|
||||
output_sRGB = true
|
||||
source_channel = 0
|
||||
source_sRGB = true
|
||||
metadata/_custom_type_script = "uid://dae58ep6ml38n"
|
||||
|
||||
[sub_resource type="Resource" id="Resource_xa153"]
|
||||
script = ExtResource("1_rj4fv")
|
||||
isAssigned = true
|
||||
notAssignedValue = 0.0
|
||||
output_sRGB = true
|
||||
source_channel = 2
|
||||
source_sRGB = true
|
||||
metadata/_custom_type_script = "uid://dae58ep6ml38n"
|
||||
|
||||
[sub_resource type="Resource" id="Resource_gqbnd"]
|
||||
script = ExtResource("1_rj4fv")
|
||||
isAssigned = false
|
||||
notAssignedValue = 0.0
|
||||
output_sRGB = true
|
||||
source_channel = 1
|
||||
source_sRGB = true
|
||||
metadata/_custom_type_script = "uid://dae58ep6ml38n"
|
||||
|
||||
[sub_resource type="Resource" id="Resource_t7yfx"]
|
||||
script = ExtResource("1_rj4fv")
|
||||
isAssigned = false
|
||||
notAssignedValue = 0.0
|
||||
output_sRGB = true
|
||||
source_channel = 0
|
||||
source_sRGB = true
|
||||
metadata/_custom_type_script = "uid://dae58ep6ml38n"
|
||||
|
||||
[resource]
|
||||
script = ExtResource("2_8vvu2")
|
||||
red = SubResource("Resource_t7yfx")
|
||||
green = SubResource("Resource_gqbnd")
|
||||
blue = SubResource("Resource_xa153")
|
||||
alpha = SubResource("Resource_35ry6")
|
||||
metadata/_custom_type_script = "uid://cixw1u0gkbovt"
|
|
@ -0,0 +1,48 @@
|
|||
[gd_resource type="Resource" script_class="TextureChannelMixerPreset" load_steps=7 format=3 uid="uid://cah7aqecamuon"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://dae58ep6ml38n" path="res://addons/rokojori_action_library/Runtime/Procedural/Textures/ChannelMixer/TextureChanneMixelChannelSetting.cs" id="1_ne34d"]
|
||||
[ext_resource type="Script" uid="uid://cixw1u0gkbovt" path="res://addons/rokojori_action_library/Runtime/Procedural/Textures/ChannelMixer/TextureChannelMixerPreset.cs" id="2_ml4ie"]
|
||||
|
||||
[sub_resource type="Resource" id="Resource_7pghi"]
|
||||
script = ExtResource("1_ne34d")
|
||||
isAssigned = false
|
||||
notAssignedValue = 1.0
|
||||
output_sRGB = true
|
||||
source_channel = 0
|
||||
source_sRGB = true
|
||||
metadata/_custom_type_script = "uid://dae58ep6ml38n"
|
||||
|
||||
[sub_resource type="Resource" id="Resource_a48r2"]
|
||||
script = ExtResource("1_ne34d")
|
||||
isAssigned = false
|
||||
notAssignedValue = 0.0
|
||||
output_sRGB = true
|
||||
source_channel = 0
|
||||
source_sRGB = true
|
||||
metadata/_custom_type_script = "uid://dae58ep6ml38n"
|
||||
|
||||
[sub_resource type="Resource" id="Resource_ysxo1"]
|
||||
script = ExtResource("1_ne34d")
|
||||
isAssigned = true
|
||||
notAssignedValue = 0.0
|
||||
output_sRGB = true
|
||||
source_channel = 1
|
||||
source_sRGB = true
|
||||
metadata/_custom_type_script = "uid://dae58ep6ml38n"
|
||||
|
||||
[sub_resource type="Resource" id="Resource_ecch3"]
|
||||
script = ExtResource("1_ne34d")
|
||||
isAssigned = false
|
||||
notAssignedValue = 0.0
|
||||
output_sRGB = true
|
||||
source_channel = 0
|
||||
source_sRGB = true
|
||||
metadata/_custom_type_script = "uid://dae58ep6ml38n"
|
||||
|
||||
[resource]
|
||||
script = ExtResource("2_ml4ie")
|
||||
red = SubResource("Resource_ecch3")
|
||||
green = SubResource("Resource_ysxo1")
|
||||
blue = SubResource("Resource_a48r2")
|
||||
alpha = SubResource("Resource_7pghi")
|
||||
metadata/_custom_type_script = "uid://cixw1u0gkbovt"
|
|
@ -0,0 +1,53 @@
|
|||
[gd_resource type="Resource" script_class="TextureChannelMixerPreset" load_steps=8 format=3 uid="uid://co8x14v8bg68h"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://dae58ep6ml38n" path="res://addons/rokojori_action_library/Runtime/Procedural/Textures/ChannelMixer/TextureChanneMixelChannelSetting.cs" id="1_urrp0"]
|
||||
[ext_resource type="Script" uid="uid://cixw1u0gkbovt" path="res://addons/rokojori_action_library/Runtime/Procedural/Textures/ChannelMixer/TextureChannelMixerPreset.cs" id="2_5golc"]
|
||||
|
||||
[sub_resource type="Curve" id="Curve_gvcnt"]
|
||||
_data = [Vector2(0, 1), 0.0, -1.0, 0, 0, Vector2(1, 0), -1.0, 0.0, 0, 0]
|
||||
point_count = 2
|
||||
|
||||
[sub_resource type="Resource" id="Resource_tcfhe"]
|
||||
script = ExtResource("1_urrp0")
|
||||
isAssigned = true
|
||||
notAssignedValue = 0.0
|
||||
output_sRGB = false
|
||||
source_channel = 1
|
||||
source_sRGB = false
|
||||
source_modifier = SubResource("Curve_gvcnt")
|
||||
metadata/_custom_type_script = "uid://dae58ep6ml38n"
|
||||
|
||||
[sub_resource type="Resource" id="Resource_xxtsh"]
|
||||
script = ExtResource("1_urrp0")
|
||||
isAssigned = false
|
||||
notAssignedValue = 0.0
|
||||
output_sRGB = true
|
||||
source_channel = 0
|
||||
source_sRGB = true
|
||||
metadata/_custom_type_script = "uid://dae58ep6ml38n"
|
||||
|
||||
[sub_resource type="Resource" id="Resource_xeyj2"]
|
||||
script = ExtResource("1_urrp0")
|
||||
isAssigned = false
|
||||
notAssignedValue = 0.0
|
||||
output_sRGB = true
|
||||
source_channel = 0
|
||||
source_sRGB = true
|
||||
metadata/_custom_type_script = "uid://dae58ep6ml38n"
|
||||
|
||||
[sub_resource type="Resource" id="Resource_wtf83"]
|
||||
script = ExtResource("1_urrp0")
|
||||
isAssigned = true
|
||||
notAssignedValue = 0.0
|
||||
output_sRGB = false
|
||||
source_channel = 2
|
||||
source_sRGB = false
|
||||
metadata/_custom_type_script = "uid://dae58ep6ml38n"
|
||||
|
||||
[resource]
|
||||
script = ExtResource("2_5golc")
|
||||
red = SubResource("Resource_wtf83")
|
||||
green = SubResource("Resource_xeyj2")
|
||||
blue = SubResource("Resource_xxtsh")
|
||||
alpha = SubResource("Resource_tcfhe")
|
||||
metadata/_custom_type_script = "uid://cixw1u0gkbovt"
|
|
@ -0,0 +1,48 @@
|
|||
[gd_resource type="Resource" script_class="TextureChannelMixerPreset" load_steps=7 format=3 uid="uid://5atymi8i3ufe"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://dae58ep6ml38n" path="res://addons/rokojori_action_library/Runtime/Procedural/Textures/ChannelMixer/TextureChanneMixelChannelSetting.cs" id="1_jxt5h"]
|
||||
[ext_resource type="Script" uid="uid://cixw1u0gkbovt" path="res://addons/rokojori_action_library/Runtime/Procedural/Textures/ChannelMixer/TextureChannelMixerPreset.cs" id="2_h12ag"]
|
||||
|
||||
[sub_resource type="Resource" id="Resource_wfamn"]
|
||||
script = ExtResource("1_jxt5h")
|
||||
isAssigned = false
|
||||
notAssignedValue = 1.0
|
||||
output_sRGB = true
|
||||
source_channel = 0
|
||||
source_sRGB = true
|
||||
metadata/_custom_type_script = "uid://dae58ep6ml38n"
|
||||
|
||||
[sub_resource type="Resource" id="Resource_6sudk"]
|
||||
script = ExtResource("1_jxt5h")
|
||||
isAssigned = false
|
||||
notAssignedValue = 0.0
|
||||
output_sRGB = true
|
||||
source_channel = 0
|
||||
source_sRGB = true
|
||||
metadata/_custom_type_script = "uid://dae58ep6ml38n"
|
||||
|
||||
[sub_resource type="Resource" id="Resource_qjaoh"]
|
||||
script = ExtResource("1_jxt5h")
|
||||
isAssigned = false
|
||||
notAssignedValue = 0.0
|
||||
output_sRGB = true
|
||||
source_channel = 0
|
||||
source_sRGB = true
|
||||
metadata/_custom_type_script = "uid://dae58ep6ml38n"
|
||||
|
||||
[sub_resource type="Resource" id="Resource_4xjsl"]
|
||||
script = ExtResource("1_jxt5h")
|
||||
isAssigned = true
|
||||
notAssignedValue = 0.0
|
||||
output_sRGB = true
|
||||
source_channel = 0
|
||||
source_sRGB = true
|
||||
metadata/_custom_type_script = "uid://dae58ep6ml38n"
|
||||
|
||||
[resource]
|
||||
script = ExtResource("2_h12ag")
|
||||
red = SubResource("Resource_4xjsl")
|
||||
green = SubResource("Resource_qjaoh")
|
||||
blue = SubResource("Resource_6sudk")
|
||||
alpha = SubResource("Resource_wfamn")
|
||||
metadata/_custom_type_script = "uid://cixw1u0gkbovt"
|
|
@ -0,0 +1,60 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Godot;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
||||
namespace Rokojori
|
||||
{
|
||||
[Tool]
|
||||
[GlobalClass]
|
||||
public partial class ColorAdjustments:_XX_ColorCorrectionModifier
|
||||
{
|
||||
[Export(PropertyHint.Range, "-180,180 suffix:°")]
|
||||
public float hue = 0;
|
||||
|
||||
[Export(PropertyHint.Range, "-100,100 suffix:%")]
|
||||
public float saturation = 0;
|
||||
|
||||
[Export(PropertyHint.Range, "-100,100 suffix:%")]
|
||||
public float vibrance = 0;
|
||||
|
||||
[Export(PropertyHint.Range, "-100,100 suffix:%")]
|
||||
public float contrast = 0;
|
||||
|
||||
[Export(PropertyHint.Range, "-100,100 suffix:%")]
|
||||
public float brightness = 0;
|
||||
|
||||
[Export(PropertyHint.Range, "-100,100 suffix:%")]
|
||||
public float gamma = 0;
|
||||
|
||||
protected override Color _Modify( Color sourceColor )
|
||||
{
|
||||
var hslColor = HSLColor.FromRGBA( sourceColor );
|
||||
|
||||
hslColor.h = MathX.Repeat( hslColor.h + hue, 360 );
|
||||
hslColor.s = MathX.Clamp01( hslColor.s + saturation/100f );
|
||||
|
||||
|
||||
var vibranceAmount = 1f;
|
||||
var angleDistanceAmount = MathX.Clamp01( Mathf.Abs( MathX.AngleDelta( hslColor.h, 0 ) ) / 180f );
|
||||
var luminanceAmount = 1f - hslColor.l;
|
||||
vibranceAmount = MathX.Clamp01( angleDistanceAmount * luminanceAmount + 0.1f );
|
||||
|
||||
// var rgb = new Color( vibrance/100f * vibranceAmount, vibrance/100f * vibranceAmount, vibrance/100f * vibranceAmount, 1 );
|
||||
hslColor.s = Mathf.Lerp( hslColor.s, 1f, vibrance/100f * vibranceAmount );
|
||||
hslColor.s = MathX.Clamp01( hslColor.s );
|
||||
|
||||
hslColor.l = ( hslColor.l - 0.5f ) * Mathf.Pow( 2, contrast/100f ) + 0.5f;
|
||||
hslColor.l = MathX.Clamp01( hslColor.l + brightness/100f );
|
||||
|
||||
var rgb = hslColor.ToRGBA();
|
||||
rgb = rgb.Gamma( Mathf.Pow( 2.2f, gamma/100f ) );
|
||||
|
||||
|
||||
return rgb;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
uid://bpulemr8hxlht
|
|
@ -0,0 +1,39 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Godot;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
||||
namespace Rokojori
|
||||
{
|
||||
[Tool]
|
||||
[GlobalClass]
|
||||
public partial class ColorCorrectionPreset:Resource
|
||||
{
|
||||
[Export]
|
||||
public _XX_ColorCorrectionModifier[] modifiers = [];
|
||||
|
||||
[Export(PropertyHint.Range, "0,100 suffix:%")]
|
||||
public float amount = 100;
|
||||
|
||||
public Color Process( Color color )
|
||||
{
|
||||
var originalColor = color;
|
||||
modifiers.ForEach(
|
||||
( m )=>
|
||||
{
|
||||
if ( m == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
color = m.Apply( color );
|
||||
}
|
||||
);
|
||||
|
||||
return ColorX.Lerp( originalColor, color, amount/100f );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
uid://eh02vfeoi8xb
|
|
@ -0,0 +1,125 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Godot;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
||||
namespace Rokojori
|
||||
{
|
||||
[Tool]
|
||||
[GlobalClass]
|
||||
public partial class ColorCorrectionStack:Node
|
||||
{
|
||||
[Export]
|
||||
public WorldEnvironment worldEnvironment;
|
||||
|
||||
[Export]
|
||||
public ColorCorrectionPreset preset;
|
||||
|
||||
[Export(PropertyHint.Range, "0,100 suffix:%")]
|
||||
public float amount = 100;
|
||||
|
||||
[Export]
|
||||
public bool changed = false;
|
||||
|
||||
Godot.Collections.Array<Image> luts;
|
||||
|
||||
|
||||
|
||||
ImageTexture3D outputTexture;
|
||||
|
||||
[Export]
|
||||
public bool refresh = false;
|
||||
|
||||
[Export]
|
||||
public int lutSize = 33;
|
||||
|
||||
public override void _Process( double delta )
|
||||
{
|
||||
if ( worldEnvironment == null || preset == null || ! changed )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( refresh )
|
||||
{
|
||||
luts = null;
|
||||
outputTexture = null;
|
||||
}
|
||||
|
||||
EnsureImages();
|
||||
|
||||
for ( int bi = 0; bi < lutSize; bi++ )
|
||||
{
|
||||
var image = luts[ bi ];
|
||||
var b = bi / ( lutSize - 1f );
|
||||
|
||||
for ( int ri = 0; ri < lutSize; ri ++ )
|
||||
{
|
||||
var r = ri / ( lutSize - 1f );
|
||||
|
||||
for ( int gi = 0; gi < lutSize; gi ++ )
|
||||
{
|
||||
|
||||
var g = gi / ( lutSize - 1f );
|
||||
|
||||
var color = new Color( r, g, b );
|
||||
var modifiedColor = preset.Process( color );
|
||||
|
||||
modifiedColor = ColorX.Lerp( color, modifiedColor, amount / 100f );
|
||||
|
||||
image.SetPixel( ri, gi, modifiedColor );
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ( outputTexture == null )
|
||||
{
|
||||
outputTexture = new ImageTexture3D();
|
||||
outputTexture.Create( Image.Format.Rgb8, lutSize, lutSize, lutSize, false, luts );
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
outputTexture.Update( luts );
|
||||
}
|
||||
|
||||
worldEnvironment.Environment.AdjustmentEnabled = true;
|
||||
worldEnvironment.Environment.AdjustmentColorCorrection = outputTexture;
|
||||
|
||||
|
||||
}
|
||||
|
||||
void EnsureImages()
|
||||
{
|
||||
if ( luts != null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
luts = new Godot.Collections.Array<Image>();
|
||||
|
||||
for ( int i = 0; i < lutSize; i++ )
|
||||
{
|
||||
luts.Add( Image.CreateEmpty( lutSize, lutSize, false, Image.Format.Rgb8 ) );
|
||||
}
|
||||
}
|
||||
|
||||
// void GrabOriginal()
|
||||
// {
|
||||
// if ( original != null )
|
||||
// {
|
||||
// return;
|
||||
// }
|
||||
|
||||
// var path = "res://addons/rokojori_action_library/Runtime/VirtualCameras/PostProcess/environment_adjustments_3d_lut_template.webp";
|
||||
// original = TextureCombinerBuffer.FromPath( path );
|
||||
// output = TextureCombinerBuffer.Create( original.width, original.height );
|
||||
// }
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
uid://b5ot2h42auy32
|
|
@ -0,0 +1,55 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Godot;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
||||
namespace Rokojori
|
||||
{
|
||||
[Tool]
|
||||
[GlobalClass]
|
||||
public partial class Colorize:_XX_ColorCorrectionModifier
|
||||
{
|
||||
[Export]
|
||||
public Color color;
|
||||
|
||||
[Export]
|
||||
public Curve amountFromSourceLuminance = MathX.Curve( 0.1f );
|
||||
|
||||
[Export(PropertyHint.Range, "0,100 suffix:%")]
|
||||
public float hueAmount = 100;
|
||||
|
||||
[Export(PropertyHint.Range, "0,100 suffix:%")]
|
||||
public float saturationAmount = 100;
|
||||
|
||||
[Export(PropertyHint.Range, "0,100 suffix:%")]
|
||||
public float luminanceAmount = 100;
|
||||
|
||||
[Export]
|
||||
public bool blendHueInRGB = true;
|
||||
|
||||
protected override Color _Modify( Color sourceColor )
|
||||
{
|
||||
var sourceHSL = HSLColor.FromRGBA( sourceColor );
|
||||
var sourceLuminanceAmount = amountFromSourceLuminance.Sample( sourceHSL.l );
|
||||
|
||||
var targetHSL = HSLColor.FromRGBA( color );
|
||||
|
||||
var weights = new Vector4( hueAmount / 100f, saturationAmount / 100f, luminanceAmount / 100f, 1 );
|
||||
weights *= sourceLuminanceAmount;
|
||||
|
||||
if ( blendHueInRGB )
|
||||
{
|
||||
targetHSL = HSLColor.LerpWithHueInRGB( sourceHSL, targetHSL, weights );
|
||||
}
|
||||
else
|
||||
{
|
||||
targetHSL = HSLColor.Lerp( sourceHSL, targetHSL, weights );
|
||||
}
|
||||
|
||||
return targetHSL;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
uid://d3jgv8mofjss5
|
|
@ -0,0 +1,68 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Godot;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
||||
namespace Rokojori
|
||||
{
|
||||
[Tool]
|
||||
[GlobalClass]
|
||||
public partial class CrossCurves:_XX_ColorCorrectionModifier
|
||||
{
|
||||
|
||||
|
||||
[Export]
|
||||
public ColorChannelType driver;
|
||||
|
||||
[Export]
|
||||
public ColorChannelType target;
|
||||
|
||||
[Export]
|
||||
public Curve crossCurve;
|
||||
|
||||
[Export]
|
||||
public bool normalize = true;
|
||||
|
||||
protected override Color _Modify( Color color )
|
||||
{
|
||||
if ( crossCurve == null )
|
||||
{
|
||||
return color;
|
||||
}
|
||||
|
||||
var valueIn = color.GetChannel( driver );
|
||||
|
||||
if ( ColorChannelType.Hue == driver )
|
||||
{
|
||||
valueIn /= 360f;
|
||||
}
|
||||
|
||||
var offsetValue = crossCurve.Sample( valueIn );
|
||||
|
||||
if ( ColorChannelType.Hue == target )
|
||||
{
|
||||
offsetValue *= 360f;
|
||||
}
|
||||
|
||||
var endValue = color.GetChannel( target ) + offsetValue;
|
||||
|
||||
if ( ColorChannelType.Hue == target )
|
||||
{
|
||||
endValue = MathX.Repeat( endValue, 360 );
|
||||
}
|
||||
else
|
||||
{
|
||||
endValue = MathX.Clamp01( endValue );
|
||||
}
|
||||
|
||||
color = color.SetChannel( target, endValue );
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
uid://c6a2k4kldmq6k
|
|
@ -0,0 +1,56 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Godot;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
||||
namespace Rokojori
|
||||
{
|
||||
[Tool]
|
||||
[GlobalClass]
|
||||
public partial class HSLCurves:_XX_ColorCorrectionModifier
|
||||
{
|
||||
[Export]
|
||||
public Curve h = MathX.Curve( 0, 360, 0, 360, 0, 360 );
|
||||
|
||||
[Export]
|
||||
public float hOffset = 0;
|
||||
|
||||
[Export]
|
||||
public Curve s = MathX.Curve( 0, 1, 0, 1);
|
||||
|
||||
[Export]
|
||||
public float sOffset = 0;
|
||||
|
||||
[Export]
|
||||
public Curve l = MathX.Curve( 0, 1, 0, 1);
|
||||
|
||||
[Export]
|
||||
public float lOffset = 0;
|
||||
|
||||
protected override Color _Modify( Color color )
|
||||
{
|
||||
var hsl = HSLColor.FromRGBA( color );
|
||||
|
||||
var hh = h == null ? hsl.h : h.Sample( hsl.h );
|
||||
var ss = s == null ? hsl.s : s.Sample( hsl.s );
|
||||
var ll = l == null ? hsl.l : l.Sample( hsl.l );
|
||||
|
||||
hh += hOffset;
|
||||
ss += sOffset;
|
||||
ll += lOffset;
|
||||
|
||||
hh = MathX.Repeat( hh, 360 );
|
||||
ss = MathX.Clamp01( ss );
|
||||
ll = MathX.Clamp01( ll );
|
||||
|
||||
hsl.h = hh;
|
||||
hsl.s = ss;
|
||||
hsl.l = ll;
|
||||
|
||||
return hsl.ToRGBA();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
uid://dlxt0pm7dpuoy
|
|
@ -0,0 +1,33 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Godot;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
||||
namespace Rokojori
|
||||
{
|
||||
[Tool]
|
||||
[GlobalClass]
|
||||
public partial class RGBCurves:_XX_ColorCorrectionModifier
|
||||
{
|
||||
[Export]
|
||||
public Curve r;
|
||||
|
||||
[Export]
|
||||
public Curve g;
|
||||
|
||||
[Export]
|
||||
public Curve b;
|
||||
|
||||
protected override Color _Modify( Color color )
|
||||
{
|
||||
var rr = r == null ? color.R : r.Sample( color.R );
|
||||
var gg = g == null ? color.G : g.Sample( color.G );
|
||||
var bb = b == null ? color.B : b.Sample( color.B );
|
||||
|
||||
return new Color( rr, gg, bb, color.A );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
uid://bf2q4pgpi2vl2
|
|
@ -0,0 +1,30 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Godot;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
||||
namespace Rokojori
|
||||
{
|
||||
[Tool]
|
||||
[GlobalClass]
|
||||
public partial class _XX_ColorCorrectionModifier:Resource
|
||||
{
|
||||
[Export(PropertyHint.Range, "0,100 suffix:%")]
|
||||
public float amount = 100;
|
||||
|
||||
public Color Apply( Color color )
|
||||
{
|
||||
var modified = _Modify( color );
|
||||
|
||||
return ColorX.Lerp( color, modified, amount / 100f );
|
||||
}
|
||||
|
||||
protected virtual Color _Modify( Color color )
|
||||
{
|
||||
return color;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
uid://b6uqqar4kc4am
|
|
@ -0,0 +1,18 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Godot;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Rokojori
|
||||
{
|
||||
[Tool]
|
||||
[GlobalClass]
|
||||
public partial class ImageSaveSettings:Resource
|
||||
{
|
||||
public virtual void Save( Image image, string path )
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
uid://ca0t2btbm43ax
|
|
@ -0,0 +1,16 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Godot;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Rokojori
|
||||
{
|
||||
public class Images
|
||||
{
|
||||
public void Save( Image img, string path, ImageSaveSettings saveSettings )
|
||||
{
|
||||
saveSettings.Save( img, path );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Godot;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Rokojori
|
||||
{
|
||||
[Tool]
|
||||
[GlobalClass]
|
||||
public partial class PNGSettings:ImageSaveSettings
|
||||
{
|
||||
public override void Save( Image image, string path )
|
||||
{
|
||||
path = path.EnsureEndsWith( ".png" );
|
||||
image.SavePng( path );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
uid://m1agofoxqejh
|
|
@ -56,11 +56,19 @@ namespace Rokojori
|
|||
public static TextureCombinerBuffer From( Texture2D texture, int srgbConversion = 0 )
|
||||
{
|
||||
var buffer = Create( texture.GetWidth(), texture.GetHeight() );
|
||||
buffer.CopyFrom( texture.GetImage(), 0, 0, 0, 0, texture.GetWidth(), texture.GetHeight(), srgbConversion);
|
||||
buffer.CopyFrom( texture.GetImage(), 0, 0, 0, 0, texture.GetWidth(), texture.GetHeight(), srgbConversion );
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public static TextureCombinerBuffer FromPath( string path, int srgbConversion = 0 )
|
||||
{
|
||||
var texture = ResourceLoader.Load<Texture2D>( path );
|
||||
var sourceBuffer = TextureCombinerBuffer.From( texture, srgbConversion );
|
||||
|
||||
return sourceBuffer;
|
||||
}
|
||||
|
||||
public void CopyFromSampled( TextureCombinerBuffer source, int x, int y, int w, int h )
|
||||
{
|
||||
// RJLog.Log( "Copy Sampled", x,y, w, h );
|
||||
|
@ -147,6 +155,26 @@ namespace Rokojori
|
|||
return ImageTexture.CreateFromImage( image );
|
||||
}
|
||||
|
||||
public ImageTexture CreateImageTexture3D( int depth, bool alpha = true, bool generateMipmaps = false )
|
||||
{
|
||||
var image = Image.CreateEmpty( width, height, generateMipmaps, alpha ? Image.Format.Rgba8 : Image.Format.Rgb8);
|
||||
CopyTo( 0, 0, 0, 0, width, height, image, alpha );
|
||||
|
||||
if ( generateMipmaps )
|
||||
{
|
||||
image.GenerateMipmaps();
|
||||
}
|
||||
|
||||
return ImageTexture.CreateFromImage( image );
|
||||
}
|
||||
|
||||
public void UpdateTexture( ImageTexture imageTexture, bool hasAlpha = true )
|
||||
{
|
||||
var image = imageTexture.GetImage();
|
||||
CopyTo( 0, 0, 0, 0, width, height, image, hasAlpha );
|
||||
imageTexture.Update( image );
|
||||
}
|
||||
|
||||
public TextureCombinerBuffer Resize( int w, int h )
|
||||
{
|
||||
var buffer = Create( w, h );
|
||||
|
@ -170,19 +198,34 @@ namespace Rokojori
|
|||
{
|
||||
if ( srgbConversion != 0 )
|
||||
{
|
||||
var gamma = Mathf.Pow( 2.2f, srgbConversion );
|
||||
|
||||
if ( srgbConversion == 1 )
|
||||
{
|
||||
for ( int i = 0; i < w; i++ )
|
||||
{
|
||||
for ( int j = 0; j < h; j++ )
|
||||
{
|
||||
var sourcePixel = image == null ? new Color( 0, 0, 0 ) : image.GetPixel( sourceX + i, sourceY + j );
|
||||
sourcePixel = sourcePixel.Gamma( gamma );
|
||||
sourcePixel = sourcePixel.SRGBtoLinear();
|
||||
SetAt( ownX + i, ownY + j, sourcePixel );
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( srgbConversion == -1 )
|
||||
{
|
||||
for ( int i = 0; i < w; i++ )
|
||||
{
|
||||
for ( int j = 0; j < h; j++ )
|
||||
{
|
||||
var sourcePixel = image == null ? new Color( 0, 0, 0 ) : image.GetPixel( sourceX + i, sourceY + j );
|
||||
sourcePixel = sourcePixel.LinearToSRGB();
|
||||
SetAt( ownX + i, ownY + j, sourcePixel );
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
|
|
|
@ -85,7 +85,7 @@ namespace Rokojori.Reallusion
|
|||
|
||||
if ( sRGB )
|
||||
{
|
||||
color = color.linearToSRGB();
|
||||
color = color.LinearToSRGB();
|
||||
}
|
||||
|
||||
return color;
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
|
||||
namespace Rokojori
|
||||
{
|
||||
public static class Text
|
||||
{
|
||||
public static string EscapeAsPathForCommandLine( this string path )
|
||||
{
|
||||
var escaped = path.Replace( "\"", "\\\"" );
|
||||
|
||||
return $"\"{escaped}\"";
|
||||
}
|
||||
|
||||
public static string EnsureEndsWith( this string path, string ending )
|
||||
{
|
||||
if ( ! path.EndsWith( ending ) )
|
||||
{
|
||||
path += ending;
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -14,6 +14,10 @@ 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")
|
||||
|
@ -23,17 +27,29 @@ 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")
|
||||
|
@ -43,6 +59,10 @@ numVisible = 1
|
|||
inputIcons = []
|
||||
useInputIconsFromSensors = true
|
||||
continous = false
|
||||
_value = 0.0
|
||||
_wasActive = false
|
||||
_active = false
|
||||
_activeTreshold = 0.5
|
||||
|
||||
[resource]
|
||||
script = ExtResource("1_ikub8")
|
||||
|
@ -52,3 +72,7 @@ numVisible = 0
|
|||
inputIcons = []
|
||||
useInputIconsFromSensors = true
|
||||
continous = false
|
||||
_value = 0.0
|
||||
_wasActive = false
|
||||
_active = false
|
||||
_activeTreshold = 0.5
|
||||
|
|
|
@ -13,6 +13,10 @@ 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")
|
||||
|
@ -22,11 +26,19 @@ 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")
|
||||
|
@ -36,6 +48,10 @@ numVisible = 0
|
|||
inputIcons = []
|
||||
useInputIconsFromSensors = true
|
||||
continous = false
|
||||
_value = 0.0
|
||||
_wasActive = false
|
||||
_active = false
|
||||
_activeTreshold = 0.5
|
||||
|
||||
[resource]
|
||||
script = ExtResource("1_e8w3r")
|
||||
|
@ -45,3 +61,7 @@ numVisible = 0
|
|||
inputIcons = []
|
||||
useInputIconsFromSensors = true
|
||||
continous = false
|
||||
_value = 0.0
|
||||
_wasActive = false
|
||||
_active = false
|
||||
_activeTreshold = 0.5
|
||||
|
|
|
@ -14,6 +14,10 @@ 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")
|
||||
|
@ -23,17 +27,29 @@ 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")
|
||||
|
@ -43,6 +59,10 @@ numVisible = 1
|
|||
inputIcons = []
|
||||
useInputIconsFromSensors = true
|
||||
continous = false
|
||||
_value = 0.0
|
||||
_wasActive = false
|
||||
_active = false
|
||||
_activeTreshold = 0.5
|
||||
|
||||
[resource]
|
||||
script = ExtResource("1_r4ul7")
|
||||
|
@ -52,3 +72,7 @@ numVisible = 0
|
|||
inputIcons = []
|
||||
useInputIconsFromSensors = true
|
||||
continous = false
|
||||
_value = 0.0
|
||||
_wasActive = false
|
||||
_active = false
|
||||
_activeTreshold = 0.5
|
||||
|
|
|
@ -14,6 +14,10 @@ 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")
|
||||
|
@ -23,17 +27,29 @@ 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")
|
||||
|
@ -43,6 +59,10 @@ numVisible = 1
|
|||
inputIcons = []
|
||||
useInputIconsFromSensors = true
|
||||
continous = false
|
||||
_value = 0.0
|
||||
_wasActive = false
|
||||
_active = false
|
||||
_activeTreshold = 0.5
|
||||
|
||||
[resource]
|
||||
script = ExtResource("1_w0cyl")
|
||||
|
@ -52,3 +72,7 @@ numVisible = 0
|
|||
inputIcons = []
|
||||
useInputIconsFromSensors = true
|
||||
continous = false
|
||||
_value = 0.0
|
||||
_wasActive = false
|
||||
_active = false
|
||||
_activeTreshold = 0.5
|
||||
|
|
|
@ -14,6 +14,10 @@ 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")
|
||||
|
@ -23,17 +27,29 @@ 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")
|
||||
|
@ -43,6 +59,10 @@ numVisible = 1
|
|||
inputIcons = []
|
||||
useInputIconsFromSensors = true
|
||||
continous = false
|
||||
_value = 0.0
|
||||
_wasActive = false
|
||||
_active = false
|
||||
_activeTreshold = 0.5
|
||||
|
||||
[resource]
|
||||
script = ExtResource("1_vdwin")
|
||||
|
@ -52,3 +72,7 @@ numVisible = 0
|
|||
inputIcons = []
|
||||
useInputIconsFromSensors = true
|
||||
continous = false
|
||||
_value = 0.0
|
||||
_wasActive = false
|
||||
_active = false
|
||||
_activeTreshold = 0.5
|
||||
|
|
|
@ -13,6 +13,10 @@ 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")
|
||||
|
@ -22,11 +26,19 @@ 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")
|
||||
|
@ -36,6 +48,10 @@ numVisible = 1
|
|||
inputIcons = []
|
||||
useInputIconsFromSensors = true
|
||||
continous = false
|
||||
_value = 0.0
|
||||
_wasActive = false
|
||||
_active = false
|
||||
_activeTreshold = 0.5
|
||||
|
||||
[resource]
|
||||
script = ExtResource("1_5263n")
|
||||
|
@ -45,3 +61,7 @@ numVisible = 0
|
|||
inputIcons = []
|
||||
useInputIconsFromSensors = true
|
||||
continous = false
|
||||
_value = 0.0
|
||||
_wasActive = false
|
||||
_active = false
|
||||
_activeTreshold = 0.5
|
||||
|
|
|
@ -9,6 +9,10 @@ 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")
|
||||
|
@ -18,3 +22,7 @@ numVisible = 0
|
|||
inputIcons = []
|
||||
useInputIconsFromSensors = true
|
||||
continous = false
|
||||
_value = 0.0
|
||||
_wasActive = false
|
||||
_active = false
|
||||
_activeTreshold = 0.5
|
||||
|
|
|
@ -9,6 +9,10 @@ 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")
|
||||
|
@ -18,3 +22,7 @@ numVisible = 0
|
|||
inputIcons = []
|
||||
useInputIconsFromSensors = true
|
||||
continous = false
|
||||
_value = 0.0
|
||||
_wasActive = false
|
||||
_active = false
|
||||
_activeTreshold = 0.5
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
|
||||
using Godot;
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
namespace Rokojori
|
||||
{
|
||||
[Tool]
|
||||
[GlobalClass]
|
||||
public partial class AdjustmentsEffect:PostProcessVolumeEffect
|
||||
{
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
uid://b7t25777r8v13
|
Binary file not shown.
After Width: | Height: | Size: 114 B |
|
@ -0,0 +1,26 @@
|
|||
[remap]
|
||||
|
||||
importer="3d_texture"
|
||||
type="CompressedTexture3D"
|
||||
uid="uid://dlr7kk6et1g3v"
|
||||
path="res://.godot/imported/environment_adjustments_3d_lut_template.webp-6d0d1fb6bd1425e1eff35b812ef39d39.ctex3d"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/rokojori_action_library/Runtime/VirtualCameras/PostProcess/environment_adjustments_3d_lut_template.webp"
|
||||
dest_files=["res://.godot/imported/environment_adjustments_3d_lut_template.webp-6d0d1fb6bd1425e1eff35b812ef39d39.ctex3d"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
slices/horizontal=33
|
||||
slices/vertical=1
|
|
@ -0,0 +1,119 @@
|
|||
#if TOOLS
|
||||
using Godot;
|
||||
using Rokojori;
|
||||
using System.Diagnostics;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Rokojori.Tools
|
||||
{
|
||||
public class BlenderResponse
|
||||
{
|
||||
public int exitCode;
|
||||
public string rawFileName;
|
||||
public string rawArguments;
|
||||
public string rawResponse;
|
||||
}
|
||||
|
||||
public class Blender
|
||||
{
|
||||
static string _path = "blender" ;
|
||||
|
||||
public static string path
|
||||
{
|
||||
get => _path;
|
||||
|
||||
set
|
||||
{
|
||||
_path = value;
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task<BlenderResponse> RunPython( string pythonPath, List<string> args, string workingDirectory = null )
|
||||
{
|
||||
var pythonArgs = new List<string>();
|
||||
|
||||
pythonArgs.Add( "--background " );
|
||||
pythonArgs.Add( "--python " + pythonPath + " ");
|
||||
pythonArgs.Add( "-- " );
|
||||
|
||||
pythonArgs.Add( args.Join( " " ) );
|
||||
|
||||
var response = await Run( pythonArgs, workingDirectory );
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
public static async Task<BlenderResponse> Run( List<string> args, string workingDirectory = null )
|
||||
{
|
||||
var response = new BlenderResponse();
|
||||
|
||||
var joinedArgs = args.Join( " ");
|
||||
response.rawArguments = joinedArgs;
|
||||
response.rawFileName = _path;
|
||||
|
||||
|
||||
var process = new Process
|
||||
{
|
||||
StartInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = _path,
|
||||
Arguments = joinedArgs,
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true,
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = true
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
if ( workingDirectory != null )
|
||||
{
|
||||
process.StartInfo.WorkingDirectory = workingDirectory;
|
||||
}
|
||||
|
||||
process.Start();
|
||||
|
||||
var outputResult = new List<string>();
|
||||
var errorResult = new List<string>();
|
||||
|
||||
process.OutputDataReceived += (sender, e) =>
|
||||
{
|
||||
RJLog.Log( e.Data );
|
||||
outputResult.Add( e.Data );
|
||||
};
|
||||
|
||||
process.ErrorDataReceived += (sender, e) =>
|
||||
{
|
||||
RJLog.Error( e.Data );
|
||||
errorResult.Add( e.Data );
|
||||
};
|
||||
|
||||
process.BeginOutputReadLine();
|
||||
process.BeginErrorReadLine();
|
||||
|
||||
// var outputTask = process.StandardOutput.ReadToEndAsync();
|
||||
// var errorTask = process.StandardError.ReadToEndAsync();
|
||||
|
||||
// await Task.WhenAll( outputTask, errorTask );
|
||||
|
||||
await process.WaitForExitAsync();
|
||||
|
||||
|
||||
response.exitCode = process.ExitCode;
|
||||
|
||||
if ( process.ExitCode == 0 )
|
||||
{
|
||||
response.rawResponse = outputResult.Join( "" );
|
||||
}
|
||||
else
|
||||
{
|
||||
response.rawResponse = errorResult.Join( "" );
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,95 @@
|
|||
#if TOOLS
|
||||
using Godot;
|
||||
using Rokojori;
|
||||
using System.Diagnostics;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Rokojori.Tools
|
||||
{
|
||||
|
||||
// https://docs.blender.org/api/current/bpy.ops.export_scene.html#bpy.ops.export_scene.fbx
|
||||
public class BlenderFBXExportSettings
|
||||
{
|
||||
public string path_mode = "AUTO";
|
||||
public string batch_mode = "OFF";
|
||||
public bool embed_textures = true;
|
||||
public bool use_batch_own_dir = false;
|
||||
public bool use_metadata = true;
|
||||
public bool check_existing = false;
|
||||
|
||||
// INCLUDE
|
||||
|
||||
public bool use_selection = false;
|
||||
public bool use_visible = false;
|
||||
public bool use_active_collection = false;
|
||||
public List<string> object_types = new List<string> { "EMPTY","CAMERA","LIGHT","ARMATURE","MESH","OTHER" };
|
||||
public bool use_custom_props = false;
|
||||
|
||||
// TRANSFORM
|
||||
public float global_scale = 1.0f;
|
||||
public string apply_scale_options = "FBX_SCALE_ALL"; // 'FBX_SCALE_NONE', 'FBX_SCALE_UNITS', 'FBX_SCALE_CUSTOM', 'FBX_SCALE_ALL'
|
||||
public string axis_forward = "-Z";
|
||||
public string axis_up = "Y";
|
||||
|
||||
public bool apply_unit_scale = false;
|
||||
public bool use_space_transform = true;
|
||||
public bool bake_space_transform = true;
|
||||
|
||||
|
||||
// GEOMETRY
|
||||
public bool use_mesh_modifiers = true; // Apply Modifiers
|
||||
public bool use_mesh_modifiers_render = false;
|
||||
public string mesh_smooth_type = "OFF"; // OFF, FACE, EDGES
|
||||
public bool use_subsurf = false;
|
||||
public bool use_mesh_edges = false;
|
||||
public bool use_tspace = false;
|
||||
public bool use_triangles = false;
|
||||
public string colors_type = "SRGB"; // NONE, SRGB, LINEAR
|
||||
|
||||
// ARMATURE
|
||||
|
||||
public bool add_leaf_bones = false;
|
||||
public string primary_bone_axis = "Y";
|
||||
public string secondary_bone_axis = "X";
|
||||
public string armature_nodetype = "NULL";
|
||||
|
||||
// BAKE ANIMATION
|
||||
public bool bake_anim = true;
|
||||
public bool bake_anim_use_all_bones = true;
|
||||
public bool bake_anim_use_nla_strips = true;
|
||||
public bool bake_anim_use_all_actions = true;
|
||||
public bool bake_anim_force_startend_keying = true;
|
||||
public float bake_anim_step = 1.0f;
|
||||
public float bake_anim_simplify_factor = 1.0f;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
public class BlenderGLTFtoFBX
|
||||
{
|
||||
|
||||
public static async Task<BlenderResponse> Run( string gltfPath, string fbxPath, BlenderFBXExportSettings fbxSettings = null )
|
||||
{
|
||||
var pythonPath = RokojoriPlugin.GlobalizedPath( "Tools/blender/gltf_to_fbx.py" );
|
||||
|
||||
var tempSettings = fbxSettings == null ? new BlenderFBXExportSettings() : fbxSettings;
|
||||
var tempSettingsPath = RokojoriPlugin.SaveTemporaryJSON( tempSettings );
|
||||
|
||||
var conversionArgs = new List<string>();
|
||||
conversionArgs.Add( gltfPath.EscapeAsPathForCommandLine() );
|
||||
conversionArgs.Add( fbxPath.EscapeAsPathForCommandLine() );
|
||||
conversionArgs.Add( tempSettingsPath.EscapeAsPathForCommandLine() );
|
||||
|
||||
|
||||
var response = await Blender.RunPython( pythonPath, conversionArgs );
|
||||
|
||||
FilesSync.Delete( tempSettingsPath );
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,47 @@
|
|||
#if TOOLS
|
||||
using Godot;
|
||||
using Rokojori;
|
||||
using System.Diagnostics;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Rokojori.Tools
|
||||
{
|
||||
[Tool]
|
||||
[GlobalClass]
|
||||
public partial class BlenderTest:Node
|
||||
{
|
||||
[Export]
|
||||
public string gltfPath;
|
||||
|
||||
[Export]
|
||||
public string fbxPath;
|
||||
|
||||
[ExportToolButton("Convert GLTF to FBX")]
|
||||
public Callable StatusButton => Callable.From(
|
||||
()=>
|
||||
{
|
||||
Convert();
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
async void Convert()
|
||||
{
|
||||
Blender.path = "C:/Program Files/Blender Foundation/Blender 4.0/blender.exe";
|
||||
|
||||
this.LogInfo( "Starting conversion..." );
|
||||
|
||||
var globalGLTFPath = ProjectSettings.GlobalizePath( gltfPath );
|
||||
var globalFBXPath = ProjectSettings.GlobalizePath( fbxPath );
|
||||
|
||||
var settings = new BlenderFBXExportSettings();
|
||||
|
||||
|
||||
var response = await BlenderGLTFtoFBX.Run( globalGLTFPath, globalFBXPath, settings );
|
||||
this.LogInfo( response.exitCode, ">>", response.rawResponse );
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1 @@
|
|||
uid://ij6cnc0jiygn
|
|
@ -0,0 +1,36 @@
|
|||
import bpy
|
||||
import sys
|
||||
import json
|
||||
|
||||
# Parse CLI arguments
|
||||
argv = sys.argv
|
||||
input_path = argv[-3]
|
||||
output_path = argv[-2]
|
||||
settings_json_path = argv[-1]
|
||||
|
||||
print( argv )
|
||||
print( input_path )
|
||||
print( output_path )
|
||||
print( settings_json_path )
|
||||
|
||||
# Reset the scene
|
||||
bpy.ops.wm.read_factory_settings(use_empty=True)
|
||||
|
||||
# Import GLTF/GLB
|
||||
bpy.ops.import_scene.gltf(filepath=input_path)
|
||||
|
||||
# Load FBX export settings from JSON file
|
||||
with open(settings_json_path, 'r') as f:
|
||||
export_settings = json.load(f)
|
||||
|
||||
# Convert certain keys to sets (JSON only allows lists)
|
||||
for key in ['object_types']:
|
||||
if key in export_settings and isinstance(export_settings[key], list):
|
||||
export_settings[key] = set(export_settings[key])
|
||||
|
||||
print( export_settings )
|
||||
# Export to FBX using settings from JSON
|
||||
bpy.ops.export_scene.fbx(
|
||||
filepath=output_path,
|
||||
**export_settings
|
||||
)
|
|
@ -0,0 +1,27 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Godot;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
||||
#if TOOLS
|
||||
|
||||
namespace Rokojori.Tools
|
||||
{
|
||||
public class GLTFExport
|
||||
{
|
||||
public static void Save( Node3D node, string path, string temporaryPath = "res://--temporary--" )
|
||||
{
|
||||
var state = new GltfState();
|
||||
|
||||
var doc = new GltfDocument();
|
||||
doc.AppendFromScene( node, state );
|
||||
doc.WriteToFilesystem( state, path );
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1 @@
|
|||
uid://ctvcbkmnyhgvn
|
Loading…
Reference in New Issue