diff --git a/RokojoriPlugin.cs b/RokojoriPlugin.cs index 36e2f31..e5efc72 100644 --- a/RokojoriPlugin.cs +++ b/RokojoriPlugin.cs @@ -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 ) ); diff --git a/Runtime/Colors/ColorChannelType.cs b/Runtime/Colors/ColorChannelType.cs new file mode 100644 index 0000000..fe5b8b5 --- /dev/null +++ b/Runtime/Colors/ColorChannelType.cs @@ -0,0 +1,16 @@ +using Godot; +using System.Collections.Generic; + +namespace Rokojori +{ + public enum ColorChannelType + { + Red, + Green, + Blue, + Hue, + Saturation, + Luminance, + Alpha + } +} diff --git a/Runtime/Colors/ColorX.cs b/Runtime/Colors/ColorX.cs index 100dddf..ee80797 100644 --- a/Runtime/Colors/ColorX.cs +++ b/Runtime/Colors/ColorX.cs @@ -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 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 ); diff --git a/Runtime/Colors/HSLColor.cs b/Runtime/Colors/HSLColor.cs index 13184b6..4811a0d 100644 --- a/Runtime/Colors/HSLColor.cs +++ b/Runtime/Colors/HSLColor.cs @@ -122,14 +122,39 @@ namespace Rokojori } return new HSLColor( h, s, l, a ); - } - + } + 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 ); } diff --git a/Runtime/Files/FilesSync.cs b/Runtime/Files/FilesSync.cs index 5f09121..d58ed1c 100644 --- a/Runtime/Files/FilesSync.cs +++ b/Runtime/Files/FilesSync.cs @@ -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 ); diff --git a/Runtime/Math/MathX.cs b/Runtime/Math/MathX.cs index 7822c5a..3c82e0e 100644 --- a/Runtime/Math/MathX.cs +++ b/Runtime/Math/MathX.cs @@ -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 indices, List 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,16 +455,18 @@ 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.MinValue = minValue; + curve.MinDomain = minX; + curve.MaxDomain = maxX; + curve.MinValue = minValue; curve.MaxValue = maxValue; return curve; diff --git a/Runtime/Procedural/Baking/PointMesh/PointMeshBaker.cs b/Runtime/Procedural/Baking/PointMesh/PointMeshBaker.cs index f5e8f32..d141b5e 100644 --- a/Runtime/Procedural/Baking/PointMesh/PointMeshBaker.cs +++ b/Runtime/Procedural/Baking/PointMesh/PointMeshBaker.cs @@ -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 ); diff --git a/Runtime/Procedural/Textures/ChannelMixer/TextureChanneMixelChannelSetting.cs b/Runtime/Procedural/Textures/ChannelMixer/TextureChanneMixelChannelSetting.cs new file mode 100644 index 0000000..13a3a2d --- /dev/null +++ b/Runtime/Procedural/Textures/ChannelMixer/TextureChanneMixelChannelSetting.cs @@ -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; + } + } +} \ No newline at end of file diff --git a/Runtime/Procedural/Textures/ChannelMixer/TextureChanneMixelChannelSetting.cs.uid b/Runtime/Procedural/Textures/ChannelMixer/TextureChanneMixelChannelSetting.cs.uid new file mode 100644 index 0000000..0ea624a --- /dev/null +++ b/Runtime/Procedural/Textures/ChannelMixer/TextureChanneMixelChannelSetting.cs.uid @@ -0,0 +1 @@ +uid://dae58ep6ml38n diff --git a/Runtime/Procedural/Textures/ChannelMixer/TextureChannelMixer.cs b/Runtime/Procedural/Textures/ChannelMixer/TextureChannelMixer.cs new file mode 100644 index 0000000..a96b2c6 --- /dev/null +++ b/Runtime/Procedural/Textures/ChannelMixer/TextureChannelMixer.cs @@ -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( 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 ); + + } + + } +} \ No newline at end of file diff --git a/Runtime/Procedural/Textures/ChannelMixer/TextureChannelMixer.cs.uid b/Runtime/Procedural/Textures/ChannelMixer/TextureChannelMixer.cs.uid new file mode 100644 index 0000000..af020b1 --- /dev/null +++ b/Runtime/Procedural/Textures/ChannelMixer/TextureChannelMixer.cs.uid @@ -0,0 +1 @@ +uid://chalyifwnlyjr diff --git a/Runtime/Procedural/Textures/ChannelMixer/TextureChannelMixerPreset.cs b/Runtime/Procedural/Textures/ChannelMixer/TextureChannelMixerPreset.cs new file mode 100644 index 0000000..f963cc4 --- /dev/null +++ b/Runtime/Procedural/Textures/ChannelMixer/TextureChannelMixerPreset.cs @@ -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; + } +} \ No newline at end of file diff --git a/Runtime/Procedural/Textures/ChannelMixer/TextureChannelMixerPreset.cs.uid b/Runtime/Procedural/Textures/ChannelMixer/TextureChannelMixerPreset.cs.uid new file mode 100644 index 0000000..618b909 --- /dev/null +++ b/Runtime/Procedural/Textures/ChannelMixer/TextureChannelMixerPreset.cs.uid @@ -0,0 +1 @@ +uid://cixw1u0gkbovt diff --git a/Runtime/Procedural/Textures/ChannelMixer/alpha-only.tres b/Runtime/Procedural/Textures/ChannelMixer/alpha-only.tres new file mode 100644 index 0000000..ef7e62d --- /dev/null +++ b/Runtime/Procedural/Textures/ChannelMixer/alpha-only.tres @@ -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" diff --git a/Runtime/Procedural/Textures/ChannelMixer/blue-only.tres b/Runtime/Procedural/Textures/ChannelMixer/blue-only.tres new file mode 100644 index 0000000..e307099 --- /dev/null +++ b/Runtime/Procedural/Textures/ChannelMixer/blue-only.tres @@ -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" diff --git a/Runtime/Procedural/Textures/ChannelMixer/green-only.tres b/Runtime/Procedural/Textures/ChannelMixer/green-only.tres new file mode 100644 index 0000000..9da6bc5 --- /dev/null +++ b/Runtime/Procedural/Textures/ChannelMixer/green-only.tres @@ -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" diff --git a/Runtime/Procedural/Textures/ChannelMixer/orm-to-metallic-smoothness.tres b/Runtime/Procedural/Textures/ChannelMixer/orm-to-metallic-smoothness.tres new file mode 100644 index 0000000..1eb9d74 --- /dev/null +++ b/Runtime/Procedural/Textures/ChannelMixer/orm-to-metallic-smoothness.tres @@ -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" diff --git a/Runtime/Procedural/Textures/ChannelMixer/red-only.tres b/Runtime/Procedural/Textures/ChannelMixer/red-only.tres new file mode 100644 index 0000000..b2f047a --- /dev/null +++ b/Runtime/Procedural/Textures/ChannelMixer/red-only.tres @@ -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" diff --git a/Runtime/Procedural/Textures/ColorCorrectionStack/ColorAdjustments.cs b/Runtime/Procedural/Textures/ColorCorrectionStack/ColorAdjustments.cs new file mode 100644 index 0000000..d211358 --- /dev/null +++ b/Runtime/Procedural/Textures/ColorCorrectionStack/ColorAdjustments.cs @@ -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; + } + } +} \ No newline at end of file diff --git a/Runtime/Procedural/Textures/ColorCorrectionStack/ColorAdjustments.cs.uid b/Runtime/Procedural/Textures/ColorCorrectionStack/ColorAdjustments.cs.uid new file mode 100644 index 0000000..2fb6f52 --- /dev/null +++ b/Runtime/Procedural/Textures/ColorCorrectionStack/ColorAdjustments.cs.uid @@ -0,0 +1 @@ +uid://bpulemr8hxlht diff --git a/Runtime/Procedural/Textures/ColorCorrectionStack/ColorCorrectionPreset.cs b/Runtime/Procedural/Textures/ColorCorrectionStack/ColorCorrectionPreset.cs new file mode 100644 index 0000000..152ddae --- /dev/null +++ b/Runtime/Procedural/Textures/ColorCorrectionStack/ColorCorrectionPreset.cs @@ -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 ); + } + } +} \ No newline at end of file diff --git a/Runtime/Procedural/Textures/ColorCorrectionStack/ColorCorrectionPreset.cs.uid b/Runtime/Procedural/Textures/ColorCorrectionStack/ColorCorrectionPreset.cs.uid new file mode 100644 index 0000000..74d2a86 --- /dev/null +++ b/Runtime/Procedural/Textures/ColorCorrectionStack/ColorCorrectionPreset.cs.uid @@ -0,0 +1 @@ +uid://eh02vfeoi8xb diff --git a/Runtime/Procedural/Textures/ColorCorrectionStack/ColorCorrectionStack.cs b/Runtime/Procedural/Textures/ColorCorrectionStack/ColorCorrectionStack.cs new file mode 100644 index 0000000..f342fe4 --- /dev/null +++ b/Runtime/Procedural/Textures/ColorCorrectionStack/ColorCorrectionStack.cs @@ -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 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(); + + 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 ); + // } + } +} \ No newline at end of file diff --git a/Runtime/Procedural/Textures/ColorCorrectionStack/ColorCorrectionStack.cs.uid b/Runtime/Procedural/Textures/ColorCorrectionStack/ColorCorrectionStack.cs.uid new file mode 100644 index 0000000..f838187 --- /dev/null +++ b/Runtime/Procedural/Textures/ColorCorrectionStack/ColorCorrectionStack.cs.uid @@ -0,0 +1 @@ +uid://b5ot2h42auy32 diff --git a/Runtime/Procedural/Textures/ColorCorrectionStack/Colorize.cs b/Runtime/Procedural/Textures/ColorCorrectionStack/Colorize.cs new file mode 100644 index 0000000..55208af --- /dev/null +++ b/Runtime/Procedural/Textures/ColorCorrectionStack/Colorize.cs @@ -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; + } + } +} \ No newline at end of file diff --git a/Runtime/Procedural/Textures/ColorCorrectionStack/Colorize.cs.uid b/Runtime/Procedural/Textures/ColorCorrectionStack/Colorize.cs.uid new file mode 100644 index 0000000..63a8ba4 --- /dev/null +++ b/Runtime/Procedural/Textures/ColorCorrectionStack/Colorize.cs.uid @@ -0,0 +1 @@ +uid://d3jgv8mofjss5 diff --git a/Runtime/Procedural/Textures/ColorCorrectionStack/CrossCurves.cs b/Runtime/Procedural/Textures/ColorCorrectionStack/CrossCurves.cs new file mode 100644 index 0000000..a510d27 --- /dev/null +++ b/Runtime/Procedural/Textures/ColorCorrectionStack/CrossCurves.cs @@ -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; + } + + + } +} \ No newline at end of file diff --git a/Runtime/Procedural/Textures/ColorCorrectionStack/CrossCurves.cs.uid b/Runtime/Procedural/Textures/ColorCorrectionStack/CrossCurves.cs.uid new file mode 100644 index 0000000..1fe4c95 --- /dev/null +++ b/Runtime/Procedural/Textures/ColorCorrectionStack/CrossCurves.cs.uid @@ -0,0 +1 @@ +uid://c6a2k4kldmq6k diff --git a/Runtime/Procedural/Textures/ColorCorrectionStack/HSLCurves.cs b/Runtime/Procedural/Textures/ColorCorrectionStack/HSLCurves.cs new file mode 100644 index 0000000..d24f11f --- /dev/null +++ b/Runtime/Procedural/Textures/ColorCorrectionStack/HSLCurves.cs @@ -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(); + } + } +} \ No newline at end of file diff --git a/Runtime/Procedural/Textures/ColorCorrectionStack/HSLCurves.cs.uid b/Runtime/Procedural/Textures/ColorCorrectionStack/HSLCurves.cs.uid new file mode 100644 index 0000000..6c31637 --- /dev/null +++ b/Runtime/Procedural/Textures/ColorCorrectionStack/HSLCurves.cs.uid @@ -0,0 +1 @@ +uid://dlxt0pm7dpuoy diff --git a/Runtime/Procedural/Textures/ColorCorrectionStack/RGBCurves.cs b/Runtime/Procedural/Textures/ColorCorrectionStack/RGBCurves.cs new file mode 100644 index 0000000..a28196f --- /dev/null +++ b/Runtime/Procedural/Textures/ColorCorrectionStack/RGBCurves.cs @@ -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 ); + } + } +} \ No newline at end of file diff --git a/Runtime/Procedural/Textures/ColorCorrectionStack/RGBCurves.cs.uid b/Runtime/Procedural/Textures/ColorCorrectionStack/RGBCurves.cs.uid new file mode 100644 index 0000000..0422afc --- /dev/null +++ b/Runtime/Procedural/Textures/ColorCorrectionStack/RGBCurves.cs.uid @@ -0,0 +1 @@ +uid://bf2q4pgpi2vl2 diff --git a/Runtime/Procedural/Textures/ColorCorrectionStack/_XX_ColorCorrectionModifier.cs b/Runtime/Procedural/Textures/ColorCorrectionStack/_XX_ColorCorrectionModifier.cs new file mode 100644 index 0000000..0e64f71 --- /dev/null +++ b/Runtime/Procedural/Textures/ColorCorrectionStack/_XX_ColorCorrectionModifier.cs @@ -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; + } + } +} \ No newline at end of file diff --git a/Runtime/Procedural/Textures/ColorCorrectionStack/_XX_ColorCorrectionModifier.cs.uid b/Runtime/Procedural/Textures/ColorCorrectionStack/_XX_ColorCorrectionModifier.cs.uid new file mode 100644 index 0000000..efb8708 --- /dev/null +++ b/Runtime/Procedural/Textures/ColorCorrectionStack/_XX_ColorCorrectionModifier.cs.uid @@ -0,0 +1 @@ +uid://b6uqqar4kc4am diff --git a/Runtime/Procedural/Textures/ImageSaveSettings.cs b/Runtime/Procedural/Textures/ImageSaveSettings.cs new file mode 100644 index 0000000..180c19f --- /dev/null +++ b/Runtime/Procedural/Textures/ImageSaveSettings.cs @@ -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 ) + { + + } + } +} \ No newline at end of file diff --git a/Runtime/Procedural/Textures/ImageSaveSettings.cs.uid b/Runtime/Procedural/Textures/ImageSaveSettings.cs.uid new file mode 100644 index 0000000..7829db9 --- /dev/null +++ b/Runtime/Procedural/Textures/ImageSaveSettings.cs.uid @@ -0,0 +1 @@ +uid://ca0t2btbm43ax diff --git a/Runtime/Procedural/Textures/Images.cs b/Runtime/Procedural/Textures/Images.cs new file mode 100644 index 0000000..6cfbcbd --- /dev/null +++ b/Runtime/Procedural/Textures/Images.cs @@ -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 ); + } + } +} \ No newline at end of file diff --git a/Runtime/Procedural/Textures/PNGSettings.cs b/Runtime/Procedural/Textures/PNGSettings.cs new file mode 100644 index 0000000..3a4ced9 --- /dev/null +++ b/Runtime/Procedural/Textures/PNGSettings.cs @@ -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 ); + } + } +} \ No newline at end of file diff --git a/Runtime/Procedural/Textures/PNGSettings.cs.uid b/Runtime/Procedural/Textures/PNGSettings.cs.uid new file mode 100644 index 0000000..5b08359 --- /dev/null +++ b/Runtime/Procedural/Textures/PNGSettings.cs.uid @@ -0,0 +1 @@ +uid://m1agofoxqejh diff --git a/Runtime/Procedural/Textures/TextureCombiner/TextureCombinerBuffer.cs b/Runtime/Procedural/Textures/TextureCombiner/TextureCombinerBuffer.cs index 285431e..b73a8f0 100644 --- a/Runtime/Procedural/Textures/TextureCombiner/TextureCombinerBuffer.cs +++ b/Runtime/Procedural/Textures/TextureCombiner/TextureCombinerBuffer.cs @@ -56,9 +56,17 @@ 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( path ); + var sourceBuffer = TextureCombinerBuffer.From( texture, srgbConversion ); + + return sourceBuffer; } public void CopyFromSampled( TextureCombinerBuffer source, int x, int y, int w, int 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,18 +198,33 @@ namespace Rokojori { if ( srgbConversion != 0 ) { - var gamma = Mathf.Pow( 2.2f, srgbConversion ); - - for ( int i = 0; i < w; i++ ) - { - for ( int j = 0; j < h; j++ ) + if ( srgbConversion == 1 ) + { + for ( int i = 0; i < w; i++ ) { - var sourcePixel = image == null ? new Color( 0, 0, 0 ) : image.GetPixel( sourceX + i, sourceY + j ); - sourcePixel = sourcePixel.Gamma( gamma ); - SetAt( ownX + i, ownY + j, sourcePixel ); + for ( int j = 0; j < h; j++ ) + { + var sourcePixel = image == null ? new Color( 0, 0, 0 ) : image.GetPixel( sourceX + i, sourceY + j ); + 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 { diff --git a/Runtime/Reallusion/CCImportFile/CCCustomShader.cs b/Runtime/Reallusion/CCImportFile/CCCustomShader.cs index 9e8b7b5..ceb9243 100644 --- a/Runtime/Reallusion/CCImportFile/CCCustomShader.cs +++ b/Runtime/Reallusion/CCImportFile/CCCustomShader.cs @@ -85,7 +85,7 @@ namespace Rokojori.Reallusion if ( sRGB ) { - color = color.linearToSRGB(); + color = color.LinearToSRGB(); } return color; diff --git a/Runtime/Rendering/Context/RDContext.cs b/Runtime/Rendering/Context/RDContext.cs index 7182f84..49919bf 100644 --- a/Runtime/Rendering/Context/RDContext.cs +++ b/Runtime/Rendering/Context/RDContext.cs @@ -143,7 +143,7 @@ namespace Rokojori { // effect.Verbose( "Incoming Uniform Index", setIndex ); - if ( setIndex == -1 ) + if ( setIndex == -1 ) { setIndex = _uniformSets.Count; } diff --git a/Runtime/Text/Text.cs b/Runtime/Text/Text.cs new file mode 100644 index 0000000..cb567cf --- /dev/null +++ b/Runtime/Text/Text.cs @@ -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; + } + + } +} \ No newline at end of file diff --git a/Runtime/VirtualCameras/MouseEditorCamera/Inputs/Sensors/Move Back.tres b/Runtime/VirtualCameras/MouseEditorCamera/Inputs/Sensors/Move Back.tres index 9fdc9c6..d739e03 100644 --- a/Runtime/VirtualCameras/MouseEditorCamera/Inputs/Sensors/Move Back.tres +++ b/Runtime/VirtualCameras/MouseEditorCamera/Inputs/Sensors/Move Back.tres @@ -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 diff --git a/Runtime/VirtualCameras/MouseEditorCamera/Inputs/Sensors/Move Down.tres b/Runtime/VirtualCameras/MouseEditorCamera/Inputs/Sensors/Move Down.tres index bc17839..32e6829 100644 --- a/Runtime/VirtualCameras/MouseEditorCamera/Inputs/Sensors/Move Down.tres +++ b/Runtime/VirtualCameras/MouseEditorCamera/Inputs/Sensors/Move Down.tres @@ -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 diff --git a/Runtime/VirtualCameras/MouseEditorCamera/Inputs/Sensors/Move Forward.tres b/Runtime/VirtualCameras/MouseEditorCamera/Inputs/Sensors/Move Forward.tres index 1176f22..3053b73 100644 --- a/Runtime/VirtualCameras/MouseEditorCamera/Inputs/Sensors/Move Forward.tres +++ b/Runtime/VirtualCameras/MouseEditorCamera/Inputs/Sensors/Move Forward.tres @@ -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 diff --git a/Runtime/VirtualCameras/MouseEditorCamera/Inputs/Sensors/Move Left.tres b/Runtime/VirtualCameras/MouseEditorCamera/Inputs/Sensors/Move Left.tres index 64e3c30..08dcde1 100644 --- a/Runtime/VirtualCameras/MouseEditorCamera/Inputs/Sensors/Move Left.tres +++ b/Runtime/VirtualCameras/MouseEditorCamera/Inputs/Sensors/Move Left.tres @@ -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 diff --git a/Runtime/VirtualCameras/MouseEditorCamera/Inputs/Sensors/Move Right.tres b/Runtime/VirtualCameras/MouseEditorCamera/Inputs/Sensors/Move Right.tres index fa7bb58..0a5579a 100644 --- a/Runtime/VirtualCameras/MouseEditorCamera/Inputs/Sensors/Move Right.tres +++ b/Runtime/VirtualCameras/MouseEditorCamera/Inputs/Sensors/Move Right.tres @@ -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 diff --git a/Runtime/VirtualCameras/MouseEditorCamera/Inputs/Sensors/Move Upward.tres b/Runtime/VirtualCameras/MouseEditorCamera/Inputs/Sensors/Move Upward.tres index bb9eefb..739c4a6 100644 --- a/Runtime/VirtualCameras/MouseEditorCamera/Inputs/Sensors/Move Upward.tres +++ b/Runtime/VirtualCameras/MouseEditorCamera/Inputs/Sensors/Move Upward.tres @@ -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 diff --git a/Runtime/VirtualCameras/MouseEditorCamera/Inputs/Sensors/Zoom In.tres b/Runtime/VirtualCameras/MouseEditorCamera/Inputs/Sensors/Zoom In.tres index e337f8e..708d1ec 100644 --- a/Runtime/VirtualCameras/MouseEditorCamera/Inputs/Sensors/Zoom In.tres +++ b/Runtime/VirtualCameras/MouseEditorCamera/Inputs/Sensors/Zoom In.tres @@ -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 diff --git a/Runtime/VirtualCameras/MouseEditorCamera/Inputs/Sensors/Zoom Out.tres b/Runtime/VirtualCameras/MouseEditorCamera/Inputs/Sensors/Zoom Out.tres index ffe8ecf..8fe0bb2 100644 --- a/Runtime/VirtualCameras/MouseEditorCamera/Inputs/Sensors/Zoom Out.tres +++ b/Runtime/VirtualCameras/MouseEditorCamera/Inputs/Sensors/Zoom Out.tres @@ -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 diff --git a/Runtime/VirtualCameras/PostProcess/AdjustmentsEffect.cs b/Runtime/VirtualCameras/PostProcess/AdjustmentsEffect.cs new file mode 100644 index 0000000..d182051 --- /dev/null +++ b/Runtime/VirtualCameras/PostProcess/AdjustmentsEffect.cs @@ -0,0 +1,13 @@ + +using Godot; +using System.Collections.Generic; +using System; +namespace Rokojori +{ + [Tool] + [GlobalClass] + public partial class AdjustmentsEffect:PostProcessVolumeEffect + { + + } +} \ No newline at end of file diff --git a/Runtime/VirtualCameras/PostProcess/AdjustmentsEffect.cs.uid b/Runtime/VirtualCameras/PostProcess/AdjustmentsEffect.cs.uid new file mode 100644 index 0000000..2d237f3 --- /dev/null +++ b/Runtime/VirtualCameras/PostProcess/AdjustmentsEffect.cs.uid @@ -0,0 +1 @@ +uid://b7t25777r8v13 diff --git a/Runtime/VirtualCameras/PostProcess/environment_adjustments_3d_lut_template.webp b/Runtime/VirtualCameras/PostProcess/environment_adjustments_3d_lut_template.webp new file mode 100644 index 0000000..dd5bff5 Binary files /dev/null and b/Runtime/VirtualCameras/PostProcess/environment_adjustments_3d_lut_template.webp differ diff --git a/Runtime/VirtualCameras/PostProcess/environment_adjustments_3d_lut_template.webp.import b/Runtime/VirtualCameras/PostProcess/environment_adjustments_3d_lut_template.webp.import new file mode 100644 index 0000000..dc9ccb3 --- /dev/null +++ b/Runtime/VirtualCameras/PostProcess/environment_adjustments_3d_lut_template.webp.import @@ -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 diff --git a/Tools/blender/Blender.cs b/Tools/blender/Blender.cs new file mode 100644 index 0000000..b6c5049 --- /dev/null +++ b/Tools/blender/Blender.cs @@ -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 RunPython( string pythonPath, List args, string workingDirectory = null ) + { + var pythonArgs = new List(); + + 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 Run( List 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(); + var errorResult = new List(); + + 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 \ No newline at end of file diff --git a/Tools/blender/BlenderGLTFtoFBX.cs b/Tools/blender/BlenderGLTFtoFBX.cs new file mode 100644 index 0000000..fbf728f --- /dev/null +++ b/Tools/blender/BlenderGLTFtoFBX.cs @@ -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 object_types = new List { "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 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(); + 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 \ No newline at end of file diff --git a/Tools/blender/BlenderTest.cs b/Tools/blender/BlenderTest.cs new file mode 100644 index 0000000..7d56585 --- /dev/null +++ b/Tools/blender/BlenderTest.cs @@ -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 \ No newline at end of file diff --git a/Tools/blender/BlenderTest.cs.uid b/Tools/blender/BlenderTest.cs.uid new file mode 100644 index 0000000..3649ee9 --- /dev/null +++ b/Tools/blender/BlenderTest.cs.uid @@ -0,0 +1 @@ +uid://ij6cnc0jiygn diff --git a/Tools/blender/gltf_to_fbx.py b/Tools/blender/gltf_to_fbx.py new file mode 100644 index 0000000..75969df --- /dev/null +++ b/Tools/blender/gltf_to_fbx.py @@ -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 +) \ No newline at end of file diff --git a/Tools/gltf-export/GLTFExport.cs b/Tools/gltf-export/GLTFExport.cs new file mode 100644 index 0000000..5a968a8 --- /dev/null +++ b/Tools/gltf-export/GLTFExport.cs @@ -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 \ No newline at end of file diff --git a/Tools/gltf-export/GLTFExport.cs.uid b/Tools/gltf-export/GLTFExport.cs.uid new file mode 100644 index 0000000..fad35ba --- /dev/null +++ b/Tools/gltf-export/GLTFExport.cs.uid @@ -0,0 +1 @@ +uid://ctvcbkmnyhgvn