2220 lines
102 KiB
C#
2220 lines
102 KiB
C#
#if UNITY_EDITOR
|
||
using System.Collections.Generic;
|
||
using System.Globalization;
|
||
using DamageNumbersPro.Internal;
|
||
using TMPro;
|
||
using UnityEditor;
|
||
using UnityEditorInternal;
|
||
using UnityEngine;
|
||
using UnityEngine.Rendering;
|
||
|
||
namespace DamageNumbersPro
|
||
{
|
||
[CustomEditor(typeof(DamageNumber), true)]
|
||
[CanEditMultipleObjects]
|
||
public class DamageNumberEditor : Editor
|
||
{
|
||
public static string version = "4.51";
|
||
|
||
private void OnEnable()
|
||
{
|
||
DNPEditorInternal.PrepareInspector(this);
|
||
}
|
||
|
||
public override void OnInspectorGUI()
|
||
{
|
||
// For some operations
|
||
var isMesh = DNPEditorInternal.damageNumbers[0].IsMesh();
|
||
|
||
// Internal
|
||
DNPEditorInternal.OnInspectorGUI(this);
|
||
DNPEditorInternal.BeginInspector();
|
||
DNPEditorInternal.DrawInspectorTop(isMesh);
|
||
|
||
// Structure
|
||
if (DNPEditorInternal.CheckStructure(this))
|
||
{
|
||
DNPEditorInternal.EndInspector();
|
||
return;
|
||
}
|
||
|
||
// Detect and warn about common mistakes
|
||
WarningCheck(isMesh);
|
||
|
||
// Update
|
||
serializedObject.Update();
|
||
|
||
switch (DNPEditorInternal.currentTab)
|
||
{
|
||
case 0: // Main
|
||
DisplayMainSettings();
|
||
DisplayFeature("enable3DGame", "3D Game");
|
||
break;
|
||
case 1: // Text
|
||
DisplayTextMain(isMesh);
|
||
DisplayFeature("enableNumber", "Number");
|
||
DisplayFeature("enableLeftText", "Left Text");
|
||
DisplayFeature("enableRightText", "Right Text");
|
||
DisplayFeature("enableTopText", "Top Text");
|
||
DisplayFeature("enableBottomText", "Bottom Text");
|
||
DisplayFeature("enableColorByNumber", "Color By Number");
|
||
break;
|
||
case 2: // Fade In
|
||
DisplayFadeMain("In");
|
||
DisplayFeature("enableOffsetFadeIn", "Offset In", "Offset");
|
||
DisplayFeature("enableScaleFadeIn", "Scale In", "Scale");
|
||
DisplayFeature("enableShakeFadeIn", "Shake In", "Shake");
|
||
DisplayFeature("enableCrossScaleFadeIn", "Cross Scale In", "Cross Scale");
|
||
break;
|
||
case 3: // Fade Out
|
||
DisplayFadeMain("Out");
|
||
DisplayFeature("enableOffsetFadeOut", "Offset Out", "Offset");
|
||
DisplayFeature("enableScaleFadeOut", "Scale Out", "Scale");
|
||
DisplayFeature("enableShakeFadeOut", "Shake Out", "Shake");
|
||
DisplayFeature("enableCrossScaleFadeOut", "Cross Scale Out", "Cross Scale");
|
||
break;
|
||
case 4: // Movement
|
||
DisplayFeature("enableLerp", "Lerp");
|
||
DisplayFeature("enableVelocity", "Velocity");
|
||
DisplayFeature("enableShaking", "Shaking");
|
||
DisplayFeature("enableFollowing", "Following");
|
||
DisplayMovementHints(isMesh);
|
||
break;
|
||
case 5: // Scale
|
||
DisplayFeature("enableStartRotation", "Start Rotation");
|
||
DisplayFeature("enableRotateOverTime", "Rotate Over Time");
|
||
DisplayFeature("enableScaleByNumber", "Scale By Number");
|
||
DisplayFeature("enableScaleOverTime", "Scale Over Time");
|
||
DisplayFeature("enableOrthographicScaling", "Orthographic Scaling");
|
||
break;
|
||
case 6: // Spam Control
|
||
DisplaySpamControlMain(isMesh);
|
||
DisplayFeature("enableCombination", "Combination");
|
||
DisplayFeature("enableDestruction", "Destruction");
|
||
DisplayFeature("enableCollision", "Collision");
|
||
DisplayFeature("enablePush", "Push");
|
||
DisplaySpamControlHints(isMesh);
|
||
break;
|
||
case 7: // Performance
|
||
DisplayPerformanceMain();
|
||
DisplayFeature("enablePooling", "Pooling");
|
||
DisplayPerformanceHints();
|
||
break;
|
||
}
|
||
|
||
// Fix Variables
|
||
foreach (var dn in DNPEditorInternal.damageNumbers) FixAllVariables(dn);
|
||
|
||
// Apply Properties
|
||
serializedObject.ApplyModifiedProperties();
|
||
|
||
// Update Text
|
||
if (!Application.isPlaying)
|
||
foreach (var damageNumber in DNPEditorInternal.damageNumbers)
|
||
if (damageNumber.gameObject.activeInHierarchy)
|
||
{
|
||
if (isMesh) DNPEditorInternal.FixTextMeshPro();
|
||
|
||
try
|
||
{
|
||
damageNumber.UpdateText();
|
||
damageNumber.UpdateAlpha(1);
|
||
}
|
||
catch
|
||
{
|
||
}
|
||
|
||
if (isMesh) damageNumber.GetTextMesh().gameObject.SetActive(true);
|
||
}
|
||
|
||
// External Editors
|
||
DNPEditorInternal.Externalnspectors(isMesh, target);
|
||
DNPEditorInternal.FinalInformation();
|
||
|
||
DNPEditorInternal.EndInspector();
|
||
}
|
||
|
||
#region Warnings
|
||
|
||
private void WarningCheck(bool isMesh)
|
||
{
|
||
// 3D Game and no 3D enabled
|
||
var gameIs3DWarning = false;
|
||
if (isMesh)
|
||
{
|
||
var camera = Camera.main;
|
||
if (camera != null)
|
||
if (!camera.orthographic)
|
||
foreach (var dn in DNPEditorInternal.damageNumbers)
|
||
if (!dn.enable3DGame)
|
||
{
|
||
gameIs3DWarning = true;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (gameIs3DWarning)
|
||
{
|
||
EditorGUILayout.Space(2);
|
||
DNPEditorInternal.StartBox(new Color(1, 1f, 0.8f));
|
||
GUI.color = new Color(1, 1, 0.8f, 0.7f);
|
||
DNPEditorInternal.ScalingLabel("Your main camera seems to be perspective <i>(3D)</i>.", 298);
|
||
DNPEditorInternal.ScalingLabel("Go to the <b>Main</b> tab and enable <b>3D Game</b>.", 256);
|
||
DNPEditorInternal.CloseBox(new Color(1, 1f, 0.7f));
|
||
}
|
||
|
||
// 3D but UI Warning
|
||
if (!isMesh)
|
||
foreach (var dn in DNPEditorInternal.damageNumbers)
|
||
if (dn.enable3DGame)
|
||
{
|
||
EditorGUILayout.Space(2);
|
||
DNPEditorInternal.StartBox(new Color(1, 1f, 0.8f));
|
||
GUI.color = new Color(1, 1, 0.8f, 0.7f);
|
||
DNPEditorInternal.ScalingLabel("You have <b>3D Game</b> enabled on the <b>GUI</b> version.",
|
||
298);
|
||
DNPEditorInternal.ScalingLabel("This component is for spawning prefabs in a <b>GUI</b> canvas.",
|
||
298);
|
||
DNPEditorInternal.CloseBox(new Color(1, 1f, 0.7f));
|
||
}
|
||
|
||
// Pooling and Runtime Prefab Edits
|
||
var runtimePoolingWarning = false;
|
||
if (Application.isPlaying)
|
||
foreach (var dn in DNPEditorInternal.damageNumbers)
|
||
if (dn.enablePooling)
|
||
{
|
||
runtimePoolingWarning = true;
|
||
break;
|
||
}
|
||
|
||
if (runtimePoolingWarning)
|
||
{
|
||
EditorGUILayout.Space(2);
|
||
DNPEditorInternal.StartBox(new Color(1, 1f, 0.8f));
|
||
GUI.color = new Color(1, 1, 0.8f, 0.7f);
|
||
DNPEditorInternal.ScalingLabel(
|
||
"You are editing this prefab at <b>runtime</b> with <b>pooling</b> enabled.", 361);
|
||
DNPEditorInternal.ScalingLabel("Prefab <b>changes</b> will not affect <b>pooled</b> damage numbers.",
|
||
343);
|
||
DNPEditorInternal.CloseBox(new Color(1, 1f, 0.7f));
|
||
}
|
||
|
||
// Scale By Number but no Numbers
|
||
var scaleByNumbersWarning = false;
|
||
foreach (var dn in DNPEditorInternal.damageNumbers)
|
||
if (dn.enableScaleByNumber && !dn.enableNumber)
|
||
{
|
||
scaleByNumbersWarning = true;
|
||
break;
|
||
}
|
||
|
||
if (scaleByNumbersWarning)
|
||
{
|
||
EditorGUILayout.Space(2);
|
||
DNPEditorInternal.StartBox(new Color(1, 1f, 0.8f));
|
||
GUI.color = new Color(1, 1, 0.8f, 0.7f);
|
||
DNPEditorInternal.ScalingLabel("<b>Scale By Number</b> will not work if <b>Number</b> is disabled.",
|
||
327);
|
||
DNPEditorInternal.CloseBox(new Color(1, 1f, 0.7f));
|
||
}
|
||
|
||
// Color By Number but no Numbers
|
||
var colorByNumbersWarning = false;
|
||
foreach (var dn in DNPEditorInternal.damageNumbers)
|
||
if (dn.enableColorByNumber && !dn.enableNumber)
|
||
{
|
||
colorByNumbersWarning = true;
|
||
break;
|
||
}
|
||
|
||
if (colorByNumbersWarning)
|
||
{
|
||
EditorGUILayout.Space(2);
|
||
DNPEditorInternal.StartBox(new Color(1, 1f, 0.8f));
|
||
GUI.color = new Color(1, 1, 0.8f, 0.7f);
|
||
DNPEditorInternal.ScalingLabel("<b>Color By Number</b> will not work if <b>Number</b> is disabled.",
|
||
327);
|
||
DNPEditorInternal.CloseBox(new Color(1, 1f, 0.7f));
|
||
}
|
||
|
||
// Collision but no Lerp
|
||
var collisionWarning = false;
|
||
foreach (var dn in DNPEditorInternal.damageNumbers)
|
||
if (dn.enableCollision && !dn.enableLerp)
|
||
{
|
||
collisionWarning = true;
|
||
break;
|
||
}
|
||
|
||
if (collisionWarning)
|
||
{
|
||
EditorGUILayout.Space(2);
|
||
DNPEditorInternal.StartBox(new Color(1, 1f, 0.8f));
|
||
GUI.color = new Color(1, 1, 0.8f, 0.7f);
|
||
DNPEditorInternal.ScalingLabel("<b>Collision</b> will not work if <b>Lerp</b> movement is disabled.",
|
||
317);
|
||
DNPEditorInternal.CloseBox(new Color(1, 1f, 0.7f));
|
||
}
|
||
|
||
// Push but no Lerp
|
||
var pushWarning = false;
|
||
foreach (var dn in DNPEditorInternal.damageNumbers)
|
||
if (dn.enablePush && !dn.enableLerp)
|
||
{
|
||
pushWarning = true;
|
||
break;
|
||
}
|
||
|
||
if (pushWarning)
|
||
{
|
||
EditorGUILayout.Space(2);
|
||
DNPEditorInternal.StartBox(new Color(1, 1f, 0.8f));
|
||
GUI.color = new Color(1, 1, 0.8f, 0.7f);
|
||
DNPEditorInternal.ScalingLabel("<b>Push</b> will not work if <b>Lerp</b> movement is disabled.", 298);
|
||
DNPEditorInternal.CloseBox(new Color(1, 1f, 0.7f));
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Editor Menus
|
||
|
||
[MenuItem("GameObject/Damage Numbers Pro/Damage Number (Mesh)", priority = 1)]
|
||
public static void CreateDamageNumberMesh(MenuCommand menuCommand)
|
||
{
|
||
// Create GameObject
|
||
var newDN = new GameObject("Damage Number (Mesh)");
|
||
GameObjectUtility.SetParentAndAlign(newDN, menuCommand.context as GameObject);
|
||
Undo.RegisterCreatedObjectUndo(newDN, "Create " + newDN.name);
|
||
Selection.activeObject = newDN;
|
||
|
||
// Add damage number component
|
||
newDN.AddComponent<DamageNumberMesh>();
|
||
|
||
// Prepare Structure
|
||
DNPEditorInternal.PrepareMeshStructure(newDN);
|
||
|
||
// Position
|
||
if (Camera.main != null)
|
||
{
|
||
// Position in front of the camera
|
||
var position = Camera.main.transform.position + Camera.main.transform.forward * 10;
|
||
|
||
// Set Z to 0 for 2D Games
|
||
if (Camera.main.orthographic) position.z = 0;
|
||
|
||
newDN.transform.position = position;
|
||
}
|
||
}
|
||
|
||
[MenuItem("GameObject/Damage Numbers Pro/Damage Number (GUI)", priority = 2)]
|
||
public static void CreateDamageNumberGUI(MenuCommand menuCommand)
|
||
{
|
||
// Create GameObject
|
||
var newDN = new GameObject("Damage Number (GUI)");
|
||
GameObjectUtility.SetParentAndAlign(newDN, menuCommand.context as GameObject);
|
||
Undo.RegisterCreatedObjectUndo(newDN, "Create " + newDN.name);
|
||
Selection.activeObject = newDN;
|
||
|
||
// Add damage number component
|
||
newDN.AddComponent<DamageNumberGUI>();
|
||
|
||
// Prepare Structure
|
||
DNPEditorInternal.PrepareGUIStructure(newDN);
|
||
|
||
// Position
|
||
if (Camera.main != null)
|
||
{
|
||
// Position in front of the camera
|
||
var position = Camera.main.transform.position + Camera.main.transform.forward * 10;
|
||
|
||
// Set Z to 0 for 2D Games
|
||
if (Camera.main.orthographic) position.z = 0;
|
||
|
||
newDN.transform.position = position;
|
||
}
|
||
}
|
||
|
||
[MenuItem("CONTEXT/DamageNumberMesh/Switch to GUI (experimental)")]
|
||
public static void SwitchToGUI(MenuCommand menuCommand)
|
||
{
|
||
foreach (var selected in Selection.gameObjects)
|
||
{
|
||
var oldComponent = selected.GetComponent<DamageNumberMesh>();
|
||
Undo.RecordObject(oldComponent.gameObject, "Switched " + oldComponent.name);
|
||
|
||
if (oldComponent != null)
|
||
{
|
||
// Get TMP Settings
|
||
var fontAsset = oldComponent.GetFontMaterial();
|
||
var tmpColor = oldComponent.GetTextMesh().color;
|
||
var colorGradient = oldComponent.GetTextMesh().colorGradient;
|
||
var enableGradient = oldComponent.GetTextMesh().enableVertexGradient;
|
||
|
||
// Clear Children
|
||
while (oldComponent.transform.childCount > 0)
|
||
DestroyImmediate(oldComponent.transform.GetChild(0).gameObject);
|
||
|
||
// Add GUI Component
|
||
var newComponent = oldComponent.gameObject.AddComponent<DamageNumberGUI>();
|
||
ComponentUtility.MoveComponentUp(newComponent);
|
||
ComponentUtility.MoveComponentUp(newComponent);
|
||
ComponentUtility.MoveComponentUp(newComponent);
|
||
ComponentUtility.MoveComponentUp(newComponent);
|
||
ComponentUtility.MoveComponentUp(newComponent);
|
||
DNPEditorInternal.PrepareGUIStructure(selected);
|
||
|
||
// TMP Settings
|
||
newComponent.SetFontMaterial(fontAsset);
|
||
foreach (var tmp in newComponent.GetTextMeshs())
|
||
{
|
||
tmp.color = tmpColor;
|
||
tmp.enableVertexGradient = enableGradient;
|
||
tmp.colorGradient = colorGradient;
|
||
}
|
||
|
||
// Settings
|
||
foreach (var propA in oldComponent.GetType().GetFields())
|
||
{
|
||
var propB = newComponent.GetType().GetField(propA.Name);
|
||
|
||
if (propB.IsPublic && propB.IsPublic)
|
||
propB.SetValue(newComponent, propA.GetValue(oldComponent));
|
||
}
|
||
|
||
// 3D
|
||
newComponent.enable3DGame = false;
|
||
|
||
// Remove old component
|
||
DestroyImmediate(oldComponent);
|
||
}
|
||
}
|
||
}
|
||
|
||
[MenuItem("CONTEXT/DamageNumberGUI/Switch to Mesh (experimental)")]
|
||
public static void SwitchToMesh(MenuCommand menuCommand)
|
||
{
|
||
foreach (var selected in Selection.gameObjects)
|
||
{
|
||
var previousComponent = selected.GetComponent<DamageNumberGUI>();
|
||
Undo.RecordObject(previousComponent.gameObject, "Switched " + previousComponent.name);
|
||
|
||
if (previousComponent != null)
|
||
{
|
||
// Get TMP Settings
|
||
var fontAsset = previousComponent.GetFontMaterial();
|
||
var tmpColor = previousComponent.GetTextMesh().color;
|
||
var colorGradient = previousComponent.GetTextMesh().colorGradient;
|
||
var enableGradient = previousComponent.GetTextMesh().enableVertexGradient;
|
||
|
||
// Clear Children
|
||
while (previousComponent.transform.childCount > 0)
|
||
DestroyImmediate(previousComponent.transform.GetChild(0).gameObject);
|
||
|
||
// Add GUI Component
|
||
var newComponent = previousComponent.gameObject.AddComponent<DamageNumberMesh>();
|
||
ComponentUtility.MoveComponentUp(newComponent);
|
||
ComponentUtility.MoveComponentUp(newComponent);
|
||
ComponentUtility.MoveComponentUp(newComponent);
|
||
ComponentUtility.MoveComponentUp(newComponent);
|
||
ComponentUtility.MoveComponentUp(newComponent);
|
||
DNPEditorInternal.PrepareMeshStructure(selected);
|
||
|
||
// TMP Settings
|
||
newComponent.SetFontMaterial(fontAsset);
|
||
foreach (var tmp in newComponent.GetTextMeshs())
|
||
{
|
||
tmp.color = tmpColor;
|
||
tmp.enableVertexGradient = enableGradient;
|
||
tmp.colorGradient = colorGradient;
|
||
}
|
||
|
||
// Settings
|
||
foreach (var propA in previousComponent.GetType().GetFields())
|
||
{
|
||
var propB = newComponent.GetType().GetField(propA.Name);
|
||
|
||
if (propB.IsPublic && propB.IsPublic)
|
||
propB.SetValue(newComponent, propA.GetValue(previousComponent));
|
||
}
|
||
|
||
// 3D
|
||
newComponent.CheckAndEnable3D();
|
||
|
||
// Remove old components
|
||
DestroyImmediate(previousComponent);
|
||
var rectComponent = selected.GetComponent<RectTransform>();
|
||
if (rectComponent != null)
|
||
Debug.Log("Please rightclick on the RectTransform component and select 'Remove Component'.");
|
||
}
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Fixing Variables
|
||
|
||
private void FixAllVariables(DamageNumber dn)
|
||
{
|
||
// Performance
|
||
dn.updateDelay = Mathf.Max(0, dn.updateDelay);
|
||
|
||
// Main
|
||
dn.lifetime = Mathf.Max(0, dn.lifetime);
|
||
dn.distanceScalingSettings.baseDistance = Mathf.Max(1, dn.distanceScalingSettings.baseDistance);
|
||
|
||
// Text
|
||
dn.numberSettings = FixTextSettings(dn.numberSettings);
|
||
dn.leftTextSettings = FixTextSettings(dn.leftTextSettings);
|
||
dn.rightTextSettings = FixTextSettings(dn.rightTextSettings);
|
||
|
||
// Fade
|
||
dn.durationFadeIn = Mathf.Max(0, dn.durationFadeIn);
|
||
dn.durationFadeOut = Mathf.Max(0, dn.durationFadeOut);
|
||
|
||
// Digit
|
||
dn.digitSettings.decimals = Mathf.Max(0, dn.digitSettings.decimals);
|
||
dn.digitSettings.dotDistance = Mathf.Max(0, dn.digitSettings.dotDistance);
|
||
|
||
// Text Shader
|
||
var font = dn.GetFontMaterial();
|
||
var is3D = dn.enable3DGame ? "3D" : "";
|
||
if (dn.enable3DGame && dn.IsMesh() && font != null && font.name + is3D != dn.editorLastFont)
|
||
{
|
||
// Cache last font to only check once
|
||
dn.editorLastFont = font.name + is3D;
|
||
|
||
// Check if font is from the asset
|
||
var path = AssetDatabase.GetAssetPath(font);
|
||
if (path != null && path.Contains("DamageNumbers"))
|
||
{
|
||
// Undo record
|
||
var objects = new Object[3];
|
||
objects[0] = dn;
|
||
objects[1] = font;
|
||
objects[2] = font.material;
|
||
Undo.RecordObjects(objects, "Swiched shader to distance field overlay.");
|
||
|
||
// Fixing the text shader
|
||
if (GraphicsSettings.currentRenderPipeline != null)
|
||
{
|
||
var pipeline = GraphicsSettings.currentRenderPipeline.GetType().ToString();
|
||
|
||
if (pipeline.Contains("High") || pipeline.Contains("HD"))
|
||
{
|
||
}
|
||
else
|
||
{
|
||
ChangeShaderToOverlay(dn);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
ChangeShaderToOverlay(dn);
|
||
}
|
||
|
||
// Fixing the sprite shader
|
||
var tmp = dn.GetTextMesh();
|
||
if (tmp.spriteAsset != null && tmp.spriteAsset.material != null)
|
||
{
|
||
// Sprite Shader
|
||
if (tmp.spriteAsset.material.shader.name != "TextMeshPro/Sprite Overlay")
|
||
{
|
||
var spriteOverlay = Shader.Find("TextMeshPro/Sprite Overlay");
|
||
|
||
if (spriteOverlay != null) tmp.spriteAsset.material.shader = spriteOverlay;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// Default Sprite Shader
|
||
if (TMP_Settings.defaultSpriteAsset != null &&
|
||
TMP_Settings.defaultSpriteAsset.material != null &&
|
||
TMP_Settings.defaultSpriteAsset.material.shader.name != "TextMeshPro/Sprite Overlay")
|
||
{
|
||
var spriteOverlay = Shader.Find("TextMeshPro/Sprite Overlay");
|
||
|
||
if (spriteOverlay != null) TMP_Settings.defaultSpriteAsset.material.shader = spriteOverlay;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
private TextSettings FixTextSettings(TextSettings ts)
|
||
{
|
||
ts.horizontal = Mathf.Max(0, ts.horizontal);
|
||
|
||
return ts;
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Properties
|
||
|
||
private void DisplayFeature(string togglePropertyName, string featureTitle = "", string displayedTitle = "")
|
||
{
|
||
// Create title if needed
|
||
if (featureTitle == "") featureTitle = togglePropertyName.Replace("enable", "");
|
||
if (displayedTitle == "") displayedTitle = featureTitle;
|
||
|
||
EditorGUILayout.Space(2);
|
||
|
||
// Get Toggle Property
|
||
var toggleProperty = serializedObject.FindProperty(togglePropertyName);
|
||
|
||
// Start Box
|
||
DNPEditorInternal.StartBox(toggleProperty.hasMultipleDifferentValues || toggleProperty.boolValue);
|
||
|
||
// Top
|
||
EditorGUILayout.BeginHorizontal();
|
||
var showProperties = FeatureButton(toggleProperty, displayedTitle);
|
||
EditorGUILayout.LabelField("", GUILayout.MinWidth(0));
|
||
|
||
// Extra Buttons
|
||
|
||
#region Text Position
|
||
|
||
if (showProperties)
|
||
switch (togglePropertyName)
|
||
{
|
||
case "enableLeftText":
|
||
var leftTextPosition = TextPosition(0);
|
||
if (leftTextPosition != 0)
|
||
{
|
||
EditorGUIUtility.keyboardControl = EditorGUIUtility.hotControl = 0; // Unselect Fields
|
||
|
||
foreach (var dn in DNPEditorInternal.damageNumbers)
|
||
{
|
||
var originalTextEnabled = dn.enableLeftText;
|
||
var originalTextString = dn.leftText;
|
||
var originalTextSettings = dn.leftTextSettings;
|
||
|
||
switch (leftTextPosition)
|
||
{
|
||
case 1:
|
||
dn.enableLeftText = dn.enableRightText;
|
||
dn.leftText = dn.rightText;
|
||
dn.leftTextSettings = dn.rightTextSettings;
|
||
|
||
dn.enableRightText = originalTextEnabled;
|
||
dn.rightText = originalTextString;
|
||
dn.rightTextSettings = originalTextSettings;
|
||
break;
|
||
case 2:
|
||
dn.enableLeftText = dn.enableTopText;
|
||
dn.leftText = dn.topText;
|
||
dn.leftTextSettings = dn.topTextSettings;
|
||
|
||
dn.enableTopText = originalTextEnabled;
|
||
dn.topText = originalTextString;
|
||
dn.topTextSettings = originalTextSettings;
|
||
break;
|
||
case 3:
|
||
dn.enableLeftText = dn.enableBottomText;
|
||
dn.leftText = dn.bottomText;
|
||
dn.leftTextSettings = dn.bottomTextSettings;
|
||
|
||
dn.enableBottomText = originalTextEnabled;
|
||
dn.bottomText = originalTextString;
|
||
dn.bottomTextSettings = originalTextSettings;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
break;
|
||
case "enableRightText":
|
||
var rightTextPosition = TextPosition(1);
|
||
if (rightTextPosition != 1)
|
||
{
|
||
EditorGUIUtility.keyboardControl = EditorGUIUtility.hotControl = 0; // Unselect Fields
|
||
|
||
foreach (var dn in DNPEditorInternal.damageNumbers)
|
||
{
|
||
var originalTextEnabled = dn.enableRightText;
|
||
var originalTextString = dn.rightText;
|
||
var originalTextSettings = dn.rightTextSettings;
|
||
|
||
switch (rightTextPosition)
|
||
{
|
||
case 0:
|
||
dn.enableRightText = dn.enableLeftText;
|
||
dn.rightText = dn.leftText;
|
||
dn.rightTextSettings = dn.leftTextSettings;
|
||
|
||
dn.enableLeftText = originalTextEnabled;
|
||
dn.leftText = originalTextString;
|
||
dn.leftTextSettings = originalTextSettings;
|
||
break;
|
||
case 2:
|
||
dn.enableRightText = dn.enableTopText;
|
||
dn.rightText = dn.topText;
|
||
dn.rightTextSettings = dn.topTextSettings;
|
||
|
||
dn.enableTopText = originalTextEnabled;
|
||
dn.topText = originalTextString;
|
||
dn.topTextSettings = originalTextSettings;
|
||
break;
|
||
case 3:
|
||
dn.enableRightText = dn.enableBottomText;
|
||
dn.rightText = dn.bottomText;
|
||
dn.rightTextSettings = dn.bottomTextSettings;
|
||
|
||
dn.enableBottomText = originalTextEnabled;
|
||
dn.bottomText = originalTextString;
|
||
dn.bottomTextSettings = originalTextSettings;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
break;
|
||
case "enableTopText":
|
||
var topTextPosition = TextPosition(2);
|
||
if (topTextPosition != 2)
|
||
{
|
||
EditorGUIUtility.keyboardControl = EditorGUIUtility.hotControl = 0; // Unselect Fields
|
||
|
||
foreach (var dn in DNPEditorInternal.damageNumbers)
|
||
{
|
||
var originalTextEnabled = dn.enableTopText;
|
||
var originalTextString = dn.topText;
|
||
var originalTextSettings = dn.topTextSettings;
|
||
|
||
switch (topTextPosition)
|
||
{
|
||
case 0:
|
||
dn.enableTopText = dn.enableLeftText;
|
||
dn.topText = dn.leftText;
|
||
dn.topTextSettings = dn.leftTextSettings;
|
||
|
||
dn.enableLeftText = originalTextEnabled;
|
||
dn.leftText = originalTextString;
|
||
dn.leftTextSettings = originalTextSettings;
|
||
break;
|
||
case 1:
|
||
dn.enableTopText = dn.enableRightText;
|
||
dn.topText = dn.rightText;
|
||
dn.topTextSettings = dn.rightTextSettings;
|
||
|
||
dn.enableRightText = originalTextEnabled;
|
||
dn.rightText = originalTextString;
|
||
dn.rightTextSettings = originalTextSettings;
|
||
break;
|
||
case 3:
|
||
dn.enableTopText = dn.enableBottomText;
|
||
dn.topText = dn.bottomText;
|
||
dn.topTextSettings = dn.bottomTextSettings;
|
||
|
||
dn.enableBottomText = originalTextEnabled;
|
||
dn.bottomText = originalTextString;
|
||
dn.bottomTextSettings = originalTextSettings;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
break;
|
||
case "enableBottomText":
|
||
var bottomTextPosition = TextPosition(3);
|
||
if (bottomTextPosition != 3)
|
||
{
|
||
EditorGUIUtility.keyboardControl = EditorGUIUtility.hotControl = 0; // Unselect Fields
|
||
|
||
foreach (var dn in DNPEditorInternal.damageNumbers)
|
||
{
|
||
var originalTextEnabled = dn.enableBottomText;
|
||
var originalTextString = dn.bottomText;
|
||
var originalTextSettings = dn.bottomTextSettings;
|
||
|
||
switch (bottomTextPosition)
|
||
{
|
||
case 0:
|
||
dn.enableBottomText = dn.enableLeftText;
|
||
dn.bottomText = dn.leftText;
|
||
dn.bottomTextSettings = dn.leftTextSettings;
|
||
|
||
dn.enableLeftText = originalTextEnabled;
|
||
dn.leftText = originalTextString;
|
||
dn.leftTextSettings = originalTextSettings;
|
||
break;
|
||
case 1:
|
||
dn.enableBottomText = dn.enableRightText;
|
||
dn.bottomText = dn.rightText;
|
||
dn.bottomTextSettings = dn.rightTextSettings;
|
||
|
||
dn.enableRightText = originalTextEnabled;
|
||
dn.rightText = originalTextString;
|
||
dn.rightTextSettings = originalTextSettings;
|
||
break;
|
||
case 2:
|
||
dn.enableBottomText = dn.enableTopText;
|
||
dn.bottomText = dn.topText;
|
||
dn.bottomTextSettings = dn.topTextSettings;
|
||
|
||
dn.enableTopText = originalTextEnabled;
|
||
dn.topText = originalTextString;
|
||
dn.topTextSettings = originalTextSettings;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
break;
|
||
}
|
||
|
||
#endregion
|
||
|
||
if (showProperties) ResetButton(featureTitle);
|
||
var showHints = DNPEditorInternal.HintButton(featureTitle);
|
||
EditorGUILayout.EndHorizontal();
|
||
|
||
// Hints
|
||
if (showHints)
|
||
{
|
||
DNPEditorInternal.Lines();
|
||
GUI.color = new Color(1, 1, 1, 0.7f);
|
||
switch (featureTitle)
|
||
{
|
||
// Main
|
||
case "3D Game":
|
||
DNPEditorInternal.Label("<b>Function:</b>");
|
||
DNPEditorInternal.Label("- Handles <b>facing</b> the camera.");
|
||
DNPEditorInternal.Label("- Handles <b>screen size</b> over distance.");
|
||
DNPEditorInternal.Label("- Can handle rendering <b>through walls</b>.");
|
||
DNPEditorInternal.Label("");
|
||
DNPEditorInternal.Label("<b>Information:</b>");
|
||
DNPEditorInternal.Label("- Enable this feature in <b>3D</b> projects.");
|
||
break;
|
||
|
||
// Text Content
|
||
case "Number":
|
||
DNPEditorInternal.Label("<b>Function:</b>");
|
||
DNPEditorInternal.Label("- Displays a <b>number</b>.");
|
||
DNPEditorInternal.Label("- Has several <b>text formatting</b> options.");
|
||
DNPEditorInternal.Label(
|
||
"- Number can be displayed as an <b>integer</b> or in <b>decimals</b>.");
|
||
DNPEditorInternal.Label(
|
||
"- Large numbers can be <b>dot separated</b> or <b>suffix shortened</b>.");
|
||
DNPEditorInternal.Label("");
|
||
DNPEditorInternal.Label("<b>Information:</b>");
|
||
DNPEditorInternal.Label(
|
||
"- If you want <b>text-only</b> simply disable this and enable <b>Left Text</b>.");
|
||
DNPEditorInternal.Label("- Text positions are <b>relative</b> to the number.");
|
||
DNPEditorInternal.Label("- Numbers will be added up if <b>Combination</b> is enabled.");
|
||
DNPEditorInternal.Label("- Numbers will be used by <b>Scale by Number</b>.");
|
||
break;
|
||
case "Left Text":
|
||
DNPEditorInternal.Label("<b>Function:</b>");
|
||
DNPEditorInternal.Label("- Displays <b>text</b> on the left side.");
|
||
DNPEditorInternal.Label("- Has several <b>text formatting</b> options.");
|
||
DNPEditorInternal.Label("");
|
||
DNPEditorInternal.Label("<b>Information:</b>");
|
||
DNPEditorInternal.Label("- If <b>number</b> is disabled this will be <b>centered</b>.");
|
||
DNPEditorInternal.Label("- You can use the <b>arrow</b> buttons to swap the position.");
|
||
DNPEditorInternal.Label("- The <b>Spawn(...)</b> function has overrides which set this text.");
|
||
break;
|
||
case "Right Text":
|
||
DNPEditorInternal.Label("<b>Function:</b>");
|
||
DNPEditorInternal.Label("- Displays <b>text</b> on the right side.");
|
||
DNPEditorInternal.Label("- Has several <b>text formatting</b> options.");
|
||
DNPEditorInternal.Label("");
|
||
DNPEditorInternal.Label("<b>Information:</b>");
|
||
DNPEditorInternal.Label("- If <b>number</b> is disabled this will be <b>centered</b>.");
|
||
DNPEditorInternal.Label("- You can use the <b>arrow</b> buttons to swap the position.");
|
||
break;
|
||
case "Top Text":
|
||
DNPEditorInternal.Label("<b>Function:</b>");
|
||
DNPEditorInternal.Label("- Displays <b>text</b> on the top side.");
|
||
DNPEditorInternal.Label("- Has several <b>text formatting</b> options.");
|
||
DNPEditorInternal.Label("");
|
||
DNPEditorInternal.Label("<b>Information:</b>");
|
||
DNPEditorInternal.Label("- You can use the <b>arrow</b> buttons to swap the position.");
|
||
break;
|
||
case "Bottom Text":
|
||
DNPEditorInternal.Label("<b>Function:</b>");
|
||
DNPEditorInternal.Label("- Displays <b>text</b> on the bottom side.");
|
||
DNPEditorInternal.Label("- Has several <b>text formatting</b> options.");
|
||
DNPEditorInternal.Label("");
|
||
DNPEditorInternal.Label("<b>Information:</b>");
|
||
DNPEditorInternal.Label("- You can use the <b>arrow</b> buttons to swap the position.");
|
||
break;
|
||
case "Color By Number":
|
||
DNPEditorInternal.Label("<b>Function:</b>");
|
||
DNPEditorInternal.Label("- Changes the <b>color</b> based on the <b>number</b>.");
|
||
DNPEditorInternal.Label(
|
||
"- <b>Larger</b> and <b>smaller</b> numbers can have different <b>tints</b>.");
|
||
break;
|
||
|
||
// Movement
|
||
case "Lerp":
|
||
DNPEditorInternal.Label("<b>Function:</b>");
|
||
DNPEditorInternal.Label("- Moves towards a random <b>offset</b>.");
|
||
DNPEditorInternal.Label("- <b>Slows</b> down as it gets closer to it's target position.");
|
||
DNPEditorInternal.Label("");
|
||
DNPEditorInternal.Label("<b>Information:</b>");
|
||
DNPEditorInternal.Label("- This is the most <b>popular</b> and <b>readable</b> option.");
|
||
DNPEditorInternal.Label(
|
||
"- Some features require this and warn you if <b>Lerp</b> is disabled.");
|
||
DNPEditorInternal.Label("- Offset is relative to <b>view</b> direction.");
|
||
break;
|
||
case "Velocity":
|
||
DNPEditorInternal.Label("<b>Function:</b>");
|
||
DNPEditorInternal.Label("- Moves at a random <b>velocity</b>.");
|
||
DNPEditorInternal.Label("- Has <b>drag</b> and <b>gravity</b> options.");
|
||
DNPEditorInternal.Label("");
|
||
DNPEditorInternal.Label("<b>Information:</b>");
|
||
DNPEditorInternal.Label("- Movement is relative to <b>view</b> direction.");
|
||
break;
|
||
case "Shaking":
|
||
DNPEditorInternal.Label("<b>Function:</b>");
|
||
DNPEditorInternal.Label("- Moves <b>back</b> and <b>forth</b>.");
|
||
DNPEditorInternal.Label("");
|
||
DNPEditorInternal.Label("<b>Information:</b>");
|
||
DNPEditorInternal.Label("- Can be used for <b>shaking</b> or <b>vibration</b> effects.");
|
||
break;
|
||
case "Following":
|
||
DNPEditorInternal.Label("<b>Function:</b>");
|
||
DNPEditorInternal.Label("- Follows the <b>target</b> transform.");
|
||
DNPEditorInternal.Label("- Maintains <b>relative position</b> to target.");
|
||
DNPEditorInternal.Label("");
|
||
DNPEditorInternal.Label("<b>Information:</b>");
|
||
DNPEditorInternal.Label("- Lower speeds are more <b>smooth</b>.");
|
||
DNPEditorInternal.Label("- Higher speeds are more <b>static</b>.");
|
||
DNPEditorInternal.Label("- Drag can be used to <b>fade out</b> the following.");
|
||
break;
|
||
|
||
// Fade In
|
||
case "Offset In":
|
||
DNPEditorInternal.Label("<b>Function:</b>");
|
||
DNPEditorInternal.Label("- Moves 2 meshs <b>together</b> from a <b>offset</b>.");
|
||
DNPEditorInternal.Label("");
|
||
DNPEditorInternal.Label("<b>Information:</b>");
|
||
DNPEditorInternal.Label("- Creates a <b>fusion-like</b> effect.");
|
||
break;
|
||
case "Scale In":
|
||
DNPEditorInternal.Label("<b>Function:</b>");
|
||
DNPEditorInternal.Label("- Fades in from a customizable <b>scale</b>.");
|
||
DNPEditorInternal.Label("");
|
||
DNPEditorInternal.Label("<b>Information:</b>");
|
||
DNPEditorInternal.Label("- Is used for <b>shrinking</b> or <b>growing</b> when fading in.");
|
||
break;
|
||
case "Cross Scale In":
|
||
DNPEditorInternal.Label("<b>Function:</b>");
|
||
DNPEditorInternal.Label("- <b>Scales</b> one mesh and <b>divides</b> the scale of the other.");
|
||
DNPEditorInternal.Label("");
|
||
DNPEditorInternal.Label("<b>Information:</b>");
|
||
DNPEditorInternal.Label(
|
||
"- <b>Inverse</b> scales one mesh and <b>normally</b> scales the other.");
|
||
break;
|
||
case "Shake In":
|
||
DNPEditorInternal.Label("<b>Function:</b>");
|
||
DNPEditorInternal.Label("- <b>Shakes</b> as it fades in.");
|
||
DNPEditorInternal.Label("");
|
||
DNPEditorInternal.Label("<b>Information:</b>");
|
||
DNPEditorInternal.Label("- Used for <b>vibration</b> or <b>motion</b> when fading in.");
|
||
break;
|
||
|
||
// Fade Out
|
||
case "Offset Out":
|
||
DNPEditorInternal.Label("<b>Function:</b>");
|
||
DNPEditorInternal.Label("- Moves 2 meshs <b>apart</b> to a <b>offset</b>.");
|
||
DNPEditorInternal.Label("");
|
||
DNPEditorInternal.Label("<b>Information:</b>");
|
||
DNPEditorInternal.Label("- Creates a <b>diffusion-like</b> effect.");
|
||
break;
|
||
case "Scale Out":
|
||
DNPEditorInternal.Label("<b>Function:</b>");
|
||
DNPEditorInternal.Label("- Fades out to a customizable <b>scale</b>.");
|
||
DNPEditorInternal.Label("");
|
||
DNPEditorInternal.Label("<b>Information:</b>");
|
||
DNPEditorInternal.Label("- Is used for <b>shrinking</b> or <b>growing</b> when fading out.");
|
||
break;
|
||
case "Cross Scale Out":
|
||
DNPEditorInternal.Label("<b>Function:</b>");
|
||
DNPEditorInternal.Label("- <b>Scales</b> one mesh and <b>divides</b> the scale of the other.");
|
||
DNPEditorInternal.Label("");
|
||
DNPEditorInternal.Label("<b>Information:</b>");
|
||
DNPEditorInternal.Label(
|
||
"- <b>Inverse</b> scales one mesh and <b>normally</b> scales the other.");
|
||
break;
|
||
case "Shake Out":
|
||
DNPEditorInternal.Label("<b>Function:</b>");
|
||
DNPEditorInternal.Label("- <b>Shakes</b> as it fades out.");
|
||
DNPEditorInternal.Label("");
|
||
DNPEditorInternal.Label("<b>Information:</b>");
|
||
DNPEditorInternal.Label("- Used for <b>vibration</b> or <b>motion</b> when fading out.");
|
||
break;
|
||
|
||
// Rotation & Scale
|
||
case "Start Rotation":
|
||
DNPEditorInternal.Label("<b>Function:</b>");
|
||
DNPEditorInternal.Label("- Spawns at a random <b>rotation</b>.");
|
||
break;
|
||
case "Rotate Over Time":
|
||
DNPEditorInternal.Label("<b>Function:</b>");
|
||
DNPEditorInternal.Label("- Rotates at a random <b>rotation speed</b> over time.");
|
||
DNPEditorInternal.Label("");
|
||
DNPEditorInternal.Label("<b>Information:</b>");
|
||
DNPEditorInternal.Label("- Speed over time can be customized in a <b>curve</b>.");
|
||
break;
|
||
case "Scale By Number":
|
||
DNPEditorInternal.Label("<b>Function:</b>");
|
||
DNPEditorInternal.Label("- Scales based on the <b>number's size</b>.");
|
||
DNPEditorInternal.Label("");
|
||
DNPEditorInternal.Label("<b>Information:</b>");
|
||
DNPEditorInternal.Label("- Bigger numbers are <b>larger</b>.");
|
||
DNPEditorInternal.Label("- Will also work with <b>Combination</b>.");
|
||
break;
|
||
case "Scale Over Time":
|
||
DNPEditorInternal.Label("<b>Function:</b>");
|
||
DNPEditorInternal.Label("- Changes scale over <b>time</b>.");
|
||
DNPEditorInternal.Label("");
|
||
DNPEditorInternal.Label("<b>Information:</b>");
|
||
DNPEditorInternal.Label("- Scale over time can be customized in a <b>curve</b>.");
|
||
break;
|
||
case "Orthographic Scaling":
|
||
DNPEditorInternal.Label("<b>Function:</b>");
|
||
DNPEditorInternal.Label(
|
||
"- Scales the popup to keep it's screen size consistent, when zooming in <b>2D projects</b>.");
|
||
DNPEditorInternal.Label("");
|
||
DNPEditorInternal.Label("<b>Information:</b>");
|
||
DNPEditorInternal.Label("- Scale is based on the camera's orthographic size.");
|
||
break;
|
||
|
||
// Spam Control
|
||
case "Combination":
|
||
DNPEditorInternal.Label("<b>Function:</b>");
|
||
DNPEditorInternal.Label("- <b>Combines</b> with other damage numbers within range.");
|
||
DNPEditorInternal.Label("- <b>Adds up</b> the combined numbers.");
|
||
DNPEditorInternal.Label("");
|
||
DNPEditorInternal.Label("<b>Information:</b>");
|
||
DNPEditorInternal.Label("- <b>ABSORB_NEW</b> makes the oldest damage number absorb new ones.");
|
||
DNPEditorInternal.Label(
|
||
"- <b>REPLACE_OLD</b> makes the newest damage number absorb older ones.");
|
||
DNPEditorInternal.Label("- Animation can be customized using <b>curves</b>.");
|
||
DNPEditorInternal.Label("- Absorber can get a <b>scale up</b> upon absorbing a damage number.");
|
||
break;
|
||
case "Destruction":
|
||
DNPEditorInternal.Label("<b>Function:</b>");
|
||
DNPEditorInternal.Label("- <b>Destroys</b> older damage numbers.");
|
||
DNPEditorInternal.Label("");
|
||
DNPEditorInternal.Label("<b>Information:</b>");
|
||
DNPEditorInternal.Label(
|
||
"- Has a custom <b>fade out</b> animation for destroyed damage numbers.");
|
||
break;
|
||
case "Collision":
|
||
DNPEditorInternal.Label("<b>Function:</b>");
|
||
DNPEditorInternal.Label("- Collides with other damage numbers to <b>spread</b> out.");
|
||
DNPEditorInternal.Label("");
|
||
DNPEditorInternal.Label("<b>Information:</b>");
|
||
DNPEditorInternal.Label(
|
||
"- If desired direction is set to something like <b>(0,10,0)</b> they will spread up.");
|
||
break;
|
||
case "Push":
|
||
DNPEditorInternal.Label("<b>Function:</b>");
|
||
DNPEditorInternal.Label(
|
||
"- Simply <b>moves</b> damage numbers by a custom offset within range.");
|
||
DNPEditorInternal.Label("");
|
||
DNPEditorInternal.Label("<b>Information:</b>");
|
||
DNPEditorInternal.Label("- This is a more efficient version of <b>Collision</b>.");
|
||
DNPEditorInternal.Label("- Use this on <b>closely spawned</b> damage numbers only.");
|
||
break;
|
||
|
||
// Performance
|
||
case "Pooling":
|
||
DNPEditorInternal.Label("<b>Function:</b>");
|
||
DNPEditorInternal.Label("- Improves <b>spawn performance</b> by recycling damage numbers.");
|
||
DNPEditorInternal.Label("");
|
||
DNPEditorInternal.Label("<b>Information:</b>");
|
||
DNPEditorInternal.Label(
|
||
"- Pool size should be <b>higher</b> if you spawn more damage numbers per second.");
|
||
DNPEditorInternal.Label(
|
||
"- New damage numbers are <b>added to the pool</b> if it's not full yet.");
|
||
DNPEditorInternal.Label("- Each prefab has it's <b>own</b> pool.");
|
||
DNPEditorInternal.Label("- Use <b>PrewarmPool()</b> on a prefab to prepare it's pool.");
|
||
break;
|
||
}
|
||
|
||
GUI.color = Color.white;
|
||
}
|
||
|
||
// Properties
|
||
if (showProperties)
|
||
{
|
||
DNPEditorInternal.Lines();
|
||
|
||
switch (featureTitle)
|
||
{
|
||
// Main
|
||
case "3D Game":
|
||
var faceCameraView = serializedObject.FindProperty("faceCameraView");
|
||
EditorGUILayout.PropertyField(faceCameraView);
|
||
if (faceCameraView.boolValue || faceCameraView.hasMultipleDifferentValues)
|
||
{
|
||
var lookAtCamera = serializedObject.FindProperty("lookAtCamera");
|
||
EditorGUILayout.PropertyField(lookAtCamera, new GUIContent("Look At (For VR)"));
|
||
|
||
if (lookAtCamera.boolValue || lookAtCamera.hasMultipleDifferentValues)
|
||
{
|
||
GUI.color = new Color(1, 1, 1, 0.7f);
|
||
DNPEditorInternal.Label(
|
||
"- Costs <b>more performance</b> and should only be used in <b>VR</b>.");
|
||
GUI.color = Color.white;
|
||
}
|
||
}
|
||
|
||
DNPEditorInternal.Lines();
|
||
|
||
// Check Materials
|
||
var hasOverlayMaterials = false;
|
||
var hasBadMaterials = false;
|
||
foreach (var dn in DNPEditorInternal.damageNumbers)
|
||
{
|
||
dn.GetReferencesIfNecessary();
|
||
var materials = dn.GetSharedMaterials();
|
||
|
||
if (materials != null)
|
||
foreach (var mat in materials)
|
||
if (mat != null && mat.shader.name.EndsWith("verlay"))
|
||
hasOverlayMaterials = true;
|
||
else
|
||
hasBadMaterials = true;
|
||
}
|
||
|
||
if (hasOverlayMaterials && !hasBadMaterials) GUI.enabled = false;
|
||
var renderThroughWalls = serializedObject.FindProperty("renderThroughWalls");
|
||
EditorGUILayout.PropertyField(renderThroughWalls);
|
||
if (hasOverlayMaterials && !hasBadMaterials)
|
||
{
|
||
GUI.enabled = true;
|
||
renderThroughWalls.boolValue = false;
|
||
PropertyOverlay(DNPEditorInternal.CheckmarkString(true) + " Overlay Shader.");
|
||
}
|
||
else
|
||
{
|
||
if (DNPEditorInternal.currentWidth < 344)
|
||
{
|
||
if (DNPEditorInternal.currentWidth < 277)
|
||
PropertyOverlay(DNPEditorInternal.CheckmarkString(false) + " Shader");
|
||
else
|
||
PropertyOverlay(DNPEditorInternal.CheckmarkString(false) + " Overlay Shader");
|
||
}
|
||
else
|
||
{
|
||
PropertyOverlay(
|
||
DNPEditorInternal.CheckmarkString(false) + " Not using overlay shader.");
|
||
}
|
||
}
|
||
|
||
if (renderThroughWalls.boolValue || renderThroughWalls.hasMultipleDifferentValues)
|
||
{
|
||
GUI.color = new Color(1, 1, 1, 0.7f);
|
||
EditorGUILayout.Space();
|
||
DNPEditorInternal.ScalingLabel(
|
||
"This option exists in-case the overlay shader does <b>not work</b>.", 371);
|
||
DNPEditorInternal.ScalingLabel(
|
||
"Make sure to try the <b>'Distance Field Overlay'</b> shader first.", 354);
|
||
DNPEditorInternal.ScalingLabel(
|
||
"It's better for <b>performance</b> to use the overlay shader.", 330);
|
||
DNPEditorInternal.ScalingLabel(
|
||
"Keep in mind that the shader does not support <b>UI masking</b> though.", 410);
|
||
EditorGUILayout.Space();
|
||
EditorGUILayout.BeginHorizontal();
|
||
DNPEditorInternal.ScalingLabel("Go to the material tab or use the button.", 333);
|
||
GUI.color = Color.white;
|
||
|
||
var buttonPressed = false;
|
||
if (DNPEditorInternal.currentWidth < 283)
|
||
buttonPressed = GUILayout.Button("Try");
|
||
else
|
||
buttonPressed = GUILayout.Button("Try Shader");
|
||
|
||
if (buttonPressed)
|
||
foreach (var dn in DNPEditorInternal.damageNumbers)
|
||
ChangeShaderToOverlay(dn);
|
||
|
||
EditorGUILayout.EndHorizontal();
|
||
}
|
||
|
||
DNPEditorInternal.Lines();
|
||
|
||
var consistentScale = serializedObject.FindProperty("consistentScreenSize");
|
||
EditorGUILayout.PropertyField(consistentScale);
|
||
GUI.enabled = consistentScale.boolValue || consistentScale.hasMultipleDifferentValues;
|
||
EditorGUILayout.BeginHorizontal();
|
||
EditorGUILayout.LabelField("", GUILayout.Width(9));
|
||
EditorGUILayout.PropertyField(serializedObject.FindProperty("distanceScalingSettings"));
|
||
EditorGUILayout.EndHorizontal();
|
||
GUI.enabled = true;
|
||
DNPEditorInternal.Lines();
|
||
|
||
|
||
var scaleWithFOV = serializedObject.FindProperty("scaleWithFov");
|
||
EditorGUILayout.PropertyField(scaleWithFOV);
|
||
if (scaleWithFOV.boolValue || scaleWithFOV.hasMultipleDifferentValues)
|
||
{
|
||
EditorGUILayout.PropertyField(serializedObject.FindProperty("defaultFov"));
|
||
EditorGUILayout.PropertyField(serializedObject.FindProperty("fovCamera"));
|
||
|
||
var noFovCameraOverride = true;
|
||
foreach (var dn in DNPEditorInternal.damageNumbers)
|
||
if (dn.fovCamera != null)
|
||
{
|
||
noFovCameraOverride = false;
|
||
break;
|
||
}
|
||
|
||
if (noFovCameraOverride)
|
||
{
|
||
var overlayString = "Main Camera";
|
||
|
||
if (DNPEditorInternal.currentWidth < 404)
|
||
{
|
||
overlayString = "<size=11>Main Camera</size>";
|
||
|
||
if (DNPEditorInternal.currentWidth < 389) overlayString = "";
|
||
}
|
||
|
||
if (DNPEditorInternal.currentWidth > 293)
|
||
PropertyOverlay(DNPEditorInternal.CheckmarkString(true) + " " + overlayString +
|
||
" ");
|
||
}
|
||
else
|
||
{
|
||
GUI.color = new Color(1, 1, 1, 0.7f);
|
||
DNPEditorInternal.ScalingLabel(
|
||
"Only required if your <b>main camera</b> is not the FOV camera.", 362);
|
||
GUI.color = Color.white;
|
||
}
|
||
}
|
||
|
||
DNPEditorInternal.Lines();
|
||
|
||
EditorGUILayout.PropertyField(serializedObject.FindProperty("cameraOverride"));
|
||
var noCameraOverride = true;
|
||
foreach (var dn in DNPEditorInternal.damageNumbers)
|
||
if (dn.cameraOverride != null)
|
||
{
|
||
noCameraOverride = false;
|
||
break;
|
||
}
|
||
|
||
if (noCameraOverride)
|
||
{
|
||
var overlayString = "Main Camera";
|
||
|
||
if (DNPEditorInternal.currentWidth < 404)
|
||
{
|
||
overlayString = "<size=11>Main Camera</size>";
|
||
|
||
if (DNPEditorInternal.currentWidth < 389) overlayString = "";
|
||
}
|
||
|
||
if (DNPEditorInternal.currentWidth > 293)
|
||
PropertyOverlay(DNPEditorInternal.CheckmarkString(true) + " " + overlayString +
|
||
" ");
|
||
}
|
||
else
|
||
{
|
||
GUI.color = new Color(1, 1, 1, 0.7f);
|
||
DNPEditorInternal.ScalingLabel(
|
||
"Only required if your <b>main camera</b> is not the target camera.", 362);
|
||
GUI.color = Color.white;
|
||
}
|
||
|
||
break;
|
||
|
||
// Text Content
|
||
case "Number":
|
||
EditorGUILayout.PropertyField(serializedObject.FindProperty("number"));
|
||
EditorGUILayout.BeginHorizontal();
|
||
EditorGUILayout.LabelField("", GUILayout.Width(9));
|
||
EditorGUILayout.PropertyField(serializedObject.FindProperty("numberSettings"));
|
||
EditorGUILayout.EndHorizontal();
|
||
EditorGUILayout.BeginHorizontal();
|
||
EditorGUILayout.LabelField("", GUILayout.Width(9));
|
||
EditorGUILayout.PropertyField(serializedObject.FindProperty("digitSettings"));
|
||
EditorGUILayout.EndHorizontal();
|
||
break;
|
||
case "Left Text":
|
||
HandleTextProperty(serializedObject.FindProperty("leftText"));
|
||
EditorGUILayout.BeginHorizontal();
|
||
EditorGUILayout.LabelField("", GUILayout.Width(9));
|
||
EditorGUILayout.PropertyField(serializedObject.FindProperty("leftTextSettings"));
|
||
EditorGUILayout.EndHorizontal();
|
||
break;
|
||
case "Right Text":
|
||
HandleTextProperty(serializedObject.FindProperty("rightText"));
|
||
EditorGUILayout.BeginHorizontal();
|
||
EditorGUILayout.LabelField("", GUILayout.Width(9));
|
||
EditorGUILayout.PropertyField(serializedObject.FindProperty("rightTextSettings"));
|
||
EditorGUILayout.EndHorizontal();
|
||
break;
|
||
case "Top Text":
|
||
HandleTextProperty(serializedObject.FindProperty("topText"));
|
||
EditorGUILayout.BeginHorizontal();
|
||
EditorGUILayout.LabelField("", GUILayout.Width(9));
|
||
EditorGUILayout.PropertyField(serializedObject.FindProperty("topTextSettings"));
|
||
EditorGUILayout.EndHorizontal();
|
||
break;
|
||
case "Bottom Text":
|
||
HandleTextProperty(serializedObject.FindProperty("bottomText"));
|
||
EditorGUILayout.BeginHorizontal();
|
||
EditorGUILayout.LabelField("", GUILayout.Width(9));
|
||
EditorGUILayout.PropertyField(serializedObject.FindProperty("bottomTextSettings"));
|
||
EditorGUILayout.EndHorizontal();
|
||
break;
|
||
case "Color By Number":
|
||
EditorGUILayout.BeginHorizontal();
|
||
EditorGUILayout.LabelField("", GUILayout.Width(9));
|
||
EditorGUILayout.PropertyField(serializedObject.FindProperty("colorByNumberSettings"));
|
||
EditorGUILayout.EndHorizontal();
|
||
break;
|
||
|
||
// Movement
|
||
case "Lerp":
|
||
EditorGUILayout.BeginHorizontal();
|
||
EditorGUILayout.LabelField("", GUILayout.Width(9));
|
||
EditorGUILayout.PropertyField(serializedObject.FindProperty("lerpSettings"));
|
||
EditorGUILayout.EndHorizontal();
|
||
break;
|
||
case "Velocity":
|
||
EditorGUILayout.BeginHorizontal();
|
||
EditorGUILayout.LabelField("", GUILayout.Width(9));
|
||
EditorGUILayout.PropertyField(serializedObject.FindProperty("velocitySettings"));
|
||
EditorGUILayout.EndHorizontal();
|
||
break;
|
||
case "Shaking":
|
||
EditorGUILayout.BeginHorizontal();
|
||
EditorGUILayout.LabelField("", GUILayout.Width(9));
|
||
EditorGUILayout.PropertyField(serializedObject.FindProperty("shakeSettings"));
|
||
EditorGUILayout.EndHorizontal();
|
||
break;
|
||
case "Following":
|
||
EditorGUILayout.PropertyField(serializedObject.FindProperty("followedTarget"));
|
||
EditorGUILayout.BeginHorizontal();
|
||
EditorGUILayout.LabelField("", GUILayout.Width(9));
|
||
EditorGUILayout.PropertyField(serializedObject.FindProperty("followSettings"));
|
||
EditorGUILayout.EndHorizontal();
|
||
break;
|
||
|
||
// Fade In
|
||
case "Offset In":
|
||
EditorGUILayout.PropertyField(serializedObject.FindProperty("offsetFadeIn"),
|
||
new GUIContent("Offset"));
|
||
break;
|
||
case "Scale In":
|
||
EditorGUILayout.PropertyField(serializedObject.FindProperty("scaleFadeIn"),
|
||
new GUIContent("Scale"));
|
||
break;
|
||
case "Cross Scale In":
|
||
EditorGUILayout.PropertyField(serializedObject.FindProperty("crossScaleFadeIn"),
|
||
new GUIContent("Cross Scale"));
|
||
break;
|
||
case "Shake In":
|
||
EditorGUILayout.PropertyField(serializedObject.FindProperty("shakeOffsetFadeIn"),
|
||
new GUIContent("Shake Offset"));
|
||
EditorGUILayout.PropertyField(serializedObject.FindProperty("shakeFrequencyFadeIn"),
|
||
new GUIContent("Shake Frequency"));
|
||
break;
|
||
|
||
|
||
// Fade Out
|
||
case "Offset Out":
|
||
EditorGUILayout.PropertyField(serializedObject.FindProperty("offsetFadeOut"),
|
||
new GUIContent("Offset"));
|
||
break;
|
||
case "Scale Out":
|
||
EditorGUILayout.PropertyField(serializedObject.FindProperty("scaleFadeOut"),
|
||
new GUIContent("Scale"));
|
||
break;
|
||
case "Cross Scale Out":
|
||
EditorGUILayout.PropertyField(serializedObject.FindProperty("crossScaleFadeOut"),
|
||
new GUIContent("Cross Scale"));
|
||
break;
|
||
case "Shake Out":
|
||
EditorGUILayout.PropertyField(serializedObject.FindProperty("shakeOffsetFadeOut"),
|
||
new GUIContent("Shake Offset"));
|
||
EditorGUILayout.PropertyField(serializedObject.FindProperty("shakeFrequencyFadeOut"),
|
||
new GUIContent("Shake Frequency"));
|
||
break;
|
||
|
||
// Rotation & Scale
|
||
case "Start Rotation":
|
||
EditorGUILayout.PropertyField(serializedObject.FindProperty("minRotation"));
|
||
EditorGUILayout.PropertyField(serializedObject.FindProperty("maxRotation"));
|
||
EditorGUILayout.PropertyField(serializedObject.FindProperty("rotationRandomFlip"),
|
||
new GUIContent("Random Flip",
|
||
"Randomly flips the Rotation.\nUseful for avoiding small rotations.\nSet Min and Max to a positive value."));
|
||
break;
|
||
case "Rotate Over Time":
|
||
EditorGUILayout.PropertyField(serializedObject.FindProperty("minRotationSpeed"));
|
||
EditorGUILayout.PropertyField(serializedObject.FindProperty("maxRotationSpeed"));
|
||
EditorGUILayout.PropertyField(serializedObject.FindProperty("rotationSpeedRandomFlip"),
|
||
new GUIContent("Random Flip",
|
||
"Randomly flips the Rotation Speed.\nUseful for avoiding small rotation speeds.\nSet Min and Max to a positive value."));
|
||
|
||
var rotateOverTimeProperty = serializedObject.FindProperty("rotateOverTime");
|
||
var rotateOverTimeColor = Color.Lerp(Color.red, Color.green,
|
||
rotateOverTimeProperty.animationCurveValue.Evaluate(1));
|
||
EditorGUILayout.CurveField(rotateOverTimeProperty, rotateOverTimeColor, new Rect(0, 0, 1, 1));
|
||
break;
|
||
case "Scale By Number":
|
||
EditorGUILayout.BeginHorizontal();
|
||
EditorGUILayout.LabelField("", GUILayout.Width(9));
|
||
EditorGUILayout.PropertyField(serializedObject.FindProperty("scaleByNumberSettings"));
|
||
EditorGUILayout.EndHorizontal();
|
||
break;
|
||
case "Scale Over Time":
|
||
var scaleOverTimeProperty = serializedObject.FindProperty("scaleOverTime");
|
||
var scaleOverTimeColor = Color.Lerp(Color.red, Color.green,
|
||
scaleOverTimeProperty.animationCurveValue.Evaluate(1));
|
||
EditorGUILayout.CurveField(scaleOverTimeProperty, scaleOverTimeColor, new Rect(0, 0, 1, 5f));
|
||
break;
|
||
case "Orthographic Scaling":
|
||
EditorGUILayout.PropertyField(serializedObject.FindProperty("defaultOrthographicSize"));
|
||
EditorGUILayout.PropertyField(serializedObject.FindProperty("maxOrthographicSize"));
|
||
EditorGUILayout.PropertyField(serializedObject.FindProperty("orthographicCamera"));
|
||
|
||
var noOrthographicCameraOverride = true;
|
||
foreach (var dn in DNPEditorInternal.damageNumbers)
|
||
if (dn.orthographicCamera != null)
|
||
{
|
||
noOrthographicCameraOverride = false;
|
||
break;
|
||
}
|
||
|
||
if (noOrthographicCameraOverride)
|
||
{
|
||
var overlayString = "Main Camera";
|
||
|
||
if (DNPEditorInternal.currentWidth < 404)
|
||
{
|
||
overlayString = "<size=11>Main Camera</size>";
|
||
|
||
if (DNPEditorInternal.currentWidth < 389) overlayString = "";
|
||
}
|
||
|
||
if (DNPEditorInternal.currentWidth > 293)
|
||
PropertyOverlay(DNPEditorInternal.CheckmarkString(true) + " " + overlayString +
|
||
" ");
|
||
}
|
||
else
|
||
{
|
||
GUI.color = new Color(1, 1, 1, 0.7f);
|
||
DNPEditorInternal.ScalingLabel(
|
||
"Only required if your <b>main camera</b> is not the orthographic camera.", 362);
|
||
GUI.color = Color.white;
|
||
}
|
||
|
||
break;
|
||
// Spam Control
|
||
case "Combination":
|
||
EditorGUILayout.BeginHorizontal();
|
||
EditorGUILayout.LabelField(" ", GUILayout.Width(9));
|
||
EditorGUILayout.PropertyField(serializedObject.FindProperty("combinationSettings"));
|
||
EditorGUILayout.EndHorizontal();
|
||
break;
|
||
case "Destruction":
|
||
EditorGUILayout.BeginHorizontal();
|
||
EditorGUILayout.LabelField(" ", GUILayout.Width(9));
|
||
EditorGUILayout.PropertyField(serializedObject.FindProperty("destructionSettings"));
|
||
EditorGUILayout.EndHorizontal();
|
||
break;
|
||
case "Collision":
|
||
EditorGUILayout.BeginHorizontal();
|
||
EditorGUILayout.LabelField(" ", GUILayout.Width(9));
|
||
EditorGUILayout.PropertyField(serializedObject.FindProperty("collisionSettings"));
|
||
EditorGUILayout.EndHorizontal();
|
||
break;
|
||
case "Push":
|
||
EditorGUILayout.BeginHorizontal();
|
||
EditorGUILayout.LabelField(" ", GUILayout.Width(9));
|
||
EditorGUILayout.PropertyField(serializedObject.FindProperty("pushSettings"));
|
||
EditorGUILayout.EndHorizontal();
|
||
break;
|
||
|
||
// Performance
|
||
case "Pooling":
|
||
EditorGUILayout.PropertyField(serializedObject.FindProperty("poolSize"));
|
||
EditorGUILayout.PropertyField(serializedObject.FindProperty("disableOnSceneLoad"));
|
||
break;
|
||
}
|
||
}
|
||
|
||
// Close Box
|
||
DNPEditorInternal.CloseBox(showProperties);
|
||
}
|
||
|
||
private void HandleTextProperty(SerializedProperty textField)
|
||
{
|
||
EditorGUI.BeginChangeCheck();
|
||
EditorGUILayout.BeginHorizontal();
|
||
EditorGUILayout.PropertyField(textField);
|
||
|
||
if (textField.stringValue.Length > 5)
|
||
{
|
||
var chars = textField.stringValue.ToCharArray();
|
||
var unicodeCheck = false;
|
||
var unicodeIndex = 0;
|
||
for (var i = 0; i < chars.Length; i++)
|
||
{
|
||
var c = chars[i];
|
||
|
||
if (c == '\\')
|
||
{
|
||
// Check if there is a unicode sequence
|
||
unicodeCheck = true;
|
||
unicodeIndex = i;
|
||
}
|
||
else
|
||
{
|
||
if (unicodeCheck)
|
||
{
|
||
if (i == unicodeIndex + 1)
|
||
{
|
||
if (char.ToLower(c) != 'u') unicodeCheck = false;
|
||
}
|
||
else if (i < unicodeIndex + 6)
|
||
{
|
||
var cInt = (int)c;
|
||
if (!char.IsNumber(c) && !(cInt > 96 && cInt < 103)) unicodeCheck = false;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if (unicodeCheck && unicodeIndex < chars.Length - 5)
|
||
if (GUILayout.Button("Unicode", GUILayout.Width(60)))
|
||
{
|
||
// Get hex code
|
||
var unicodeHex = "";
|
||
for (var i = unicodeIndex + 2; i < unicodeIndex + 6; i++) unicodeHex += chars[i];
|
||
var hexCode = int.Parse(unicodeHex, NumberStyles.HexNumber);
|
||
|
||
// Get unicode
|
||
var unicode = char.ConvertFromUtf32(hexCode);
|
||
|
||
// Combine
|
||
var newString = "";
|
||
for (var i = 0; i < unicodeIndex; i++) newString += chars[i];
|
||
newString += unicode;
|
||
for (var i = unicodeIndex + 6; i < chars.Length; i++) newString += chars[i];
|
||
|
||
// Assign
|
||
textField.stringValue = newString;
|
||
}
|
||
}
|
||
|
||
EditorGUILayout.EndHorizontal();
|
||
}
|
||
|
||
public static void ChangeShaderToOverlay(DamageNumber damageNumber)
|
||
{
|
||
damageNumber.GetReferencesIfNecessary();
|
||
var materials = damageNumber.GetSharedMaterials();
|
||
|
||
if (materials != null)
|
||
foreach (var mat in materials)
|
||
if (!mat.shader.name.EndsWith("verlay"))
|
||
{
|
||
var shader = Shader.Find(mat.shader.name + " Overlay");
|
||
if (shader == null) shader = Shader.Find("TextMeshPro/Distance Field - Overlay");
|
||
if (shader == null) shader = Shader.Find("TextMeshPro/Distance Field (Overlay)");
|
||
if (shader == null) shader = Shader.Find("TextMeshPro/Distance Field Overlay");
|
||
|
||
mat.shader = shader;
|
||
damageNumber.renderThroughWalls = false;
|
||
}
|
||
}
|
||
|
||
private bool FeatureButton(SerializedProperty property, string featureTitle)
|
||
{
|
||
// Get name for toggle button
|
||
var buttonName = property.hasMultipleDifferentValues ? "<b>− − −</b>" :
|
||
property.boolValue ? "<b> " + featureTitle + "</b>" : featureTitle;
|
||
|
||
var toggled = GUILayout.Button(buttonName, DNPEditorInternal.buttonStyle, GUILayout.Width(140));
|
||
|
||
if (toggled)
|
||
{
|
||
// Record changes
|
||
var objectsList = new List<Object>();
|
||
foreach (var targetObject in targets) objectsList.Add(targetObject);
|
||
foreach (var damageNumber in DNPEditorInternal.damageNumbers)
|
||
if (damageNumber != null)
|
||
{
|
||
damageNumber.GetReferencesIfNecessary();
|
||
foreach (var tmpText in damageNumber.GetTextMeshs())
|
||
if (tmpText != null)
|
||
objectsList.Add(tmpText);
|
||
}
|
||
|
||
var objectsArray = new Object[objectsList.Count];
|
||
for (var i = 0; i < objectsList.Count; i++) objectsArray[i] = objectsList[i];
|
||
Undo.RecordObjects(objectsArray, "Toggled " + featureTitle);
|
||
|
||
// Toggle feature
|
||
property.boolValue = !property.boolValue;
|
||
|
||
// Avoid Conflicts
|
||
if (property.boolValue)
|
||
switch (property.name)
|
||
{
|
||
case "enableDestruction":
|
||
serializedObject.FindProperty("enableCombination").boolValue = false;
|
||
break;
|
||
case "enableCombination":
|
||
serializedObject.FindProperty("enableDestruction").boolValue = false;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (property.boolValue || property.hasMultipleDifferentValues)
|
||
{
|
||
GUI.color = new Color(1, 1, 1, 0.8f);
|
||
GUI.Toolbar(GUILayoutUtility.GetLastRect(), 0, new[] { buttonName }, DNPEditorInternal.buttonStyle);
|
||
GUI.color = new Color(1, 1, 1, 1f);
|
||
|
||
return true;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
private void DisplayTextMain(bool isMesh)
|
||
{
|
||
EditorGUILayout.Space(2);
|
||
DNPEditorInternal.StartBox();
|
||
|
||
var editingPrefabPreview = DNPEditorInternal.EditingPrefabPreview(target);
|
||
if (editingPrefabPreview) GUI.enabled = false;
|
||
|
||
// Font
|
||
var mixedFontAssets = false;
|
||
TMP_FontAsset fontAsset = null;
|
||
|
||
foreach (var dn in DNPEditorInternal.damageNumbers)
|
||
{
|
||
dn.GetReferencesIfNecessary();
|
||
|
||
if (isMesh)
|
||
{
|
||
var tmp = dn.GetTextMesh();
|
||
|
||
if (fontAsset != null && tmp.font != null && tmp.font != fontAsset)
|
||
mixedFontAssets = true;
|
||
else
|
||
fontAsset = tmp.font;
|
||
}
|
||
else
|
||
{
|
||
foreach (var tmp in dn.GetTextMeshs())
|
||
if (fontAsset != null && tmp.font != null && tmp.font != fontAsset)
|
||
mixedFontAssets = true;
|
||
else
|
||
fontAsset = tmp.font;
|
||
}
|
||
}
|
||
|
||
EditorGUI.showMixedValue = mixedFontAssets;
|
||
EditorGUI.BeginChangeCheck();
|
||
var newFontAsset = (TMP_FontAsset)EditorGUILayout.ObjectField(
|
||
new GUIContent("Font", "The font used by text mesh pro."), fontAsset, typeof(TMP_FontAsset), false);
|
||
if (EditorGUI.EndChangeCheck())
|
||
{
|
||
foreach (var dn in DNPEditorInternal.damageNumbers)
|
||
{
|
||
Undo.RecordObjects(dn.GetTextMeshs(), "Changed font.");
|
||
|
||
foreach (var tmp in dn.GetTextMeshs()) tmp.font = newFontAsset;
|
||
}
|
||
|
||
DNPEditorInternal.ResetMaterials();
|
||
}
|
||
|
||
EditorGUI.showMixedValue = false;
|
||
|
||
// Color
|
||
var mixedColor = false;
|
||
var vertexColor = Color.white;
|
||
var firstColor = true;
|
||
foreach (var dn in DNPEditorInternal.damageNumbers)
|
||
foreach (var tmp in dn.GetTextMeshs())
|
||
if (firstColor)
|
||
{
|
||
firstColor = false;
|
||
vertexColor = tmp.color;
|
||
}
|
||
else
|
||
{
|
||
if (vertexColor != tmp.color) mixedColor = true;
|
||
}
|
||
|
||
EditorGUI.showMixedValue = mixedColor;
|
||
EditorGUI.BeginChangeCheck();
|
||
var newColor =
|
||
EditorGUILayout.ColorField(new GUIContent("Color", "The vertex color used by text mesh pro."),
|
||
vertexColor);
|
||
if (EditorGUI.EndChangeCheck())
|
||
foreach (var dn in DNPEditorInternal.damageNumbers)
|
||
{
|
||
Undo.RecordObjects(dn.GetTextMeshs(), "Changed color.");
|
||
|
||
foreach (var tmp in dn.GetTextMeshs()) tmp.color = newColor;
|
||
}
|
||
|
||
GUI.enabled = true;
|
||
|
||
// Info
|
||
DNPEditorInternal.Lines();
|
||
GUI.color = new Color(1, 1, 1, 0.7f);
|
||
if (editingPrefabPreview)
|
||
{
|
||
DNPEditorInternal.ScalingLabel("You need to <b>open</b> the <b>prefab</b> to access these settings.",
|
||
355);
|
||
DNPEditorInternal.OpenPrefabButton(target);
|
||
}
|
||
else
|
||
{
|
||
DNPEditorInternal.ScalingLabel("Check out the <b>TextMeshPro</b> component for more settings.", 355);
|
||
GUI.color = Color.white;
|
||
}
|
||
|
||
DNPEditorInternal.CloseBox();
|
||
}
|
||
|
||
private void DisplayMainSettings()
|
||
{
|
||
EditorGUILayout.Space(2);
|
||
DNPEditorInternal.StartBox();
|
||
|
||
var permanentProperty = serializedObject.FindProperty("permanent");
|
||
GUI.enabled = !permanentProperty.boolValue || permanentProperty.hasMultipleDifferentValues;
|
||
|
||
EditorGUILayout.BeginHorizontal();
|
||
|
||
var lifetimeProperty = serializedObject.FindProperty("lifetime");
|
||
EditorGUILayout.PropertyField(lifetimeProperty);
|
||
|
||
var notEnoughLifetime = false;
|
||
foreach (var dn in DNPEditorInternal.damageNumbers)
|
||
if (dn.lifetime < dn.durationFadeIn)
|
||
{
|
||
notEnoughLifetime = true;
|
||
break;
|
||
}
|
||
|
||
if (notEnoughLifetime)
|
||
PropertyOverlay("<color=#FF0000BB>Not enough time to fade in.</color>");
|
||
else
|
||
TimePropertyOverlay(lifetimeProperty.floatValue);
|
||
|
||
ResetButton("Lifetime");
|
||
|
||
EditorGUILayout.EndHorizontal();
|
||
|
||
GUI.enabled = true;
|
||
|
||
EditorGUILayout.BeginHorizontal();
|
||
var timescaleProperty = serializedObject.FindProperty("unscaledTime");
|
||
EditorGUILayout.PropertyField(timescaleProperty);
|
||
ResetButton("UnscaledTime");
|
||
EditorGUILayout.EndHorizontal();
|
||
GUI.enabled = true;
|
||
|
||
EditorGUILayout.BeginHorizontal();
|
||
EditorGUILayout.PropertyField(permanentProperty);
|
||
ResetButton("Permanent");
|
||
EditorGUILayout.EndHorizontal();
|
||
|
||
// Information
|
||
|
||
DNPEditorInternal.Lines();
|
||
GUI.color = new Color(1, 1, 1, 0.7f);
|
||
if (permanentProperty.boolValue)
|
||
DNPEditorInternal.Label("- Will not <b>fade out</b> on it's own.");
|
||
else
|
||
DNPEditorInternal.Label("- Will <b>fade out</b> after <b>" +
|
||
Mathf.Round(lifetimeProperty.floatValue * 10) * 0.1f + "</b> seconds.");
|
||
GUI.color = Color.white;
|
||
|
||
DNPEditorInternal.CloseBox();
|
||
}
|
||
|
||
private void DisplayFadeMain(string inOrOut)
|
||
{
|
||
EditorGUILayout.Space(2);
|
||
DNPEditorInternal.StartBox();
|
||
|
||
EditorGUILayout.BeginHorizontal();
|
||
|
||
var serializedProperty = serializedObject.FindProperty("durationFade" + inOrOut);
|
||
EditorGUILayout.PropertyField(serializedProperty,
|
||
new GUIContent("Duration", "The duration it takes to fade " + inOrOut.ToLower() + "."));
|
||
TimePropertyOverlay(serializedProperty.floatValue);
|
||
ResetButton("Fade " + inOrOut + " Main");
|
||
|
||
EditorGUILayout.EndHorizontal();
|
||
|
||
DNPEditorInternal.CloseBox();
|
||
}
|
||
|
||
private void DisplaySpamControlMain(bool isMesh)
|
||
{
|
||
EditorGUILayout.Space(2);
|
||
|
||
// Check if Spam Group is required
|
||
var requiresSpamGroup = false;
|
||
var hasSpamGroup = false;
|
||
var serializedProperty = serializedObject.FindProperty("spamGroup");
|
||
var combinationProperty = serializedObject.FindProperty("enableCombination");
|
||
var destructionProperty = serializedObject.FindProperty("enableDestruction");
|
||
var collisionProperty = serializedObject.FindProperty("enableCollision");
|
||
var pushProperty = serializedObject.FindProperty("enablePush");
|
||
if (combinationProperty.boolValue || combinationProperty.hasMultipleDifferentValues)
|
||
requiresSpamGroup = true;
|
||
if (destructionProperty.boolValue || destructionProperty.hasMultipleDifferentValues)
|
||
requiresSpamGroup = true;
|
||
if (collisionProperty.boolValue || collisionProperty.hasMultipleDifferentValues) requiresSpamGroup = true;
|
||
if (pushProperty.boolValue || pushProperty.hasMultipleDifferentValues) requiresSpamGroup = true;
|
||
if (requiresSpamGroup && serializedProperty.stringValue.Replace(" ", "") != "")
|
||
{
|
||
requiresSpamGroup = false;
|
||
hasSpamGroup = true;
|
||
}
|
||
|
||
DNPEditorInternal.StartBox(requiresSpamGroup ? new Color(1, 1f, 0.8f) : Color.white);
|
||
|
||
EditorGUILayout.BeginHorizontal();
|
||
|
||
EditorGUILayout.PropertyField(serializedProperty);
|
||
|
||
if (requiresSpamGroup) PropertyOverlay("<color=#FF0000BB>Required</color>");
|
||
|
||
ResetButton("Spam Control Main");
|
||
|
||
EditorGUILayout.EndHorizontal();
|
||
|
||
if (requiresSpamGroup)
|
||
{
|
||
DNPEditorInternal.Lines();
|
||
GUI.color = new Color(1, 1, 1, 0.7f);
|
||
DNPEditorInternal.ScalingLabel("This field is <b>required</b> by the features below.", 272);
|
||
}
|
||
else if (hasSpamGroup)
|
||
{
|
||
DNPEditorInternal.Lines();
|
||
GUI.color = new Color(1, 1, 1, 0.7f);
|
||
if (isMesh)
|
||
DNPEditorInternal.ScalingLabel(
|
||
"Damage numbers within the same <b>group</b> interact with each other.", 395);
|
||
else
|
||
DNPEditorInternal.ScalingLabel(
|
||
"Damage numbers with the same <b>group</b> & <b>parent</b> interact with each other.", 440);
|
||
}
|
||
|
||
DNPEditorInternal.CloseBox(requiresSpamGroup ? new Color(1, 1f, 0.7f) : Color.white);
|
||
}
|
||
|
||
private int TextPosition(int current)
|
||
{
|
||
// Change Position
|
||
EditorGUILayout.BeginHorizontal();
|
||
|
||
|
||
GUI.color = new Color(1, 1, 1, 0.7f);
|
||
GUI.color = Color.white;
|
||
|
||
var swapWith = GUILayout.Toolbar(current,
|
||
new[]
|
||
{
|
||
new GUIContent("←", "Move this text to the left."),
|
||
new GUIContent("→", "Move this text to the right."),
|
||
new GUIContent("↑", "Move this text to the top."),
|
||
new GUIContent("↓", "Move this text to the bottom.")
|
||
}, GUILayout.Width(DNPEditorInternal.currentWidth > 330 ? 90 : 0));
|
||
|
||
GUI.color = new Color(1, 1, 1, 0.7f);
|
||
GUILayout.Label(" | ", DNPEditorInternal.centerTextStyle, GUILayout.Width(10), GUILayout.Height(18));
|
||
GUI.color = Color.white;
|
||
EditorGUILayout.EndHorizontal();
|
||
|
||
return swapWith;
|
||
}
|
||
|
||
private void DisplayPerformanceMain()
|
||
{
|
||
EditorGUILayout.Space(4);
|
||
|
||
// Delays
|
||
DNPEditorInternal.StartBox();
|
||
|
||
EditorGUILayout.BeginHorizontal();
|
||
DisplayDelay("updateDelay", "Update Delay", "The delay between updates.\nGreatly affects performance.");
|
||
ResetButton("Update Delay");
|
||
EditorGUILayout.EndHorizontal();
|
||
|
||
DNPEditorInternal.CloseBox();
|
||
}
|
||
|
||
private void DisplayPerformanceHints()
|
||
{
|
||
EditorGUILayout.Space(4);
|
||
|
||
DNPEditorInternal.StartBox();
|
||
|
||
GUI.color = new Color(1, 1, 1, 0.7f);
|
||
|
||
DNPEditorInternal.Label("<b><size=13>Performance Hints:</size></b>");
|
||
|
||
EditorGUILayout.Space(5);
|
||
|
||
DNPEditorInternal.ScalingLabel("Always make sure to enable <b>Pooling</b>.", 1);
|
||
DNPEditorInternal.ScalingLabel("You can also decrease the <b>Update FPS</b>.", 261);
|
||
DNPEditorInternal.ScalingLabel(
|
||
"Enabling <b>Combination</b> and <b>Destruction</b> also boosts performance.", 398);
|
||
DNPEditorInternal.ScalingLabel("You can find those features in the <b>Spam Control</b> section.", 350);
|
||
|
||
GUI.color = Color.white;
|
||
|
||
DNPEditorInternal.CloseBox();
|
||
}
|
||
|
||
private void DisplayMovementHints(bool isMesh)
|
||
{
|
||
if (!isMesh)
|
||
{
|
||
EditorGUILayout.Space(4);
|
||
|
||
DNPEditorInternal.StartBox();
|
||
|
||
GUI.color = new Color(1, 1, 1, 0.7f);
|
||
|
||
DNPEditorInternal.Label("<b><size=13>GUI Hints:</size></b>");
|
||
|
||
EditorGUILayout.Space(5);
|
||
|
||
DNPEditorInternal.ScalingLabel("The <b>GUI</b> version handles movement in <b>anchored</b> position.",
|
||
363);
|
||
DNPEditorInternal.ScalingLabel(
|
||
"An <b>offset</b> or <b>velocity</b> of <b>1</b> equals <b>100</b> in <b>anchored</b> space.",
|
||
352f);
|
||
DNPEditorInternal.ScalingLabel(
|
||
"This <b>x100</b> conversion is for keeping values <b>small</b> and <b>consistent</b>.", 399f);
|
||
|
||
GUI.color = Color.white;
|
||
|
||
DNPEditorInternal.CloseBox();
|
||
}
|
||
}
|
||
|
||
private void DisplaySpamControlHints(bool isMesh)
|
||
{
|
||
if (!isMesh)
|
||
{
|
||
EditorGUILayout.Space(4);
|
||
|
||
DNPEditorInternal.StartBox();
|
||
|
||
GUI.color = new Color(1, 1, 1, 0.7f);
|
||
|
||
DNPEditorInternal.Label("<b><size=13>GUI Hints:</size></b>");
|
||
|
||
EditorGUILayout.Space(5);
|
||
|
||
DNPEditorInternal.ScalingLabel("The <b>GUI</b> version handles everything in <b>anchored</b> position.",
|
||
363);
|
||
DNPEditorInternal.ScalingLabel(
|
||
"A <b>distance</b> or <b>radius</b> of <b>1</b> equals <b>100</b> in <b>anchored</b> space.", 358f);
|
||
DNPEditorInternal.ScalingLabel(
|
||
"This <b>x100</b> conversion is for keeping values <b>small</b> and <b>consistent</b>.", 399f);
|
||
|
||
GUI.color = Color.white;
|
||
|
||
DNPEditorInternal.CloseBox();
|
||
}
|
||
}
|
||
|
||
private void DisplayDelay(string propertyName, string displayName, string displayTooltip)
|
||
{
|
||
// Property
|
||
var property = serializedObject.FindProperty(propertyName);
|
||
|
||
// Delay
|
||
EditorGUILayout.BeginHorizontal();
|
||
EditorGUILayout.PropertyField(property, new GUIContent(displayName, displayTooltip));
|
||
|
||
// Delay Overlay
|
||
string overlayContent;
|
||
if (property.hasMultipleDifferentValues)
|
||
{
|
||
overlayContent = "";
|
||
}
|
||
else
|
||
{
|
||
if (property.floatValue > 0)
|
||
{
|
||
if (DNPEditorInternal.currentWidth < 400f)
|
||
overlayContent = "s";
|
||
else
|
||
overlayContent = "Delay";
|
||
}
|
||
else
|
||
{
|
||
overlayContent = "No Delay";
|
||
}
|
||
}
|
||
|
||
PropertyOverlay(overlayContent);
|
||
|
||
GUI.color = new Color(1, 1, 1, 0.5f);
|
||
EditorGUILayout.LabelField("➜", DNPEditorInternal.centerTextStyle,
|
||
GUILayout.Width(DNPEditorInternal.currentWidth > 334 ? 15 : 0));
|
||
|
||
GUI.color = Color.white;
|
||
|
||
if (property.hasMultipleDifferentValues)
|
||
{
|
||
GUI.enabled = false;
|
||
GUILayout.TextField(" - - - ", GUILayout.Width(100));
|
||
GUI.enabled = true;
|
||
}
|
||
else
|
||
{
|
||
if (property.floatValue > 0.10001f) GUI.color = new Color(1f, 1f, 0.7f, 1f);
|
||
|
||
var currentFPS = property.floatValue > 0 ? Mathf.RoundToInt(1f / property.floatValue) : 0;
|
||
|
||
|
||
var fpsWidth = 90;
|
||
if (DNPEditorInternal.currentWidth < 400)
|
||
fpsWidth = (int)Mathf.Clamp(DNPEditorInternal.currentWidth - 300, 50, 90);
|
||
|
||
var newFPS = EditorGUILayout.IntField(currentFPS,
|
||
GUILayout.Width(DNPEditorInternal.currentWidth > 294 ? fpsWidth : 0));
|
||
|
||
if (currentFPS != newFPS)
|
||
{
|
||
if (newFPS > 0)
|
||
property.floatValue = Mathf.Round(100000f / newFPS) * 0.00001f;
|
||
else if (newFPS <= 0) property.floatValue = 0f;
|
||
}
|
||
}
|
||
|
||
EditorGUILayout.EndHorizontal();
|
||
|
||
// FPS Overlay
|
||
GUI.color = new Color(1, 1, 1, 0.7f);
|
||
if (property.hasMultipleDifferentValues)
|
||
{
|
||
overlayContent = "";
|
||
}
|
||
else
|
||
{
|
||
if (property.floatValue > 0)
|
||
{
|
||
overlayContent = "FPS";
|
||
}
|
||
else
|
||
{
|
||
if (DNPEditorInternal.currentWidth < 400)
|
||
overlayContent = "";
|
||
else
|
||
overlayContent = "Every Frame";
|
||
}
|
||
}
|
||
|
||
PropertyOverlay(DNPEditorInternal.currentWidth > 310 ? overlayContent : "");
|
||
}
|
||
|
||
private void ResetButton(string category)
|
||
{
|
||
var resetButton = new GUIContent();
|
||
resetButton.text = "R";
|
||
resetButton.tooltip = "Reset this feature.";
|
||
|
||
if (GUILayout.Button(resetButton, GUILayout.Width(21)))
|
||
{
|
||
EditorGUIUtility.keyboardControl = EditorGUIUtility.hotControl = 0;
|
||
ResetCategory(category);
|
||
}
|
||
}
|
||
|
||
private void ResetCategory(string category)
|
||
{
|
||
Undo.RecordObject(target, "Reset " + category + " settings.");
|
||
|
||
foreach (var dn in DNPEditorInternal.damageNumbers)
|
||
// Reset Feature
|
||
switch (category)
|
||
{
|
||
// Main
|
||
case "Lifetime":
|
||
dn.lifetime = 2f;
|
||
break;
|
||
case "Permanent":
|
||
dn.permanent = false;
|
||
break;
|
||
case "UnscaledTime":
|
||
dn.unscaledTime = false;
|
||
break;
|
||
case "3D Game":
|
||
dn.faceCameraView = true;
|
||
dn.renderThroughWalls = true;
|
||
dn.consistentScreenSize = false;
|
||
dn.distanceScalingSettings = new DistanceScalingSettings(0);
|
||
dn.cameraOverride = null;
|
||
break;
|
||
|
||
// Text Content
|
||
case "Number":
|
||
dn.number = 1;
|
||
dn.numberSettings = new TextSettings(0);
|
||
dn.digitSettings = new DigitSettings(0);
|
||
break;
|
||
case "Left Text":
|
||
dn.leftText = "";
|
||
dn.leftTextSettings = new TextSettings(0f);
|
||
break;
|
||
case "Right Text":
|
||
dn.rightText = "";
|
||
dn.rightTextSettings = new TextSettings(0f);
|
||
break;
|
||
case "Top Text":
|
||
dn.topText = "";
|
||
dn.topTextSettings = new TextSettings(0f);
|
||
break;
|
||
case "Bottom Text":
|
||
dn.bottomText = "";
|
||
dn.bottomTextSettings = new TextSettings(0f);
|
||
break;
|
||
case "Color By Number":
|
||
dn.colorByNumberSettings = new ColorByNumberSettings(0f);
|
||
break;
|
||
|
||
// Movement
|
||
case "Lerp":
|
||
dn.lerpSettings = new LerpSettings(0);
|
||
break;
|
||
case "Velocity":
|
||
dn.velocitySettings = new VelocitySettings(0);
|
||
break;
|
||
case "Shaking":
|
||
dn.shakeSettings = new ShakeSettings(new Vector2(0.005f, 0.005f));
|
||
break;
|
||
case "Following":
|
||
dn.followedTarget = null;
|
||
dn.followSettings = new FollowSettings(0);
|
||
break;
|
||
|
||
// Fade In
|
||
case "Fade In Main":
|
||
dn.durationFadeIn = 0.2f;
|
||
break;
|
||
case "Offset In":
|
||
dn.offsetFadeIn = new Vector2(0.5f, 0);
|
||
break;
|
||
case "Scale In":
|
||
dn.scaleFadeIn = new Vector2(2f, 2f);
|
||
break;
|
||
case "Shake In":
|
||
dn.shakeOffsetFadeIn = new Vector2(0f, 1.5f);
|
||
dn.shakeFrequencyFadeIn = 4f;
|
||
break;
|
||
case "Cross Scale In":
|
||
dn.crossScaleFadeIn = new Vector2(1f, 1.5f);
|
||
break;
|
||
|
||
// Fade Out
|
||
case "Fade Out Main":
|
||
dn.durationFadeOut = 0.2f;
|
||
break;
|
||
case "Offset Out":
|
||
dn.enableOffsetFadeOut = true;
|
||
dn.offsetFadeOut = new Vector2(0.5f, 0);
|
||
break;
|
||
case "Scale Out":
|
||
dn.scaleFadeOut = new Vector2(2f, 2f);
|
||
break;
|
||
case "Shake Out":
|
||
dn.shakeOffsetFadeOut = new Vector2(0f, 1.5f);
|
||
dn.shakeFrequencyFadeOut = 4f;
|
||
break;
|
||
case "Cross Scale Out":
|
||
dn.crossScaleFadeOut = new Vector2(1f, 1.5f);
|
||
break;
|
||
|
||
// Rotation & Scale
|
||
case "Start Rotation":
|
||
dn.minRotation = -4;
|
||
dn.maxRotation = 4;
|
||
break;
|
||
case "Rotate Over Time":
|
||
dn.minRotationSpeed = -15f;
|
||
dn.maxRotationSpeed = 15;
|
||
dn.rotateOverTime = new AnimationCurve(new Keyframe(0, 1), new Keyframe(0.4f, 1),
|
||
new Keyframe(0.8f, 0), new Keyframe(1, 0));
|
||
break;
|
||
case "Scale By Number":
|
||
dn.scaleByNumberSettings = new ScaleByNumberSettings(0);
|
||
break;
|
||
case "Scale Over Time":
|
||
dn.scaleOverTime = new AnimationCurve(new Keyframe(0, 1), new Keyframe(1, 0.7f));
|
||
break;
|
||
case "Orthographic Scaling":
|
||
dn.defaultOrthographicSize = 5f;
|
||
dn.maxOrthographicSize = 1.5f;
|
||
dn.orthographicCamera = null;
|
||
break;
|
||
|
||
// Spam Control
|
||
case "Spam Control Main":
|
||
dn.spamGroup = "";
|
||
break;
|
||
case "Combination":
|
||
dn.combinationSettings = new CombinationSettings(0);
|
||
break;
|
||
case "Destruction":
|
||
dn.destructionSettings = new DestructionSettings(0);
|
||
break;
|
||
case "Collision":
|
||
dn.collisionSettings = new CollisionSettings(0);
|
||
break;
|
||
case "Push":
|
||
dn.pushSettings = new PushSettings(0);
|
||
break;
|
||
|
||
// Performance
|
||
case "Pooling":
|
||
dn.poolSize = 50;
|
||
break;
|
||
case "Update Delay":
|
||
dn.updateDelay = 0.0125f;
|
||
break;
|
||
}
|
||
}
|
||
|
||
private void TimePropertyOverlay(float seconds, string zeroString = "Instantly")
|
||
{
|
||
if (seconds > 0)
|
||
PropertyOverlay("Seconds");
|
||
else
|
||
PropertyOverlay(zeroString);
|
||
}
|
||
|
||
private void PropertyOverlay(string text)
|
||
{
|
||
GUI.color = new Color(1, 1, 1, 0.7f);
|
||
GUI.Label(GUILayoutUtility.GetLastRect(), text + " ", DNPEditorInternal.rightTextStyle);
|
||
GUI.color = Color.white;
|
||
}
|
||
|
||
#endregion
|
||
}
|
||
}
|
||
|
||
#endif |