2025-07-08 10:46:31 +00:00
#if UNITY_EDITOR
using System.IO ;
using UnityEditor ;
using UnityEngine ;
using ShaderType = AllIn1SpriteShader . AllIn1Shader . ShaderTypes ;
namespace AllIn1SpriteShader
{
public class AllIn1ShaderWindow : EditorWindow
{
private const string versionString = "4.2" ;
[MenuItem("Tools/AllIn1/SpriteShaderWindow")]
public static void ShowAllIn1ShaderWindowWindow ( )
{
GetWindow < AllIn1ShaderWindow > ( "All In 1 Shader Window" ) ;
}
public static readonly string CUSTOM_EDITOR_HEADER = "AllIn1SpriteShaderEditorImage" ;
private static string basePath = "Assets/Plugins/AllIn1SpriteShader" ;
public static readonly string materialsSavesRelativePath = "/Materials" ;
public static readonly string renderImagesSavesRelativePath = "/Textures" ;
public static readonly string normalMapSavesRelativePath = "/Textures/NormalMaps" ;
public static readonly string gradientSavesRelativePath = "/Textures/GradientTextures" ;
public Vector2 scrollPosition = Vector2 . zero ;
private Texture2D imageInspector ;
private DefaultAsset materialTargetFolder = null ;
private GUIStyle style , bigLabel = new GUIStyle ( ) , titleStyle = new GUIStyle ( ) ;
private const int bigFontSize = 16 ;
AllIn1Shader . ShaderTypes shaderTypes = AllIn1Shader . ShaderTypes . Default ;
bool showUrpWarning = false ;
double warningTime = 0f ;
private Texture2D targetNormalImage ;
private float normalStrength = 5f ;
private int normalSmoothing = 1 ;
private int isComputingNormals = 0 ;
private enum TextureSizes
{
_2 = 2 ,
_4 = 4 ,
_8 = 8 ,
_16 = 16 ,
_32 = 32 ,
_64 = 64 ,
_128 = 128 ,
_256 = 256 ,
_512 = 512 ,
_1024 = 1024 ,
_2048 = 2048
}
private TextureSizes textureSizes = TextureSizes . _128 ;
[SerializeField] private Gradient gradient = new Gradient ( ) ;
private FilterMode gradientFiltering = FilterMode . Bilinear ;
private enum ImageType
{
ShowImage ,
HideInComponent ,
HideEverywhere
}
private ImageType imageType ;
private void OnGUI ( )
{
style = new GUIStyle ( EditorStyles . helpBox ) ;
style . margin = new RectOffset ( 0 , 0 , 0 , 0 ) ;
bigLabel = new GUIStyle ( EditorStyles . boldLabel ) ;
bigLabel . fontSize = bigFontSize ;
titleStyle . alignment = TextAnchor . MiddleLeft ;
using ( var scrollView = new EditorGUILayout . ScrollViewScope ( scrollPosition , GUILayout . Width ( position . width ) , GUILayout . Height ( position . height ) ) )
{
scrollPosition = scrollView . scrollPosition ;
ShowImageAndSetImageEditorPref ( ) ;
ShowAssetImageOptionsToggle ( ) ;
DefaultAssetShader ( ) ;
DrawLine ( Color . grey , 1 , 3 ) ;
GUILayout . Label ( "Material Save Path" , bigLabel ) ;
GUILayout . Space ( 20 ) ;
GUILayout . Label ( "Select the folder where new Materials will be saved when the Save Material To Folder button of the asset component is pressed" , EditorStyles . boldLabel ) ;
HandleSaveFolderEditorPref ( "All1ShaderMaterials" , basePath + materialsSavesRelativePath , "Material" ) ;
DrawLine ( Color . grey , 1 , 3 ) ;
GUILayout . Label ( "Render Material to Image Save Path" , bigLabel ) ;
GUILayout . Space ( 20 ) ;
EditorGUILayout . BeginHorizontal ( ) ;
{
float scaleSlider = 1 ;
if ( PlayerPrefs . HasKey ( "All1ShaderRenderImagesScale" ) ) scaleSlider = PlayerPrefs . GetFloat ( "All1ShaderRenderImagesScale" ) ;
GUILayout . Label ( "Rendered Image Texture Scale" , GUILayout . MaxWidth ( 190 ) ) ;
scaleSlider = EditorGUILayout . Slider ( scaleSlider , 0.2f , 5f , GUILayout . MaxWidth ( 200 ) ) ;
if ( GUILayout . Button ( "Default Value" , GUILayout . MaxWidth ( 100 ) ) ) PlayerPrefs . SetFloat ( "All1ShaderRenderImagesScale" , 1f ) ;
else PlayerPrefs . SetFloat ( "All1ShaderRenderImagesScale" , scaleSlider ) ;
}
EditorGUILayout . EndVertical ( ) ;
GUILayout . Label ( "Select the folder where new Images will be saved when the Render Material To Image button of the asset component is pressed" , EditorStyles . boldLabel ) ;
HandleSaveFolderEditorPref ( "All1ShaderRenderImages" , basePath + renderImagesSavesRelativePath , "Images" ) ;
DrawLine ( Color . grey , 1 , 3 ) ;
NormalMapCreator ( ) ;
DrawLine ( Color . grey , 1 , 3 ) ;
GradientCreator ( ) ;
DrawLine ( Color . grey , 1 , 3 ) ;
GUILayout . Space ( 10 ) ;
SceneNotificationsToggle ( ) ;
DrawLine ( Color . grey , 1 , 3 ) ;
GUILayout . Space ( 10 ) ;
RefreshLitShader ( ) ;
GUILayout . Space ( 10 ) ;
DrawLine ( Color . grey , 1 , 3 ) ;
GUILayout . Label ( "Current asset version is " + versionString , EditorStyles . boldLabel ) ;
}
}
private void ShowImageAndSetImageEditorPref ( )
{
if ( ! EditorPrefs . HasKey ( "allIn1ImageConfig" ) )
{
EditorPrefs . SetInt ( "allIn1ImageConfig" , ( int ) ImageType . ShowImage ) ;
}
imageType = ( ImageType ) EditorPrefs . GetInt ( "allIn1ImageConfig" ) ;
if ( imageType = = ImageType . HideEverywhere ) return ;
switch ( imageType )
{
case ImageType . ShowImage :
case ImageType . HideInComponent :
if ( imageInspector = = null ) imageInspector = GetInspectorImage ( ) ;
break ;
}
if ( imageInspector )
{
Rect rect = EditorGUILayout . GetControlRect ( GUILayout . Height ( 50 ) ) ;
GUI . DrawTexture ( rect , imageInspector , ScaleMode . ScaleToFit , true ) ;
}
DrawLine ( Color . grey , 1 , 3 ) ;
}
public static Texture2D GetInspectorImage ( ) = > GetImage ( CUSTOM_EDITOR_HEADER ) ;
private static Texture2D GetImage ( string textureName )
{
string [ ] guids = AssetDatabase . FindAssets ( $"{textureName} t:texture" ) ;
if ( guids . Length > 0 )
{
string path = AssetDatabase . GUIDToAssetPath ( guids [ 0 ] ) ;
return AssetDatabase . LoadAssetAtPath < Texture2D > ( path ) ;
}
return null ;
}
private void ShowAssetImageOptionsToggle ( )
{
GUILayout . Label ( "Asset Image Display Options" , bigLabel ) ;
GUILayout . Space ( 20 ) ;
int previousImageType = ( int ) imageType ;
imageType = ( ImageType ) EditorGUILayout . EnumPopup ( imageType , GUILayout . MaxWidth ( 200 ) ) ;
if ( ( int ) imageType ! = previousImageType ) EditorPrefs . SetInt ( "allIn1ImageConfig" , ( int ) imageType ) ;
DrawLine ( Color . grey , 1 , 3 ) ;
}
private void DefaultAssetShader ( )
{
GUILayout . Label ( "Default Asset Shader" , bigLabel ) ;
GUILayout . Space ( 20 ) ;
GUILayout . Label ( "This is the shader variant that will be assigned by default to Sprites and UI Images when the asset component is added" , EditorStyles . boldLabel ) ;
bool isUrp = false ;
Shader temp = FindShader ( "AllIn1Urp2dRenderer" ) ;
if ( temp ! = null ) isUrp = true ;
shaderTypes = ( AllIn1Shader . ShaderTypes ) PlayerPrefs . GetInt ( "allIn1DefaultShader" ) ;
int previousShaderType = ( int ) shaderTypes ;
shaderTypes = ( AllIn1Shader . ShaderTypes ) EditorGUILayout . EnumPopup ( shaderTypes , GUILayout . MaxWidth ( 200 ) ) ;
if ( previousShaderType ! = ( int ) shaderTypes )
{
if ( ! isUrp & & shaderTypes = = AllIn1Shader . ShaderTypes . Urp2dRenderer )
{
showUrpWarning = true ;
warningTime = EditorApplication . timeSinceStartup + 5 ;
}
else
{
PlayerPrefs . SetInt ( "allIn1DefaultShader" , ( int ) shaderTypes ) ;
showUrpWarning = false ;
}
}
if ( warningTime < EditorApplication . timeSinceStartup ) showUrpWarning = false ;
if ( isUrp ) showUrpWarning = false ;
if ( ! isUrp & & ! showUrpWarning & & shaderTypes = = AllIn1Shader . ShaderTypes . Urp2dRenderer )
{
showUrpWarning = true ;
warningTime = EditorApplication . timeSinceStartup + 5 ;
shaderTypes = AllIn1Shader . ShaderTypes . Default ;
PlayerPrefs . SetInt ( "allIn1DefaultShader" , ( int ) shaderTypes ) ;
}
if ( showUrpWarning ) EditorGUILayout . HelpBox (
"You can't set the URP 2D Renderer variant since you didn't import the URP package available in the asset root folder (SEE DOCUMENTATION)" ,
MessageType . Error ,
true ) ;
}
private void NormalMapCreator ( )
{
GUILayout . Label ( "Normal Map Creator" , bigLabel ) ;
GUILayout . Space ( 20 ) ;
GUILayout . Label ( "Select the folder where new Normal Maps will be saved when the Create Normal Map button of the asset component is pressed (URP only)" , EditorStyles . boldLabel ) ;
HandleSaveFolderEditorPref ( "All1ShaderNormals" , basePath + normalMapSavesRelativePath , "Normal Maps" ) ;
GUILayout . Space ( 20 ) ;
GUILayout . Label ( "Assign a sprite you want to create a normal map from. Choose the normal map settings and press the 'Create And Save Normal Map' button" , EditorStyles . boldLabel ) ;
targetNormalImage = ( Texture2D ) EditorGUILayout . ObjectField ( "Target Image" , targetNormalImage , typeof ( Texture2D ) , false , GUILayout . MaxWidth ( 225 ) ) ;
EditorGUILayout . BeginHorizontal ( ) ;
{
GUILayout . Label ( "Normal Strength:" , GUILayout . MaxWidth ( 150 ) ) ;
normalStrength = EditorGUILayout . Slider ( normalStrength , 1f , 20f , GUILayout . MaxWidth ( 400 ) ) ;
}
EditorGUILayout . EndHorizontal ( ) ;
EditorGUILayout . BeginHorizontal ( ) ;
{
GUILayout . Label ( "Normal Smoothing:" , GUILayout . MaxWidth ( 150 ) ) ;
normalSmoothing = EditorGUILayout . IntSlider ( normalSmoothing , 0 , 3 , GUILayout . MaxWidth ( 400 ) ) ;
}
EditorGUILayout . EndHorizontal ( ) ;
if ( isComputingNormals = = 0 )
{
if ( targetNormalImage ! = null )
{
if ( GUILayout . Button ( "Create And Save Normal Map" ) )
{
isComputingNormals = 1 ;
return ;
}
}
else
{
GUILayout . Label ( "Add a Target Image to use this feature" , EditorStyles . boldLabel ) ;
}
}
else
{
GUILayout . Label ( "Normal Map is currently being created, be patient" , EditorStyles . boldLabel , GUILayout . Height ( 40 ) ) ;
Repaint ( ) ;
isComputingNormals + + ;
if ( isComputingNormals > 5 )
{
string assetPath = AssetDatabase . GetAssetPath ( targetNormalImage ) ;
var tImporter = AssetImporter . GetAtPath ( assetPath ) as TextureImporter ;
if ( tImporter ! = null )
{
tImporter . isReadable = true ;
tImporter . SaveAndReimport ( ) ;
}
Texture2D normalToSave = CreateNormalMap ( targetNormalImage , normalStrength , normalSmoothing ) ;
string prefSavedPath = PlayerPrefs . GetString ( "All1ShaderNormals" ) + "/" ;
string path = prefSavedPath + "NormalMap.png" ;
if ( System . IO . File . Exists ( path ) ) path = GetNewValidPath ( path ) ;
string texName = path . Replace ( prefSavedPath , "" ) ;
path = EditorUtility . SaveFilePanel ( "Save texture as PNG" , prefSavedPath , texName , "png" ) ;
//If you are reading this you might have encountered an error in Unity 2022 Mac builds, if that's the case comment the line above and uncomment the line below
//path = prefSavedPath + texName + ".png";
if ( path . Length ! = 0 )
{
byte [ ] pngData = normalToSave . EncodeToPNG ( ) ;
if ( pngData ! = null ) File . WriteAllBytes ( path , pngData ) ;
AssetDatabase . Refresh ( ) ;
if ( path . IndexOf ( "Assets/" ) > = 0 )
{
string subPath = path . Substring ( path . IndexOf ( "Assets/" ) ) ;
TextureImporter importer = AssetImporter . GetAtPath ( subPath ) as TextureImporter ;
if ( importer ! = null )
{
Debug . Log ( "Normal Map saved inside the project: " + subPath ) ;
importer . filterMode = FilterMode . Bilinear ;
importer . textureType = TextureImporterType . NormalMap ;
importer . wrapMode = TextureWrapMode . Repeat ;
importer . SaveAndReimport ( ) ;
EditorGUIUtility . PingObject ( AssetDatabase . LoadAssetAtPath ( subPath , typeof ( Texture ) ) ) ;
}
}
else Debug . Log ( "Normal Map saved outside the project: " + path ) ;
}
isComputingNormals = 0 ;
}
}
GUILayout . Label ( "*This process will freeze the editor for some seconds, larger images will take longer" , EditorStyles . boldLabel ) ;
}
private void HandleSaveFolderEditorPref ( string keyName , string defaultPath , string logsFeatureName )
{
if ( ! PlayerPrefs . HasKey ( keyName ) ) PlayerPrefs . SetString ( keyName , defaultPath ) ;
materialTargetFolder = ( DefaultAsset ) AssetDatabase . LoadAssetAtPath ( PlayerPrefs . GetString ( keyName ) , typeof ( DefaultAsset ) ) ;
if ( materialTargetFolder = = null )
{
PlayerPrefs . SetString ( keyName , defaultPath ) ;
materialTargetFolder = ( DefaultAsset ) AssetDatabase . LoadAssetAtPath ( PlayerPrefs . GetString ( keyName ) , typeof ( DefaultAsset ) ) ;
if ( materialTargetFolder = = null )
{
materialTargetFolder = ( DefaultAsset ) AssetDatabase . LoadAssetAtPath ( "Assets/" , typeof ( DefaultAsset ) ) ;
if ( materialTargetFolder = = null )
{
EditorGUILayout . BeginHorizontal ( GUILayout . MaxWidth ( 600 ) ) ;
EditorGUILayout . HelpBox ( "Folder is invalid, please select a valid one" , MessageType . Error , true ) ;
EditorGUILayout . EndHorizontal ( ) ;
}
else PlayerPrefs . SetString ( "Assets/" , defaultPath ) ;
}
}
materialTargetFolder = ( DefaultAsset ) EditorGUILayout . ObjectField ( "New " + logsFeatureName + " Folder" ,
materialTargetFolder , typeof ( DefaultAsset ) , false , GUILayout . MaxWidth ( 500 ) ) ;
if ( materialTargetFolder ! = null & & IsAssetAFolder ( materialTargetFolder ) )
{
string path = AssetDatabase . GetAssetPath ( materialTargetFolder ) ;
PlayerPrefs . SetString ( keyName , path ) ;
EditorGUILayout . BeginHorizontal ( GUILayout . MaxWidth ( 600 ) ) ;
EditorGUILayout . HelpBox ( "Valid folder! " + logsFeatureName + " save path: " + path , MessageType . Info ) ;
EditorGUILayout . EndHorizontal ( ) ;
}
else
{
EditorGUILayout . BeginHorizontal ( GUILayout . MaxWidth ( 600 ) ) ;
EditorGUILayout . HelpBox ( "Select the new " + logsFeatureName + " Folder" , MessageType . Warning , true ) ;
EditorGUILayout . EndHorizontal ( ) ;
}
}
private void GradientCreator ( )
{
GUILayout . Label ( "Gradient Creator" , bigLabel ) ;
GUILayout . Space ( 20 ) ;
GUILayout . Label ( "This feature can be used to create textures for the Color Ramp Effect" , EditorStyles . boldLabel ) ;
EditorGUILayout . GradientField ( "Gradient" , gradient , GUILayout . Height ( 25 ) , GUILayout . MaxWidth ( 500 ) ) ;
EditorGUILayout . BeginHorizontal ( ) ;
{
GUILayout . Label ( "Texture Size:" , GUILayout . MaxWidth ( 145 ) ) ;
textureSizes = ( TextureSizes ) EditorGUILayout . EnumPopup ( textureSizes , GUILayout . MaxWidth ( 200 ) ) ;
}
EditorGUILayout . EndHorizontal ( ) ;
int textureSize = ( int ) textureSizes ;
Texture2D gradTex = new Texture2D ( textureSize , 1 , TextureFormat . RGBA32 , false ) ;
for ( int i = 0 ; i < textureSize ; i + + ) gradTex . SetPixel ( i , 0 , gradient . Evaluate ( ( float ) i / ( float ) textureSize ) ) ;
gradTex . Apply ( ) ;
GUILayout . Space ( 20 ) ;
GUILayout . Label ( "Select the folder where new Gradient Textures will be saved" , EditorStyles . boldLabel ) ;
HandleSaveFolderEditorPref ( "All1ShaderGradients" , basePath + gradientSavesRelativePath , "Gradient" ) ;
string prefSavedPath = PlayerPrefs . GetString ( "All1ShaderGradients" ) + "/" ;
if ( Directory . Exists ( prefSavedPath ) )
{
EditorGUILayout . BeginHorizontal ( ) ;
{
GUILayout . Label ( "Gradient Texture Filtering: " , GUILayout . MaxWidth ( 170 ) ) ;
gradientFiltering = ( FilterMode ) EditorGUILayout . EnumPopup ( gradientFiltering , GUILayout . MaxWidth ( 200 ) ) ;
}
EditorGUILayout . EndHorizontal ( ) ;
if ( GUILayout . Button ( "Save Gradient Texture" , GUILayout . MaxWidth ( 500 ) ) )
{
string path = prefSavedPath + "ColorGradient.png" ;
if ( System . IO . File . Exists ( path ) ) path = GetNewValidPath ( path ) ;
string texName = path . Replace ( prefSavedPath , "" ) ;
path = EditorUtility . SaveFilePanel ( "Save texture as PNG" , prefSavedPath , texName , "png" ) ;
if ( path . Length ! = 0 )
{
byte [ ] pngData = gradTex . EncodeToPNG ( ) ;
if ( pngData ! = null ) File . WriteAllBytes ( path , pngData ) ;
AssetDatabase . Refresh ( ) ;
if ( path . IndexOf ( "Assets/" ) > = 0 )
{
string subPath = path . Substring ( path . IndexOf ( "Assets/" ) ) ;
TextureImporter importer = AssetImporter . GetAtPath ( subPath ) as TextureImporter ;
if ( importer ! = null )
{
Debug . Log ( "Gradient saved inside the project: " + subPath ) ;
importer . filterMode = gradientFiltering ;
importer . SaveAndReimport ( ) ;
EditorGUIUtility . PingObject ( AssetDatabase . LoadAssetAtPath ( subPath , typeof ( Texture ) ) ) ;
}
}
else Debug . Log ( "Gradient saved outside the project: " + path ) ;
}
}
}
}
private static bool IsAssetAFolder ( Object obj )
{
string path = "" ;
if ( obj = = null ) return false ;
path = AssetDatabase . GetAssetPath ( obj . GetInstanceID ( ) ) ;
if ( path . Length > 0 )
{
if ( Directory . Exists ( path ) ) return true ;
else return false ;
}
return false ;
}
private static string GetNewValidPath ( string path , string extension = ".png" , int i = 1 )
{
int number = i ;
path = path . Replace ( extension , "" ) ;
string newPath = path + "_" + number . ToString ( ) ;
string fullPath = newPath + extension ;
if ( File . Exists ( fullPath ) )
{
number + + ;
fullPath = GetNewValidPath ( path , extension , number ) ;
}
return fullPath ;
}
private void DrawLine ( Color color , int thickness = 2 , int padding = 10 )
{
Rect r = EditorGUILayout . GetControlRect ( GUILayout . Height ( padding + thickness ) ) ;
r . height = thickness ;
r . y + = ( padding / 2 ) ;
r . x - = 2 ;
r . width + = 6 ;
EditorGUI . DrawRect ( r , color ) ;
}
public static Texture2D CreateNormalMap ( Texture2D t , float normalMult = 5f , int normalSmooth = 0 )
{
int width = t . width ;
int height = t . height ;
Color [ ] sourcePixels = t . GetPixels ( ) ;
Color [ ] resultPixels = new Color [ width * height ] ;
Vector3 vScale = new Vector3 ( 0.3333f , 0.3333f , 0.3333f ) ;
for ( int y = 0 ; y < height ; y + + )
{
for ( int x = 0 ; x < width ; x + + )
{
int index = x + y * width ;
Vector3 cSampleNegXNegY = GetPixelClamped ( sourcePixels , x - 1 , y - 1 , width , height ) ;
Vector3 cSampleZerXNegY = GetPixelClamped ( sourcePixels , x , y - 1 , width , height ) ;
Vector3 cSamplePosXNegY = GetPixelClamped ( sourcePixels , x + 1 , y - 1 , width , height ) ;
Vector3 cSampleNegXZerY = GetPixelClamped ( sourcePixels , x - 1 , y , width , height ) ;
Vector3 cSamplePosXZerY = GetPixelClamped ( sourcePixels , x + 1 , y , width , height ) ;
Vector3 cSampleNegXPosY = GetPixelClamped ( sourcePixels , x - 1 , y + 1 , width , height ) ;
Vector3 cSampleZerXPosY = GetPixelClamped ( sourcePixels , x , y + 1 , width , height ) ;
Vector3 cSamplePosXPosY = GetPixelClamped ( sourcePixels , x + 1 , y + 1 , width , height ) ;
float fSampleNegXNegY = Vector3 . Dot ( cSampleNegXNegY , vScale ) ;
float fSampleZerXNegY = Vector3 . Dot ( cSampleZerXNegY , vScale ) ;
float fSamplePosXNegY = Vector3 . Dot ( cSamplePosXNegY , vScale ) ;
float fSampleNegXZerY = Vector3 . Dot ( cSampleNegXZerY , vScale ) ;
float fSamplePosXZerY = Vector3 . Dot ( cSamplePosXZerY , vScale ) ;
float fSampleNegXPosY = Vector3 . Dot ( cSampleNegXPosY , vScale ) ;
float fSampleZerXPosY = Vector3 . Dot ( cSampleZerXPosY , vScale ) ;
float fSamplePosXPosY = Vector3 . Dot ( cSamplePosXPosY , vScale ) ;
float edgeX = ( fSampleNegXNegY - fSamplePosXNegY ) * 0.25f + ( fSampleNegXZerY - fSamplePosXZerY ) * 0.5f + ( fSampleNegXPosY - fSamplePosXPosY ) * 0.25f ;
float edgeY = ( fSampleNegXNegY - fSampleNegXPosY ) * 0.25f + ( fSampleZerXNegY - fSampleZerXPosY ) * 0.5f + ( fSamplePosXNegY - fSamplePosXPosY ) * 0.25f ;
Vector2 vEdge = new Vector2 ( edgeX , edgeY ) * normalMult ;
Vector3 norm = new Vector3 ( vEdge . x , vEdge . y , 1.0f ) . normalized ;
resultPixels [ index ] = new Color ( norm . x * 0.5f + 0.5f , norm . y * 0.5f + 0.5f , norm . z * 0.5f + 0.5f , 1 ) ;
}
}
if ( normalSmooth > 0 )
{
resultPixels = SmoothNormals ( resultPixels , width , height , normalSmooth ) ;
}
Texture2D texNormal = new Texture2D ( width , height , TextureFormat . RGB24 , false , false ) ;
texNormal . SetPixels ( resultPixels ) ;
texNormal . Apply ( ) ;
return texNormal ;
}
private static Vector3 GetPixelClamped ( Color [ ] pixels , int x , int y , int width , int height )
{
x = Mathf . Clamp ( x , 0 , width - 1 ) ;
y = Mathf . Clamp ( y , 0 , height - 1 ) ;
Color c = pixels [ x + y * width ] ;
return new Vector3 ( c . r , c . g , c . b ) ;
}
private static Color [ ] SmoothNormals ( Color [ ] pixels , int width , int height , int normalSmooth )
{
Color [ ] smoothedPixels = new Color [ pixels . Length ] ;
float step = 0.00390625f * normalSmooth ;
for ( int y = 0 ; y < height ; y + + )
{
for ( int x = 0 ; x < width ; x + + )
{
float pixelsToAverage = 0.0f ;
Color c = pixels [ x + y * width ] ;
pixelsToAverage + + ;
for ( int offsetY = - normalSmooth ; offsetY < = normalSmooth ; offsetY + + )
{
for ( int offsetX = - normalSmooth ; offsetX < = normalSmooth ; offsetX + + )
{
if ( offsetX = = 0 & & offsetY = = 0 ) continue ;
int sampleX = Mathf . Clamp ( x + offsetX , 0 , width - 1 ) ;
int sampleY = Mathf . Clamp ( y + offsetY , 0 , height - 1 ) ;
c + = pixels [ sampleX + sampleY * width ] ;
pixelsToAverage + + ;
}
}
smoothedPixels [ x + y * width ] = c / pixelsToAverage ;
}
}
return smoothedPixels ;
}
[MenuItem("Assets/Create/AllIn1Shader Materials/CreateDefaultMaterial")]
public static void CreateDefaultMaterial ( )
{
CreateMaterial ( "AllIn1SpriteShader" ) ;
}
[MenuItem("Assets/Create/AllIn1Shader Materials/CreateScaledTimeMaterial")]
public static void CreateScaledTimeMaterial ( )
{
CreateMaterial ( "AllIn1SpriteShaderScaledTime" ) ;
}
[MenuItem("Assets/Create/AllIn1Shader Materials/CreateUiMaskMaterial")]
public static void CreateUiMaskMaterial ( )
{
CreateMaterial ( "AllIn1SpriteShaderUiMask" ) ;
}
private static void CreateMaterial ( string shaderName )
{
string selectedPath = AssetDatabase . GetAssetPath ( Selection . activeObject ) ;
if ( ! string . IsNullOrEmpty ( selectedPath ) & & Directory . Exists ( selectedPath ) )
{
Material material = new Material ( FindShader ( shaderName ) ) ;
string fullPath = selectedPath + "/Mat-" + shaderName + ".mat" ;
if ( File . Exists ( fullPath ) ) fullPath = GetNewValidPath ( fullPath , ".mat" ) ;
AssetDatabase . CreateAsset ( material , fullPath ) ;
AssetDatabase . Refresh ( ) ;
}
else
{
Debug . LogWarning ( "Please select a valid folder in the Project Window." ) ;
}
}
private void OnEnable ( ) = > GetBasePath ( ) ;
private static void GetBasePath ( )
{
string [ ] guids = AssetDatabase . FindAssets ( "t:folder AllIn1SpriteShader" ) ;
if ( guids . Length > 0 )
{
basePath = AssetDatabase . GUIDToAssetPath ( guids [ 0 ] ) ;
}
else
{
Debug . LogError ( "AllIn1SpriteShader folder not found in the project." ) ;
basePath = "Assets/Plugins/AllIn1SpriteShader" ;
}
}
public static string GetMaterialSavePath ( )
{
if ( ! PlayerPrefs . HasKey ( "All1ShaderMaterials" ) )
{
GetBasePath ( ) ;
return basePath + materialsSavesRelativePath ;
}
return PlayerPrefs . GetString ( "All1ShaderMaterials" ) ;
}
public static string GetRenderImageSavePath ( )
{
if ( ! PlayerPrefs . HasKey ( "All1ShaderRenderImages" ) )
{
GetBasePath ( ) ;
return basePath + renderImagesSavesRelativePath ;
}
return PlayerPrefs . GetString ( "All1ShaderRenderImages" ) ;
}
public static string GetNormalMapSavePath ( )
{
if ( ! PlayerPrefs . HasKey ( "All1ShaderNormals" ) )
{
GetBasePath ( ) ;
return basePath + normalMapSavesRelativePath ;
}
return PlayerPrefs . GetString ( "All1ShaderNormals" ) ;
}
private void SceneNotificationsToggle ( )
{
float previousLabelWidth = EditorGUIUtility . labelWidth ;
EditorGUIUtility . labelWidth = 200f ;
bool areNotificationsEnabled = EditorPrefs . GetInt ( "DisplaySceneViewNotifications" , 1 ) = = 1 ;
areNotificationsEnabled = EditorGUILayout . Toggle ( "Display Scene View Notifications" , areNotificationsEnabled ) ;
EditorPrefs . SetInt ( "DisplaySceneViewNotifications" , areNotificationsEnabled ? 1 : 0 ) ;
EditorGUIUtility . labelWidth = previousLabelWidth ;
}
private static void RefreshLitShader ( )
{
GUILayout . Label ( "Force the Lit Shader to be reconfigured" ) ;
GUILayout . Label ( "If you are getting some error or have changed the render pipeline press the button below" ) ;
if ( GUILayout . Button ( "Refresh Lit Shader" , GUILayout . MaxWidth ( 500f ) ) )
{
AllIn1ShaderImporter . ForceReimport ( ) ;
}
}
public static void SceneViewNotificationAndLog ( string message )
{
Debug . Log ( message ) ;
ShowSceneViewNotification ( message ) ;
}
public static void ShowSceneViewNotification ( string message )
{
bool showNotification = EditorPrefs . GetInt ( "DisplaySceneViewNotifications" , 1 ) = = 1 ;
if ( ! showNotification ) return ;
GUIContent content = new GUIContent ( message ) ;
#if UNITY_2019_1_OR_NEWER
SceneView . lastActiveSceneView . ShowNotification ( content , 1.5f ) ;
#else
SceneView . lastActiveSceneView . ShowNotification ( content ) ;
#endif
}
public static Shader FindShader ( string shaderName )
{
string [ ] guids = AssetDatabase . FindAssets ( $"{shaderName} t:shader" ) ;
foreach ( string guid in guids )
{
string path = AssetDatabase . GUIDToAssetPath ( guid ) ;
Shader shader = AssetDatabase . LoadAssetAtPath < Shader > ( path ) ;
if ( shader ! = null )
{
string fullShaderName = shader . name ;
string actualShaderName = fullShaderName . Substring ( fullShaderName . LastIndexOf ( '/' ) + 1 ) ;
if ( actualShaderName . Equals ( shaderName ) ) return shader ;
}
}
return null ;
}
}
}
#endif