597 lines
25 KiB
C#
597 lines
25 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Text.RegularExpressions;
|
|
using System.Threading.Tasks;
|
|
using UnityEngine;
|
|
using TMPro;
|
|
using UnityEditor;
|
|
using Object = UnityEngine.Object;
|
|
|
|
namespace DreadScripts.TextToTexture
|
|
{
|
|
public class TextToTexture : EditorWindow
|
|
{
|
|
#region Constants
|
|
|
|
private const string POIYOMI_SHADER_NAME = ".poiyomi/• Poiyomi Toon •";
|
|
private const string FALLBACK_SHADER_NAME = "Standard";
|
|
|
|
private const string DUMMY_PARENT_NAME = "(Temp) TTT_Objects";
|
|
|
|
private const string EDITORPREFS_SAVEPATH = "Text2TextureSavePath";
|
|
private const string EDITORPREFS_DEFAULTSAVEPATH = "Assets/DreadScripts/TextToTexture/Generated Assets";
|
|
|
|
private const string RESOURCE_FONTPATH = "Assets/DreadScripts/TextToTexture/Resources/TTT_DancingScript TMP.asset";
|
|
private const string RESOURCE_FONTGUID = "e7d6a5821a387564caacc9929e10eb22";
|
|
|
|
private const string RESOURCE_TEMPLATEPATH = "Assets/DreadScripts/TextToTexture/Resources/TTT_CanvasTemplate.prefab";
|
|
private const string RESOURCE_TEMPLATEGUID = "2cd48bc473a380748ad104409753555e";
|
|
|
|
private readonly string[] DimensionPresets =
|
|
{
|
|
"128x128",
|
|
"256x256",
|
|
"512x512",
|
|
"1024x1024",
|
|
"2048x2048",
|
|
"4096x4096",
|
|
};
|
|
|
|
#endregion
|
|
|
|
#region Automated Variables
|
|
|
|
public static string savePath;
|
|
|
|
private static GUIContent resetIcon;
|
|
private static bool showExtra;
|
|
private static bool isInCustomizing;
|
|
|
|
private static Camera tempCamera;
|
|
private static TextMeshProUGUI tempText;
|
|
private static GameObject tempParent;
|
|
private static Material tempMaterial;
|
|
private static RenderTexture tempRenderTexture;
|
|
|
|
#endregion
|
|
|
|
#region Input Variables
|
|
public static string textInput = "";
|
|
public static TextureGenerationType generationType = TextureGenerationType.GenerateMaterial;
|
|
|
|
public static TMP_FontAsset customFont;
|
|
public static float outlineThickness = 0.075f;
|
|
public static float extraPadding = 5;
|
|
public static Vector2 offset;
|
|
public static int resolutionWidth = 1024;
|
|
public static int resolutionHeight = 1024;
|
|
|
|
public static float verticalMargin = 100;
|
|
public static float horizontalMargin = 100;
|
|
|
|
public static bool invert;
|
|
public static bool wrapText = true;
|
|
#endregion
|
|
|
|
#region Declarations
|
|
public enum TextureGenerationType
|
|
{
|
|
GenerateNormalMap,
|
|
GenerateMask,
|
|
GenerateCustomTexture,
|
|
GenerateMaterial
|
|
}
|
|
#endregion
|
|
|
|
[MenuItem("DreadTools/Utility/Text2Texture")]
|
|
public static void showWindow()
|
|
{
|
|
var title = GetWindow<TextToTexture>(false, "Text2Texture", true).titleContent;
|
|
title.image = EditorGUIUtility.IconContent("GUIText Icon").image;
|
|
}
|
|
|
|
private void OnGUI()
|
|
{
|
|
EditorGUI.BeginDisabledGroup(isInCustomizing);
|
|
|
|
GUIStyle iconStyle = new GUIStyle() {margin = new RectOffset(0, 0, 1, 1)};
|
|
|
|
using (new GUILayout.VerticalScope("helpbox"))
|
|
{
|
|
using (new GUILayout.HorizontalScope())
|
|
{
|
|
GUILayout.FlexibleSpace();
|
|
GUILayout.Label("Text Input", "boldlabel");
|
|
GUILayout.FlexibleSpace();
|
|
}
|
|
textInput = EditorGUILayout.TextArea(textInput);
|
|
generationType = (TextureGenerationType)EditorGUILayout.EnumPopup(generationType);
|
|
}
|
|
|
|
using (new GUILayout.VerticalScope("box"))
|
|
{
|
|
showExtra = EditorGUILayout.Foldout(showExtra, "Extra Settings");
|
|
|
|
if (showExtra)
|
|
{
|
|
|
|
using (new GUILayout.HorizontalScope("helpbox"))
|
|
customFont = (TMP_FontAsset) EditorGUILayout.ObjectField("Custom Font", customFont, typeof(TMP_FontAsset), false);
|
|
|
|
using (new GUILayout.HorizontalScope("helpbox"))
|
|
using (new EditorGUI.DisabledScope(generationType != TextureGenerationType.GenerateNormalMap && generationType != TextureGenerationType.GenerateMaterial))
|
|
outlineThickness = Mathf.Clamp01(EditorGUILayout.FloatField("Normal Thickness", outlineThickness));
|
|
|
|
using (new GUILayout.HorizontalScope("helpbox"))
|
|
extraPadding = EditorGUILayout.FloatField("Padding", extraPadding);
|
|
|
|
using (new GUILayout.HorizontalScope("helpbox"))
|
|
{
|
|
GUILayout.Label("Offset", GUILayout.Width(136));
|
|
offset = EditorGUILayout.Vector2Field(GUIContent.none, offset);
|
|
}
|
|
|
|
using (new GUILayout.HorizontalScope("helpbox"))
|
|
{
|
|
GUILayout.Label("Margin (%)", GUILayout.Width(136));
|
|
|
|
EditorGUIUtility.labelWidth = 10;
|
|
horizontalMargin = EditorGUILayout.FloatField(new GUIContent("X", "Width"), horizontalMargin);
|
|
verticalMargin = EditorGUILayout.FloatField(new GUIContent("Y", "Height"), verticalMargin);
|
|
EditorGUIUtility.labelWidth = 0;
|
|
}
|
|
|
|
using (new GUILayout.HorizontalScope("helpbox"))
|
|
{
|
|
GUILayout.Label("Resolution", GUILayout.Width(136));
|
|
|
|
EditorGUIUtility.labelWidth = 0;
|
|
|
|
EditorGUIUtility.labelWidth = 10;
|
|
resolutionWidth = EditorGUILayout.IntField(new GUIContent("X", "Width"), resolutionWidth);
|
|
resolutionHeight = EditorGUILayout.IntField(new GUIContent("Y", "Height"), resolutionHeight);
|
|
EditorGUIUtility.labelWidth = 0;
|
|
|
|
|
|
int dummy = -1;
|
|
EditorGUI.BeginChangeCheck();
|
|
dummy = EditorGUILayout.Popup(dummy, DimensionPresets, GUILayout.Width(18));
|
|
if (EditorGUI.EndChangeCheck())
|
|
{
|
|
string[] dimensions = ((string) DimensionPresets.GetValue(dummy)).Split('x');
|
|
resolutionWidth = int.Parse(dimensions[0]);
|
|
resolutionHeight = int.Parse(dimensions[1]);
|
|
}
|
|
|
|
if (GUILayout.Button(resetIcon, iconStyle, GUILayout.Height(18), GUILayout.Width(18)))
|
|
resolutionWidth = resolutionHeight = 1024;
|
|
}
|
|
|
|
using (new GUILayout.HorizontalScope("helpbox"))
|
|
{
|
|
wrapText = EditorGUILayout.Toggle("Wrap Text", wrapText);
|
|
|
|
using (new EditorGUI.DisabledScope((int)generationType > 1))
|
|
invert = EditorGUILayout.Toggle(new GUIContent("Invert Map"), invert);
|
|
}
|
|
}
|
|
}
|
|
|
|
EditorGUI.EndDisabledGroup();
|
|
|
|
if (!isInCustomizing)
|
|
{
|
|
using (new EditorGUI.DisabledScope(string.IsNullOrWhiteSpace(textInput)))
|
|
using (new GUILayout.HorizontalScope())
|
|
{
|
|
if (GUILayout.Button("Generate"))
|
|
{
|
|
switch (generationType)
|
|
{
|
|
case TextureGenerationType.GenerateNormalMap:
|
|
case TextureGenerationType.GenerateMask:
|
|
GenerateInit();
|
|
break;
|
|
case TextureGenerationType.GenerateCustomTexture:
|
|
isInCustomizing = true;
|
|
GenerateInit();
|
|
break;
|
|
case TextureGenerationType.GenerateMaterial:
|
|
|
|
generationType = TextureGenerationType.GenerateNormalMap;
|
|
Texture2D normalTexture = GenerateInit();
|
|
|
|
generationType = TextureGenerationType.GenerateMask;
|
|
bool oldInvert = invert;
|
|
invert = true;
|
|
Texture2D maskTexture = GenerateInit();
|
|
invert = oldInvert;
|
|
|
|
generationType = TextureGenerationType.GenerateMaterial;
|
|
|
|
Shader currentShader = Shader.Find(POIYOMI_SHADER_NAME) ?? Shader.Find(FALLBACK_SHADER_NAME);
|
|
Material newMaterial = new Material(currentShader);
|
|
#region Standard/Generic Property Set
|
|
newMaterial.SetTexture("_MainTex", maskTexture);
|
|
newMaterial.SetTexture("_MetallicGlossMap", maskTexture);
|
|
newMaterial.SetTexture("_BumpMap", normalTexture);
|
|
newMaterial.SetFloat("_Glossiness", 0.85f);
|
|
newMaterial.SetFloat("_GlossMapScale", 0.85f);
|
|
#endregion
|
|
|
|
#region Poiyomi Propert Set
|
|
newMaterial.EnableKeyword("VIGNETTE_CLASSIC");
|
|
newMaterial.SetTexture("_BRDFSpecularMap", maskTexture);
|
|
newMaterial.SetTexture("_BRDFMetallicMap", maskTexture);
|
|
newMaterial.SetFloat("_LightingMode", 1);
|
|
newMaterial.SetFloat("_LightingStandardSmoothness", 0.85f);
|
|
newMaterial.SetFloat("_EnableBRDF", 1);
|
|
newMaterial.SetFloat("_BRDFMetallic", 1);
|
|
newMaterial.SetFloat("_BRDFGlossiness", 0.85f);
|
|
#endregion
|
|
string newMatName = Regex.Replace(textInput, "[^\\w\\._ ]", "");
|
|
if (newMatName.Length > 30) newMatName = "Generated TextMaterial";
|
|
string newMatPath = AssetDatabase.GenerateUniqueAssetPath($"{savePath}/{newMatName}.mat");
|
|
AssetDatabase.CreateAsset(newMaterial, newMatPath);
|
|
EditorGUIUtility.PingObject(newMaterial);
|
|
break;
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!tempCamera) isInCustomizing = false;
|
|
if (GUILayout.Button("Save Texture"))
|
|
GenerateTexture();
|
|
}
|
|
|
|
|
|
DrawSeparator();
|
|
savePath = AssetFolderPath(savePath, "New Textures Path", EDITORPREFS_SAVEPATH, false);
|
|
Credit();
|
|
}
|
|
|
|
private Texture2D GenerateInit()
|
|
{
|
|
GameObject canvasTemplate = ReadyResource<GameObject>(RESOURCE_TEMPLATEPATH, RESOURCE_TEMPLATEGUID);
|
|
customFont = customFont ?? ReadyResource<TMP_FontAsset>(RESOURCE_FONTPATH, RESOURCE_FONTGUID);
|
|
|
|
tempRenderTexture = new RenderTexture(resolutionWidth, resolutionHeight, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.sRGB);
|
|
|
|
float resolutionRatio = (float) resolutionWidth / resolutionHeight;
|
|
|
|
tempParent = GameObject.Find(DUMMY_PARENT_NAME);
|
|
if (tempParent) DestroyImmediate(tempParent);
|
|
tempParent = new GameObject(DUMMY_PARENT_NAME)
|
|
{
|
|
hideFlags = HideFlags.DontSaveInEditor | HideFlags.DontSaveInBuild,
|
|
transform =
|
|
{
|
|
position = new Vector3(420, 666, 69)
|
|
}
|
|
};
|
|
|
|
GameObject canvas = Instantiate(canvasTemplate, tempParent.transform);
|
|
if (generationType == TextureGenerationType.GenerateCustomTexture) EditorGUIUtility.PingObject(canvas.GetInstanceID());
|
|
|
|
tempCamera = canvas.GetComponentInChildren<Camera>();
|
|
tempText = canvas.GetComponentInChildren<TextMeshProUGUI>();
|
|
RectTransform textRect = tempText.GetComponent<RectTransform>();
|
|
|
|
tempCamera.transform.Translate(-offset);
|
|
tempCamera.orthographicSize = 80 + extraPadding * 2;
|
|
|
|
tempText.enableWordWrapping = wrapText;
|
|
tempText.font = customFont;
|
|
tempText.text = textInput;
|
|
|
|
switch (generationType)
|
|
{
|
|
case TextureGenerationType.GenerateNormalMap:
|
|
CreateTemporaryMaterial(tempText.fontSharedMaterial, true, true);
|
|
break;
|
|
case TextureGenerationType.GenerateMask:
|
|
CreateTemporaryMaterial(tempText.fontSharedMaterial, true, false);
|
|
break;
|
|
case TextureGenerationType.GenerateCustomTexture:
|
|
CreateTemporaryMaterial(tempText.fontSharedMaterial, false, false);
|
|
break;
|
|
}
|
|
|
|
|
|
textRect.sizeDelta = new Vector2(160 * resolutionRatio * (horizontalMargin/100), 160 * (verticalMargin / 100));
|
|
|
|
|
|
return isInCustomizing ? null : GenerateTexture();
|
|
}
|
|
|
|
private Texture2D GenerateTexture()
|
|
{
|
|
isInCustomizing = false;
|
|
tempCamera.targetTexture = tempRenderTexture;
|
|
RenderTexture.active = tempRenderTexture;
|
|
|
|
ReadyPath(savePath);
|
|
byte[] textureBytes = null;
|
|
|
|
switch (generationType)
|
|
{
|
|
case TextureGenerationType.GenerateNormalMap:
|
|
{
|
|
|
|
tempMaterial.SetFloat("_LightAngle", 0);
|
|
Texture2D bottomTexture = CaptureRender();
|
|
|
|
tempMaterial.SetFloat("_LightAngle", 6.28f / 4);
|
|
Texture2D rightTexture = CaptureRender();
|
|
|
|
tempMaterial.SetFloat("_LightAngle", 6.28f / 4 * 2);
|
|
Texture2D topTexture = CaptureRender();
|
|
|
|
tempMaterial.SetFloat("_LightAngle", 6.28f / 4 * 3);
|
|
Texture2D leftTexture = CaptureRender();
|
|
|
|
|
|
Color[] bottomPixels = bottomTexture.GetPixels();
|
|
Color[] rightPixels = rightTexture.GetPixels();
|
|
Color[] topPixels = topTexture.GetPixels();
|
|
Color[] leftPixels = leftTexture.GetPixels();
|
|
|
|
Color[] newColors = new Color[resolutionHeight * resolutionWidth];
|
|
|
|
Parallel.For(0, resolutionHeight, i =>
|
|
{
|
|
Parallel.For(0, resolutionWidth, j =>
|
|
{
|
|
int currentIndex = i * resolutionWidth + j;
|
|
float horizontalInfluence = 0.5f + leftPixels[currentIndex].r / 2 - rightPixels[currentIndex].r / 2;
|
|
float verticalInfluence = 0.5f + bottomPixels[currentIndex].r / 2 - topPixels[currentIndex].r / 2;
|
|
float blueColor = 1 - ((Mathf.Abs(horizontalInfluence - 0.5f) + Mathf.Abs(verticalInfluence - 0.5f)) / 2);
|
|
newColors[currentIndex] = new Color(horizontalInfluence, verticalInfluence, blueColor);
|
|
});
|
|
});
|
|
|
|
DestroyImmediate(rightTexture);
|
|
DestroyImmediate(topTexture);
|
|
DestroyImmediate(leftTexture);
|
|
|
|
bottomTexture.SetPixels(newColors);
|
|
bottomTexture.Apply();
|
|
textureBytes = bottomTexture.EncodeToPNG();
|
|
DestroyImmediate(bottomTexture);
|
|
break;
|
|
}
|
|
case TextureGenerationType.GenerateMask:
|
|
{
|
|
CreateTemporaryMaterial(tempText.fontSharedMaterial, true, false);
|
|
|
|
tempCamera.backgroundColor = invert ? Color.white : Color.black;
|
|
Texture2D maskTexture = CaptureRender();
|
|
textureBytes = maskTexture.EncodeToPNG();
|
|
DestroyImmediate(maskTexture);
|
|
|
|
break;
|
|
}
|
|
case TextureGenerationType.GenerateCustomTexture:
|
|
{
|
|
Texture2D newTexture = CaptureRender();
|
|
textureBytes = newTexture.EncodeToPNG();
|
|
DestroyImmediate(newTexture);
|
|
break;
|
|
}
|
|
}
|
|
|
|
RenderTexture.active = null;
|
|
tempRenderTexture.Release();
|
|
|
|
Texture2D generatedTexture = SaveTexture(textureBytes);
|
|
EditorGUIUtility.PingObject(generatedTexture);
|
|
|
|
if (tempParent)
|
|
DestroyImmediate(tempParent);
|
|
|
|
return generatedTexture;
|
|
}
|
|
|
|
private static Texture2D SaveTexture(byte[] textureBytes)
|
|
{
|
|
AssetDatabase.DeleteAsset(AssetDatabase.GetAssetPath(tempMaterial));
|
|
string suffix;
|
|
switch (generationType)
|
|
{
|
|
case TextureGenerationType.GenerateNormalMap:
|
|
suffix = " Normal";
|
|
break;
|
|
case TextureGenerationType.GenerateMask:
|
|
suffix = " Mask";
|
|
break;
|
|
default:
|
|
suffix = string.Empty;
|
|
break;
|
|
}
|
|
string texturePath = AssetDatabase.GenerateUniqueAssetPath($"{savePath}/{Regex.Replace(textInput, "[^\\w\\._ ]", "")}{suffix}.png");
|
|
try
|
|
{
|
|
File.WriteAllBytes(texturePath, textureBytes);
|
|
}
|
|
catch
|
|
{
|
|
texturePath = AssetDatabase.GenerateUniqueAssetPath($"{savePath}/Generated TextTexture.png");
|
|
File.WriteAllBytes(texturePath, textureBytes);
|
|
}
|
|
|
|
AssetDatabase.ImportAsset(texturePath);
|
|
|
|
TextureImporter textureSettings = (TextureImporter)AssetImporter.GetAtPath(texturePath);
|
|
|
|
if (generationType == TextureGenerationType.GenerateNormalMap) textureSettings.textureType = TextureImporterType.NormalMap;
|
|
if (generationType == TextureGenerationType.GenerateMask) textureSettings.sRGBTexture = false;
|
|
|
|
textureSettings.maxTextureSize = 1024;
|
|
textureSettings.crunchedCompression = true;
|
|
textureSettings.compressionQuality = 100;
|
|
|
|
textureSettings.streamingMipmaps = true;
|
|
textureSettings.SaveAndReimport();
|
|
|
|
return (Texture2D)AssetDatabase.LoadMainAssetAtPath(texturePath);
|
|
}
|
|
|
|
private static Texture2D CaptureRender()
|
|
{
|
|
tempCamera.Render();
|
|
Texture2D capturedTexture = new Texture2D(resolutionWidth, resolutionHeight, TextureFormat.RGBA32, false);
|
|
capturedTexture.ReadPixels(new Rect(0, 0, resolutionWidth, resolutionHeight), 0, 0);
|
|
return capturedTexture;
|
|
}
|
|
|
|
private static void SetRequiredMaterialSettings(Material m, bool isNormal)
|
|
{
|
|
foreach (var key in m.shaderKeywords)
|
|
m.DisableKeyword(key);
|
|
|
|
if (isNormal)
|
|
{
|
|
m.EnableKeyword("BEVEL_ON");
|
|
m.SetFloat("_OutlineWidth", outlineThickness);
|
|
}
|
|
|
|
m.SetFloat("_ShaderFlags", 0);
|
|
m.SetFloat("_Bevel", isNormal ? invert ? -1 : 1 : 0);
|
|
m.SetFloat("_BevelOffset", 0);
|
|
m.SetFloat("_BevelClamp", 0);
|
|
m.SetFloat("_BevelRoundness", 0);
|
|
m.SetFloat("_BevelWidth", 0.5f);
|
|
|
|
m.SetFloat("_Ambient", 1);
|
|
m.SetFloat("_SpecularPower", 1);
|
|
m.SetFloat("_Reflectivity", 5);
|
|
m.SetFloat("_Diffuse", 0);
|
|
|
|
m.SetFloat("_BumpFace", 0);
|
|
m.SetFloat("_BumpOutline", 0);
|
|
|
|
m.SetColor("_FaceColor", isNormal ? Color.clear : invert ? Color.black : Color.white);
|
|
m.SetColor("_OutlineColor", isNormal ? Color.black : Color.clear);
|
|
m.SetColor("_ReflectFaceColor", Color.clear);
|
|
m.SetColor("_ReflectOutlineColor", Color.clear);
|
|
m.SetColor("_SpecularColor", new Color(1.498039f, 1.498039f, 1.498039f));
|
|
}
|
|
|
|
private static void CreateTemporaryMaterial(Material original, bool ForceSettings, bool isNormal)
|
|
{
|
|
ReadyPath($"{savePath}/Temp");
|
|
string path = AssetDatabase.GenerateUniqueAssetPath($"{savePath}/Temp/(Temp) {original.name}.mat");
|
|
tempMaterial = CopyAssetAndReturn(original, path);
|
|
if (ForceSettings) SetRequiredMaterialSettings(tempMaterial, isNormal);
|
|
tempText.fontSharedMaterial = tempMaterial;
|
|
}
|
|
|
|
private void OnEnable()
|
|
{
|
|
savePath = EditorPrefs.GetString(EDITORPREFS_SAVEPATH, EDITORPREFS_DEFAULTSAVEPATH);
|
|
resetIcon = new GUIContent(EditorGUIUtility.IconContent("d_Refresh")) {tooltip = "Reset Dimensions"};
|
|
}
|
|
|
|
#region DSHelper Methods
|
|
|
|
private static T ReadyResource<T>(string resourcePath, string resourceGUID = "", string msg = "") where T : Object
|
|
{
|
|
T asset = Resources.Load<T>(resourcePath);
|
|
if (asset) return asset;
|
|
|
|
if (!string.IsNullOrWhiteSpace(resourceGUID))
|
|
{
|
|
asset = AssetDatabase.LoadAssetAtPath<T>(AssetDatabase.GUIDToAssetPath(resourceGUID));
|
|
if (asset) return asset;
|
|
}
|
|
|
|
if (string.IsNullOrWhiteSpace(msg)) msg = $"Required Resources Asset at Resource Path {resourcePath} not found! Execution may not proceed.";
|
|
EditorUtility.DisplayDialog("Error", msg, "Heck");
|
|
throw new NullReferenceException(msg);
|
|
}
|
|
|
|
private static void ReadyPath(string path)
|
|
{
|
|
if (Directory.Exists(path)) return;
|
|
|
|
Directory.CreateDirectory(path);
|
|
AssetDatabase.ImportAsset(path);
|
|
}
|
|
|
|
private static T CopyAssetAndReturn<T>(T obj, string newPath) where T : Object
|
|
{
|
|
string assetPath = AssetDatabase.GetAssetPath(obj);
|
|
Object mainAsset = AssetDatabase.LoadMainAssetAtPath(assetPath);
|
|
|
|
if (!mainAsset) return null;
|
|
if (obj != mainAsset)
|
|
{
|
|
T newAsset = Object.Instantiate(obj);
|
|
AssetDatabase.CreateAsset(newAsset, newPath);
|
|
return newAsset;
|
|
}
|
|
|
|
AssetDatabase.CopyAsset(assetPath, newPath);
|
|
return AssetDatabase.LoadAssetAtPath<T>(newPath);
|
|
}
|
|
|
|
private static string AssetFolderPath(string variable, string title, string playerpref, bool isPlayerPrefs = true)
|
|
{
|
|
using (new GUILayout.HorizontalScope())
|
|
{
|
|
using (new EditorGUI.DisabledScope(true))
|
|
EditorGUILayout.TextField(title, variable);
|
|
|
|
if (GUILayout.Button("...", GUILayout.Width(30)))
|
|
{
|
|
var dummyPath = EditorUtility.OpenFolderPanel(title, AssetDatabase.IsValidFolder(variable) ? variable : string.Empty, string.Empty);
|
|
if (string.IsNullOrEmpty(dummyPath))
|
|
return null;
|
|
|
|
if (!dummyPath.StartsWith("Assets"))
|
|
{
|
|
Debug.LogWarning("New Path must be a folder within Assets!");
|
|
return null;
|
|
}
|
|
|
|
variable = FileUtil.GetProjectRelativePath(dummyPath);
|
|
if (isPlayerPrefs)
|
|
PlayerPrefs.SetString(playerpref, variable);
|
|
else
|
|
EditorPrefs.SetString(playerpref, variable);
|
|
}
|
|
}
|
|
|
|
return variable;
|
|
}
|
|
|
|
private static void DrawSeparator(int thickness = 2, int padding = 10)
|
|
{
|
|
Rect r = EditorGUILayout.GetControlRect(GUILayout.Height(thickness + padding));
|
|
r.height = thickness;
|
|
r.y += padding / 2f;
|
|
r.x -= 2;
|
|
r.width += 6;
|
|
ColorUtility.TryParseHtmlString(EditorGUIUtility.isProSkin ? "#595959" : "#858585", out Color lineColor);
|
|
EditorGUI.DrawRect(r, lineColor);
|
|
}
|
|
|
|
private static void Credit()
|
|
{
|
|
using (new GUILayout.HorizontalScope())
|
|
{
|
|
GUILayout.FlexibleSpace();
|
|
if (GUILayout.Button("Made By Dreadrith#3238", "boldlabel"))
|
|
Application.OpenURL("https://linktr.ee/Dreadrith");
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|