Files
KopMap/Assets/FImpossible Creations/Editor/Editor Tools/F Texture Tools/FTexture Edit Windows/FBlendToolWindow.cs

205 lines
7.8 KiB
C#
Raw Normal View History

2025-09-02 18:55:19 +08:00
using FIMSpace.FEditor;
using System;
using UnityEditor;
using UnityEngine;
namespace FIMSpace.FTextureTools
{
public class FBlendToolWindow : FTextureProcessWindow
{
enum EBlendMode
{
AlphaBlend,
Additive,
Multiply,
NormalMapBlending,
}
EBlendMode Mode = EBlendMode.AlphaBlend;
float BlendValue = 0.5f;
Texture2D BlendWith;
bool BlendWithReadable = false;
float BlendWithTiling = 1f;
Texture2D BlendWithMemo = null;
public static void Init()
{
FBlendToolWindow window = (FBlendToolWindow)GetWindow( typeof( FBlendToolWindow ) );
window.titleContent = new GUIContent( "Blend Tool", FTextureToolsGUIUtilities.FindIcon( "SPR_BlendGen" ), "Blend two textures operation" );
window.previewScale = FEPreview.m_1x1;
window.drawPreviewScale = true;
window.previewSize = 100;
window.position = new Rect( 340, 50, 550, 580 );
window.Show();
called = true;
}
protected override void OnGUICustom()
{
EditorGUI.BeginChangeCheck();
Mode = (EBlendMode)EditorGUILayout.EnumPopup( "Mode:", Mode );
GUILayout.Space( 8 );
BlendValue = EditorGUILayout.Slider( "Blend:", BlendValue, 0f, 1f );
GUILayout.Space( 8 );
BlendWith = EditorGUILayout.ObjectField( "Blend With:", BlendWith, typeof( Texture2D ), false ) as Texture2D;
#region Blend-with options
if( BlendWith != null )
{
string path = AssetDatabase.GetAssetPath( BlendWith );
TextureImporter tImp = (TextureImporter)AssetImporter.GetAtPath( path );
if( tImp is null == false )
{
BlendWithReadable = tImp.isReadable;
GUILayout.Space( 4 );
EditorGUILayout.BeginHorizontal();
GUILayout.Space( 32 );
if( tImp.isReadable == false ) GUI.backgroundColor = Color.green;
if( GUILayout.Button( "Switch readonly for '" + BlendWith.name + "' to " + ( !tImp.isReadable ).ToString() ) )
{
tImp.isReadable = !tImp.isReadable;
AssetDatabase.ImportAsset( path, ImportAssetOptions.ForceUpdate );
BlendWithReadable = tImp.isReadable;
}
GUI.backgroundColor = Color.white;
GUILayout.Space( 32 );
EditorGUILayout.EndHorizontal();
//GUILayout.Space( 5 );
//EditorGUILayout.BeginHorizontal();
//float highRange = BlendWithTiling > 4f ? 16f : 4.001f;
//BlendWithTiling = EditorGUILayout.Slider( "Blend-With Tiling:", BlendWithTiling, 0.1f, highRange );
//EditorGUILayout.EndHorizontal();
Texture2D srcTex = GetFirstTexture;
if( srcTex ) if( BlendWith.width != srcTex.width )
{
EditorGUILayout.HelpBox( "Texture sizes differs, preview can look different than final file result!", MessageType.None );
}
}
if( BlendWithReadable == false )
EditorGUILayout.HelpBox( "Texture must have 'Read/Write' enabled", MessageType.Warning );
}
else
BlendWithReadable = false;
#endregion
if( EditorGUI.EndChangeCheck() )
somethingChanged = true;
else
somethingChanged = false;
}
protected override void ProcessTexture( Texture2D source, Texture2D target, bool preview = true )
{
if( BlendWith == null ) return;
if( BlendWithReadable == false ) return;
if( !preview ) EditorUtility.DisplayProgressBar( "Blending Texture...", "Preparing... ", 2f / 5f );
#region Prepare Blend-With reference
Color32[] sourcePixels = source.GetPixels32();
Color32[] newPixels = source.GetPixels32();
int targetWidth = Mathf.RoundToInt( source.width / BlendWithTiling );
int targetHeight = Mathf.RoundToInt( source.height / BlendWithTiling );
if( targetWidth < 1 ) targetWidth = 1;
if( targetHeight < 1 ) targetHeight = 1;
if( BlendWithMemo == null || BlendWithMemo.width != targetWidth || BlendWithMemo.height != targetHeight || BlendWithMemo.name != BlendWith.name )
{
BlendWithMemo = FTextureEditorToolsMethods.GenerateScaledTexture2DReference( BlendWith, new Vector2( targetWidth, targetHeight ), preview ? 2 : 4 );
BlendWithMemo.name = BlendWith.name;
}
Texture2D blendWithSource = BlendWithMemo;
if( blendWithSource.width < 4 )
{
if( !preview ) EditorUtility.ClearProgressBar();
return;
}
Color32[] blendWithPixels = blendWithSource.GetPixels32();
#endregion
if( !preview )
EditorUtility.DisplayProgressBar( "Blending Texture...", "Blending... ", 3f / 5f );
Vector2 srcDimensions = GetDimensions( source );
if( Mode == EBlendMode.AlphaBlend ) pixelOperation = AlphaBlend;
else if( Mode == EBlendMode.Additive ) pixelOperation = AdditiveBlend;
else if( Mode == EBlendMode.Multiply ) pixelOperation = MultiplyBlend;
else if( Mode == EBlendMode.NormalMapBlending ) pixelOperation = NormalBlend;
for( int x = 0; x < source.width; x++ )
{
for( int y = 0; y < source.height; y++ )
{
int pxIndex = GetPX( x, y, srcDimensions );
Color srcPixel = sourcePixels[pxIndex];
Color blendWithColor = blendWithPixels[GetPXLoopSkipEdges( x, y, new Vector2( blendWithSource.width, blendWithSource.height ) )];
Color tgtColor = pixelOperation.Invoke( srcPixel, blendWithColor );
newPixels[pxIndex] = tgtColor;
}
}
// Finalizing changes
if( !preview ) EditorUtility.DisplayProgressBar( "Equalizing Texture...", "Applying Equalization to Texture... ", 3.85f / 5f );
target.SetPixels32( newPixels );
target.Apply( false, false );
if( !preview )
EditorUtility.ClearProgressBar();
}
Func<Color32, Color32, Color32> pixelOperation = null;
Color32 AlphaBlend( Color32 source, Color32 target ) => Color32.Lerp( source, target, BlendValue );
Color32 AdditiveBlend( Color32 source, Color32 target )
{
Color32 newColor = new Color32();
newColor.r = (byte)Mathf.Min( 255, source.r + target.r );
newColor.g = (byte)Mathf.Min( 255, source.g + target.g );
newColor.b = (byte)Mathf.Min( 255, source.b + target.b );
newColor.a = target.a;
return Color32.Lerp( source, newColor, BlendValue );
}
Color32 MultiplyBlend( Color32 source, Color32 target )
{
Color srcCol = (Color)source;
Color newColor = (Color)target;
newColor.r = Mathf.Min( 1f, srcCol.r * newColor.r );
newColor.g = Mathf.Min( 1f, srcCol.g * newColor.g );
newColor.b = Mathf.Min( 1f, srcCol.b * newColor.b );
return Color32.Lerp( source, (Color32)newColor, BlendValue );
}
Color32 NormalBlend( Color32 source, Color32 target ) => FTextureEditorToolsMethods.BlendNormals( source, target, BlendValue );
}
}