Move scripts

This commit is contained in:
mob-sakai
2019-01-17 20:15:40 +09:00
parent 9f53decd10
commit ad029f6537
8 changed files with 8 additions and 0 deletions

8
Scripts/Editor.meta Normal file
View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: f479867169fb04929b98c38e646b83c5
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,533 @@
using UnityEditor;
using UnityEditor.UI;
using UnityEngine;
using System.Collections.Generic;
using System.Linq;
using UnityEditor.IMGUI.Controls;
using System;
using System.Reflection;
namespace Coffee.UIExtensions
{
[CustomEditor (typeof (UIParticle))]
[CanEditMultipleObjects]
public class UIParticleEditor : GraphicEditor
{
//################################
// Constant or Static Members.
//################################
static readonly GUIContent s_ContentParticleMaterial = new GUIContent ("Particle Material", "The material for rendering particles");
static readonly GUIContent s_ContentTrailMaterial = new GUIContent ("Trail Material", "The material for rendering particle trails");
static readonly List<ParticleSystem> s_ParticleSystems = new List<ParticleSystem> ();
static readonly Matrix4x4 s_ArcHandleOffsetMatrix = Matrix4x4.TRS (Vector3.zero, Quaternion.AngleAxis (90f, Vector3.right) * Quaternion.AngleAxis (90f, Vector3.up), Vector3.one);
static readonly Dictionary<string, MethodInfo> s_InternalMethods = new Dictionary<string, MethodInfo> ();
static readonly Color s_GizmoColor = new Color (1f, 0.7f, 0.7f, 0.9f);
static readonly Color s_ShapeGizmoThicknessTint = new Color (0.7f, 0.7f, 0.7f, 1.0f);
static Material s_Material;
//################################
// Public/Protected Members.
//################################
/// <summary>
/// This function is called when the object becomes enabled and active.
/// </summary>
protected override void OnEnable ()
{
base.OnEnable ();
_spParticleSystem = serializedObject.FindProperty ("m_ParticleSystem");
_spTrailParticle = serializedObject.FindProperty ("m_TrailParticle");
_spScale = serializedObject.FindProperty ("m_Scale");
_spIgnoreParent = serializedObject.FindProperty ("m_IgnoreParent");
if (!s_Material)
{
s_Material = Call<Material> (typeof (Material), "GetDefaultMaterial");
}
_particles = targets.Cast<UIParticle> ().ToArray ();
}
/// <summary>
/// Implement this function to make a custom inspector.
/// </summary>
public override void OnInspectorGUI ()
{
serializedObject.Update ();
EditorGUILayout.PropertyField (_spParticleSystem);
EditorGUI.indentLevel++;
var ps = _spParticleSystem.objectReferenceValue as ParticleSystem;
if (ps)
{
var pr = ps.GetComponent<ParticleSystemRenderer> ();
var sp = new SerializedObject (pr).FindProperty ("m_Materials");
EditorGUILayout.PropertyField (sp.GetArrayElementAtIndex (0), s_ContentParticleMaterial);
EditorGUILayout.PropertyField (sp.GetArrayElementAtIndex (1), s_ContentTrailMaterial);
sp.serializedObject.ApplyModifiedProperties ();
if (!Application.isPlaying && pr.enabled)
{
EditorGUILayout.HelpBox ("ParticleSystemRenderer will be disable on playing.", MessageType.Info);
}
}
EditorGUI.indentLevel--;
EditorGUI.BeginDisabledGroup (true);
EditorGUILayout.PropertyField (_spTrailParticle);
EditorGUI.EndDisabledGroup ();
var current = target as UIParticle;
EditorGUILayout.PropertyField (_spIgnoreParent);
EditorGUI.BeginDisabledGroup (!current.isRoot);
EditorGUILayout.PropertyField (_spScale);
EditorGUI.EndDisabledGroup ();
current.GetComponentsInChildren<ParticleSystem> (true, s_ParticleSystems);
if (s_ParticleSystems.Any (x => x.GetComponent<UIParticle> () == null))
{
GUILayout.BeginHorizontal ();
EditorGUILayout.HelpBox ("There are child ParticleSystems that does not have a UIParticle component.\nAdd UIParticle component to them.", MessageType.Warning);
GUILayout.BeginVertical ();
if (GUILayout.Button ("Fix"))
{
foreach (var p in s_ParticleSystems.Where (x => !x.GetComponent<UIParticle> ()))
{
p.gameObject.AddComponent<UIParticle> ();
}
}
GUILayout.EndVertical ();
GUILayout.EndHorizontal ();
}
s_ParticleSystems.Clear ();
serializedObject.ApplyModifiedProperties ();
}
//################################
// Private Members.
//################################
SerializedProperty _spParticleSystem;
SerializedProperty _spTrailParticle;
SerializedProperty _spScale;
SerializedProperty _spIgnoreParent;
UIParticle [] _particles;
ArcHandle _arcHandle = new ArcHandle ();
BoxBoundsHandle _boxBoundsHandle = new BoxBoundsHandle ();
SphereBoundsHandle _sphereBoundsHandle = new SphereBoundsHandle ();
Mesh _spriteMesh;
static T Call<T> (Type type, string method, params object [] args)
{
MethodInfo mi;
if (!s_InternalMethods.TryGetValue (method, out mi))
{
mi = type.GetMethod (method, BindingFlags.Static | BindingFlags.NonPublic);
s_InternalMethods.Add (method, mi);
}
return (T)mi.Invoke (null, args);
}
void OnSceneGUI ()
{
Color origCol = Handles.color;
Handles.color = s_GizmoColor;
Matrix4x4 orgMatrix = Handles.matrix;
EditorGUI.BeginChangeCheck ();
foreach (UIParticle uip in _particles)
{
ParticleSystem ps = uip.cachedParticleSystem;
if (!ps || !uip.canvas)
{
continue;
}
var shapeModule = ps.shape;
var mainModule = ps.main;
ParticleSystemShapeType type = shapeModule.shapeType;
Matrix4x4 transformMatrix = new Matrix4x4 ();
if (mainModule.scalingMode == ParticleSystemScalingMode.Local)
{
transformMatrix.SetTRS (ps.transform.position, ps.transform.rotation, ps.transform.localScale);
}
else if (mainModule.scalingMode == ParticleSystemScalingMode.Hierarchy)
{
transformMatrix = ps.transform.localToWorldMatrix;
}
else
{
transformMatrix.SetTRS (ps.transform.position, ps.transform.rotation, ps.transform.lossyScale);
}
bool isBox = (type == ParticleSystemShapeType.Box || type == ParticleSystemShapeType.BoxShell || type == ParticleSystemShapeType.BoxEdge || type == ParticleSystemShapeType.Rectangle);
Vector3 emitterScale = isBox ? Vector3.one : shapeModule.scale;
Matrix4x4 emitterMatrix = Matrix4x4.TRS (shapeModule.position, Quaternion.Euler (shapeModule.rotation), emitterScale);
transformMatrix *= emitterMatrix;
Handles.matrix = transformMatrix;
if(uip.canvas.renderMode == RenderMode.ScreenSpaceOverlay || ps.main.scalingMode == ParticleSystemScalingMode.Hierarchy)
{
Handles.matrix = Handles.matrix * Matrix4x4.Scale (Vector3.one * uip.scale);
}
else
{
Handles.matrix = Handles.matrix * Matrix4x4.Scale (uip.canvas.rootCanvas.transform.localScale * uip.scale);
}
if (type == ParticleSystemShapeType.Sphere)
{
// Thickness
Handles.color *= s_ShapeGizmoThicknessTint;
EditorGUI.BeginChangeCheck ();
//float radiusThickness = Handles.DoSimpleRadiusHandle (Quaternion.identity, Vector3.zero, shapeModule.radius * (1.0f - shapeModule.radiusThickness), false, shapeModule.arc);
float radiusThickness = Handles.RadiusHandle (Quaternion.identity, Vector3.zero, shapeModule.radius * (1.0f - shapeModule.radiusThickness), false);
if (EditorGUI.EndChangeCheck ())
{
Undo.RecordObject (ps, "Sphere Thickness Handle Change");
shapeModule.radiusThickness = 1.0f - (radiusThickness / shapeModule.radius);
}
// Sphere
Handles.color = s_GizmoColor;
EditorGUI.BeginChangeCheck ();
//float radius = Handles.DoSimpleRadiusHandle (Quaternion.identity, Vector3.zero, shapeModule.radius, false, shapeModule.arc);
float radius = Handles.RadiusHandle (Quaternion.identity, Vector3.zero, shapeModule.radius, false);
if (EditorGUI.EndChangeCheck ())
{
Undo.RecordObject (ps, "Sphere Handle Change");
shapeModule.radius = radius;
}
// Texture
//Matrix4x4 textureTransform = transformMatrix * Matrix4x4.TRS (Vector3.zero, Quaternion.identity, Vector3.one * shapeModule.radius * 2.0f);
//OnSceneViewTextureGUI (shapeModule, s_SphereMesh, false, s_SphereTextureMaterial, textureTransform);
}
else if (type == ParticleSystemShapeType.Circle)
{
// Thickness
EditorGUI.BeginChangeCheck ();
_arcHandle.angle = shapeModule.arc;
_arcHandle.radius = shapeModule.radius * (1.0f - shapeModule.radiusThickness);
_arcHandle.SetColorWithRadiusHandle (s_ShapeGizmoThicknessTint, 0f);
_arcHandle.angleHandleColor = Color.clear;
using (new Handles.DrawingScope (Handles.matrix * s_ArcHandleOffsetMatrix))
_arcHandle.DrawHandle ();
if (EditorGUI.EndChangeCheck ())
{
Undo.RecordObject (ps, "Circle Thickness Handle Change");
shapeModule.radiusThickness = 1.0f - (_arcHandle.radius / shapeModule.radius);
}
// Circle
EditorGUI.BeginChangeCheck ();
_arcHandle.radius = shapeModule.radius;
_arcHandle.SetColorWithRadiusHandle (Color.white, 0f);
using (new Handles.DrawingScope (Handles.matrix * s_ArcHandleOffsetMatrix))
_arcHandle.DrawHandle ();
if (EditorGUI.EndChangeCheck ())
{
Undo.RecordObject (ps, "Circle Handle Change");
shapeModule.radius = _arcHandle.radius;
shapeModule.arc = _arcHandle.angle;
}
// Texture
//Matrix4x4 textureTransform = transformMatrix * Matrix4x4.TRS (Vector3.zero, Quaternion.Euler (90.0f, 0.0f, 180.0f), Vector3.one * shapeModule.radius * 2.0f);
//OnSceneViewTextureGUI (shapeModule, s_CircleMesh, true, s_TextureMaterial, textureTransform);
}
else if (type == ParticleSystemShapeType.Hemisphere)
{
// Thickness
Handles.color *= s_ShapeGizmoThicknessTint;
EditorGUI.BeginChangeCheck ();
//float radiusThickness = Handles.DoSimpleRadiusHandle (Quaternion.identity, Vector3.zero, shapeModule.radius * (1.0f - shapeModule.radiusThickness), true, shapeModule.arc);
//float radiusThickness = Call<float> (typeof (Handles), "DoSimpleRadiusHandle", Quaternion.identity, Vector3.zero, shapeModule.radius * (1.0f - shapeModule.radiusThickness), true, shapeModule.arc);
float radiusThickness = Handles.RadiusHandle (Quaternion.identity, Vector3.zero, shapeModule.radius * (1.0f - shapeModule.radiusThickness), true);
if (EditorGUI.EndChangeCheck ())
{
Undo.RecordObject (ps, "Hemisphere Thickness Handle Change");
shapeModule.radiusThickness = 1.0f - (radiusThickness / shapeModule.radius);
}
// Hemisphere
Handles.color = s_GizmoColor;
EditorGUI.BeginChangeCheck ();
//float radius = Handles.DoSimpleRadiusHandle (Quaternion.identity, Vector3.zero, shapeModule.radius, true, shapeModule.arc);
float radius = Handles.RadiusHandle (Quaternion.identity, Vector3.zero, shapeModule.radius, true);
if (EditorGUI.EndChangeCheck ())
{
Undo.RecordObject (ps, "Hemisphere Handle Change");
shapeModule.radius = radius;
}
// Texture
//Matrix4x4 textureTransform = transformMatrix * Matrix4x4.TRS (Vector3.zero, Quaternion.identity, Vector3.one * shapeModule.radius * 2.0f);
//OnSceneViewTextureGUI (shapeModule, s_HemisphereMesh, false, s_SphereTextureMaterial, textureTransform);
}
else if (type == ParticleSystemShapeType.Cone)
{
// Thickness
Handles.color *= s_ShapeGizmoThicknessTint;
EditorGUI.BeginChangeCheck ();
float angleThickness = Mathf.Lerp (shapeModule.angle, 0.0f, shapeModule.radiusThickness);
Vector3 radiusThicknessAngleRange = new Vector3 (shapeModule.radius * (1.0f - shapeModule.radiusThickness), angleThickness, mainModule.startSpeedMultiplier);
//radiusThicknessAngleRange = Handles.ConeFrustrumHandle (Quaternion.identity, Vector3.zero, radiusThicknessAngleRange, Handles.ConeHandles.Radius);
#if UNITY_2018_3_OR_NEWER
radiusThicknessAngleRange = Call<Vector3> (typeof (Handles), "ConeFrustrumHandle", Quaternion.identity, Vector3.zero, radiusThicknessAngleRange, 1);
#else
radiusThicknessAngleRange = Call<Vector3> (typeof (Handles), "ConeFrustrumHandle", Quaternion.identity, Vector3.zero, radiusThicknessAngleRange);
#endif
if (EditorGUI.EndChangeCheck ())
{
Undo.RecordObject (ps, "Cone Thickness Handle Change");
shapeModule.radiusThickness = 1.0f - (radiusThicknessAngleRange.x / shapeModule.radius);
}
// Cone
Handles.color = s_GizmoColor;
EditorGUI.BeginChangeCheck ();
Vector3 radiusAngleRange = new Vector3 (shapeModule.radius, shapeModule.angle, mainModule.startSpeedMultiplier);
//radiusAngleRange = Handles.ConeFrustrumHandle (Quaternion.identity, Vector3.zero, radiusAngleRange);
#if UNITY_2018_3_OR_NEWER
radiusAngleRange = Call<Vector3> (typeof (Handles), "ConeFrustrumHandle", Quaternion.identity, Vector3.zero, radiusAngleRange, 7);
#else
radiusAngleRange = Call<Vector3> (typeof (Handles), "ConeFrustrumHandle", Quaternion.identity, Vector3.zero, radiusAngleRange);
#endif
if (EditorGUI.EndChangeCheck ())
{
Undo.RecordObject (ps, "Cone Handle Change");
shapeModule.radius = radiusAngleRange.x;
shapeModule.angle = radiusAngleRange.y;
mainModule.startSpeedMultiplier = radiusAngleRange.z;
}
// Texture
//Matrix4x4 textureTransform = transformMatrix * Matrix4x4.TRS (Vector3.zero, Quaternion.Euler (90.0f, 0.0f, 180.0f), Vector3.one * shapeModule.radius * 2.0f);
//OnSceneViewTextureGUI (shapeModule, s_CircleMesh, true, s_TextureMaterial, textureTransform);
}
else if (type == ParticleSystemShapeType.ConeVolume)
{
// Thickness
Handles.color *= s_ShapeGizmoThicknessTint;
EditorGUI.BeginChangeCheck ();
float angleThickness = Mathf.Lerp (shapeModule.angle, 0.0f, shapeModule.radiusThickness);
Vector3 radiusThicknessAngleLength = new Vector3 (shapeModule.radius * (1.0f - shapeModule.radiusThickness), angleThickness, shapeModule.length);
//radiusThicknessAngleLength = Handles.ConeFrustrumHandle (Quaternion.identity, Vector3.zero, radiusThicknessAngleLength, Handles.ConeHandles.Radius);
#if UNITY_2018_3_OR_NEWER
radiusThicknessAngleLength = Call<Vector3> (typeof (Handles), "ConeFrustrumHandle", Quaternion.identity, Vector3.zero, radiusThicknessAngleLength, 1);
#else
radiusThicknessAngleLength = Call<Vector3> (typeof (Handles), "ConeFrustrumHandle", Quaternion.identity, Vector3.zero, radiusThicknessAngleLength);
#endif
if (EditorGUI.EndChangeCheck ())
{
Undo.RecordObject (ps, "Cone Volume Thickness Handle Change");
shapeModule.radiusThickness = 1.0f - (radiusThicknessAngleLength.x / shapeModule.radius);
}
// Cone
Handles.color = s_GizmoColor;
EditorGUI.BeginChangeCheck ();
Vector3 radiusAngleLength = new Vector3 (shapeModule.radius, shapeModule.angle, shapeModule.length);
//radiusAngleLength = Handles.ConeFrustrumHandle (Quaternion.identity, Vector3.zero, radiusAngleLength);
#if UNITY_2018_3_OR_NEWER
radiusAngleLength = Call<Vector3> (typeof (Handles), "ConeFrustrumHandle", Quaternion.identity, Vector3.zero, radiusAngleLength, 7);
#else
radiusAngleLength = Call<Vector3> (typeof (Handles), "ConeFrustrumHandle", Quaternion.identity, Vector3.zero, radiusAngleLength);
#endif
if (EditorGUI.EndChangeCheck ())
{
Undo.RecordObject (ps, "Cone Volume Handle Change");
shapeModule.radius = radiusAngleLength.x;
shapeModule.angle = radiusAngleLength.y;
shapeModule.length = radiusAngleLength.z;
}
// Texture
//Matrix4x4 textureTransform = transformMatrix * Matrix4x4.TRS (Vector3.zero, Quaternion.Euler (90.0f, 0.0f, 180.0f), Vector3.one * shapeModule.radius * 2.0f);
//OnSceneViewTextureGUI (shapeModule, s_CircleMesh, true, s_TextureMaterial, textureTransform);
}
else if (type == ParticleSystemShapeType.Box || type == ParticleSystemShapeType.BoxShell || type == ParticleSystemShapeType.BoxEdge)
{
EditorGUI.BeginChangeCheck ();
_boxBoundsHandle.center = Vector3.zero;
_boxBoundsHandle.size = shapeModule.scale;
_boxBoundsHandle.DrawHandle ();
if (EditorGUI.EndChangeCheck ())
{
Undo.RecordObject (ps, "Box Handle Change");
shapeModule.scale = _boxBoundsHandle.size;
}
//Matrix4x4 textureTransform = transformMatrix * Matrix4x4.TRS (new Vector3 (0.0f, 0.0f, -m_BoxBoundsHandle.size.z * 0.5f), Quaternion.identity, m_BoxBoundsHandle.size);
//OnSceneViewTextureGUI (shapeModule, s_QuadMesh, true, s_TextureMaterial, textureTransform);
}
else if (type == ParticleSystemShapeType.Donut)
{
// Radius
EditorGUI.BeginChangeCheck ();
_arcHandle.radius = shapeModule.radius;
_arcHandle.angle = shapeModule.arc;
_arcHandle.SetColorWithRadiusHandle (Color.white, 0f);
_arcHandle.wireframeColor = Color.clear;
using (new Handles.DrawingScope (Handles.matrix * s_ArcHandleOffsetMatrix))
_arcHandle.DrawHandle ();
if (EditorGUI.EndChangeCheck ())
{
Undo.RecordObject (ps, "Donut Handle Change");
shapeModule.radius = _arcHandle.radius;
shapeModule.arc = _arcHandle.angle;
}
// Donut extents
using (new Handles.DrawingScope (Handles.matrix * s_ArcHandleOffsetMatrix))
{
float excessAngle = shapeModule.arc % 360f;
float angle = Mathf.Abs (shapeModule.arc) >= 360f ? 360f : excessAngle;
Handles.DrawWireArc (new Vector3 (0.0f, shapeModule.donutRadius, 0.0f), Vector3.up, Vector3.forward, angle, shapeModule.radius);
Handles.DrawWireArc (new Vector3 (0.0f, -shapeModule.donutRadius, 0.0f), Vector3.up, Vector3.forward, angle, shapeModule.radius);
Handles.DrawWireArc (Vector3.zero, Vector3.up, Vector3.forward, angle, shapeModule.radius + shapeModule.donutRadius);
Handles.DrawWireArc (Vector3.zero, Vector3.up, Vector3.forward, angle, shapeModule.radius - shapeModule.donutRadius);
if (shapeModule.arc != 360.0f)
{
Quaternion arcRotation = Quaternion.AngleAxis (shapeModule.arc, Vector3.up);
Vector3 capCenter = arcRotation * Vector3.forward * shapeModule.radius;
Handles.DrawWireDisc (capCenter, arcRotation * Vector3.right, shapeModule.donutRadius);
}
}
// Donut thickness
_sphereBoundsHandle.axes = PrimitiveBoundsHandle.Axes.X | PrimitiveBoundsHandle.Axes.Y;
_sphereBoundsHandle.radius = shapeModule.donutRadius * (1.0f - shapeModule.radiusThickness);
_sphereBoundsHandle.center = Vector3.zero;
_sphereBoundsHandle.SetColor (s_ShapeGizmoThicknessTint);
const float handleInterval = 90.0f;
int numOuterRadii = Mathf.Max (1, (int)Mathf.Ceil (shapeModule.arc / handleInterval));
Matrix4x4 donutRadiusStartMatrix = Matrix4x4.TRS (new Vector3 (shapeModule.radius, 0.0f, 0.0f), Quaternion.Euler (90.0f, 0.0f, 0.0f), Vector3.one);
for (int i = 0; i < numOuterRadii; i++)
{
EditorGUI.BeginChangeCheck ();
using (new Handles.DrawingScope (Handles.matrix * (Matrix4x4.Rotate (Quaternion.Euler (0.0f, 0.0f, handleInterval * i)) * donutRadiusStartMatrix)))
_sphereBoundsHandle.DrawHandle ();
if (EditorGUI.EndChangeCheck ())
{
Undo.RecordObject (ps, "Donut Radius Thickness Handle Change");
shapeModule.radiusThickness = 1.0f - (_sphereBoundsHandle.radius / shapeModule.donutRadius);
}
}
// Donut radius
_sphereBoundsHandle.radius = shapeModule.donutRadius;
_sphereBoundsHandle.SetColor (Color.white);
for (int i = 0; i < numOuterRadii; i++)
{
EditorGUI.BeginChangeCheck ();
using (new Handles.DrawingScope (Handles.matrix * (Matrix4x4.Rotate (Quaternion.Euler (0.0f, 0.0f, handleInterval * i)) * donutRadiusStartMatrix)))
_sphereBoundsHandle.DrawHandle ();
if (EditorGUI.EndChangeCheck ())
{
Undo.RecordObject (ps, "Donut Radius Handle Change");
shapeModule.donutRadius = _sphereBoundsHandle.radius;
}
}
// Texture
//Matrix4x4 textureTransform = transformMatrix * Matrix4x4.TRS (new Vector3 (shapeModule.radius, 0.0f, 0.0f), Quaternion.Euler (180.0f, 0.0f, 180.0f), Vector3.one * shapeModule.donutRadius * 2.0f);
//OnSceneViewTextureGUI (shapeModule, s_CircleMesh, true, s_TextureMaterial, textureTransform);
}
else if (type == ParticleSystemShapeType.SingleSidedEdge)
{
EditorGUI.BeginChangeCheck ();
//float radius = Handles.DoSimpleEdgeHandle (Quaternion.identity, Vector3.zero, shapeModule.radius);
float radius = Call<float> (typeof (Handles), "DoSimpleEdgeHandle", Quaternion.identity, Vector3.zero, shapeModule.radius);
if (EditorGUI.EndChangeCheck ())
{
Undo.RecordObject (ps, "Edge Handle Change");
shapeModule.radius = radius;
}
}
else if (type == ParticleSystemShapeType.Mesh)
{
Mesh mesh = shapeModule.mesh;
if (mesh)
{
bool orgWireframeMode = GL.wireframe;
GL.wireframe = true;
s_Material.SetPass (0);
Graphics.DrawMeshNow (mesh, transformMatrix);
GL.wireframe = orgWireframeMode;
//OnSceneViewTextureGUI (shapeModule, mesh, false, s_TextureMaterial, transformMatrix);
}
}
else if (type == ParticleSystemShapeType.Rectangle)
{
EditorGUI.BeginChangeCheck ();
_boxBoundsHandle.center = Vector3.zero;
_boxBoundsHandle.size = new Vector3 (shapeModule.scale.x, shapeModule.scale.y, 0.0f);
_boxBoundsHandle.DrawHandle ();
if (EditorGUI.EndChangeCheck ())
{
Undo.RecordObject (ps, "Rectangle Handle Change");
shapeModule.scale = new Vector3 (_boxBoundsHandle.size.x, _boxBoundsHandle.size.y, 0.0f);
}
//OnSceneViewTextureGUI (shapeModule, s_QuadMesh, true, s_TextureMaterial, transformMatrix * Matrix4x4.Scale (m_BoxBoundsHandle.size));
}
else if (type == ParticleSystemShapeType.Sprite)
{
Sprite sprite = shapeModule.sprite;
if (sprite)
{
if (!_spriteMesh)
{
_spriteMesh = new Mesh ();
_spriteMesh.name = "ParticleSpritePreview";
_spriteMesh.hideFlags |= HideFlags.HideAndDontSave;
}
_spriteMesh.vertices = Array.ConvertAll (sprite.vertices, i => (Vector3)i);
_spriteMesh.uv = sprite.uv;
_spriteMesh.triangles = Array.ConvertAll (sprite.triangles, i => (int)i);
bool orgWireframeMode = GL.wireframe;
GL.wireframe = true;
s_Material.SetPass (0);
Graphics.DrawMeshNow (_spriteMesh, transformMatrix);
GL.wireframe = orgWireframeMode;
//OnSceneViewTextureGUI (shapeModule, m_SpriteMesh, false, s_TextureMaterial, transformMatrix);
}
}
}
Handles.color = origCol;
Handles.matrix = orgMatrix;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 37cdd12f98487483aba53394d2174e31
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

407
Scripts/UIParticle.cs Executable file
View File

@@ -0,0 +1,407 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Profiling;
using UnityEngine.UI;
namespace Coffee.UIExtensions
{
/// <summary>
/// Render maskable and sortable particle effect ,without Camera, RenderTexture or Canvas.
/// </summary>
[ExecuteInEditMode]
public class UIParticle : MaskableGraphic
{
//################################
// Constant or Readonly Static Members.
//################################
static readonly int s_IdMainTex = Shader.PropertyToID ("_MainTex");
static readonly List<Vector3> s_Vertices = new List<Vector3> ();
static readonly List<UIParticle> s_TempRelatables = new List<UIParticle> ();
static readonly List<UIParticle> s_ActiveParticles = new List<UIParticle> ();
//################################
// Serialize Members.
//################################
[Tooltip ("The ParticleSystem rendered by CanvasRenderer")]
[SerializeField] ParticleSystem m_ParticleSystem;
[Tooltip ("The UIParticle to render trail effect")]
[SerializeField] UIParticle m_TrailParticle;
[HideInInspector] [SerializeField] bool m_IsTrail = false;
[Tooltip ("Particle effect scale")]
[SerializeField] float m_Scale = 1;
[Tooltip ("Ignore parent scale")]
[SerializeField] bool m_IgnoreParent = false;
//################################
// Public/Protected Members.
//################################
public override Texture mainTexture
{
get
{
Texture tex = null;
if (!m_IsTrail && cachedParticleSystem)
{
Profiler.BeginSample ("Check TextureSheetAnimation module");
var textureSheet = cachedParticleSystem.textureSheetAnimation;
if (textureSheet.enabled && textureSheet.mode == ParticleSystemAnimationMode.Sprites && 0 < textureSheet.spriteCount)
{
tex = textureSheet.GetSprite (0).texture;
}
Profiler.EndSample ();
}
if (!tex && _renderer)
{
Profiler.BeginSample ("Check material");
var mat = m_IsTrail
? _renderer.trailMaterial
: _renderer.sharedMaterial;
if (mat && mat.HasProperty (s_IdMainTex))
{
tex = mat.mainTexture;
}
Profiler.EndSample ();
}
return tex ?? s_WhiteTexture;
}
}
/// <summary>
/// Particle effect scale.
/// </summary>
public float scale { get { return _parent ? _parent.scale : m_Scale; } set { m_Scale = value; } }
/// <summary>
/// Should the soft mask ignore parent soft masks?
/// </summary>
/// <value>If set to true the soft mask will ignore any parent soft mask settings.</value>
public bool ignoreParent
{
get { return m_IgnoreParent; }
set
{
if (m_IgnoreParent != value)
{
m_IgnoreParent = value;
OnTransformParentChanged ();
}
}
}
/// <summary>
/// Is this the root UIParticle?
/// </summary>
public bool isRoot
{
get { return !_parent; }
}
/// <summary>
/// Should this graphic be considered a target for raycasting?
/// </summary>
public override bool raycastTarget { get { return false; } set { base.raycastTarget = value; } }
/// <summary>
/// ParticleSystem.
/// </summary>
public ParticleSystem cachedParticleSystem { get { return m_ParticleSystem ? m_ParticleSystem : (m_ParticleSystem = GetComponent<ParticleSystem> ()); } }
/// <summary>
/// Perform material modification in this function.
/// </summary>
/// <returns>Modified material.</returns>
/// <param name="baseMaterial">Configured Material.</param>
public override Material GetModifiedMaterial (Material baseMaterial)
{
return base.GetModifiedMaterial (_renderer ? _renderer.sharedMaterial : baseMaterial);
}
/// <summary>
/// This function is called when the object becomes enabled and active.
/// </summary>
protected override void OnEnable ()
{
// Register.
if (s_ActiveParticles.Count == 0)
{
Canvas.willRenderCanvases += UpdateMeshes;
}
s_ActiveParticles.Add (this);
// Reset the parent-child relation.
GetComponentsInChildren<UIParticle> (false, s_TempRelatables);
for (int i = s_TempRelatables.Count - 1; 0 <= i; i--)
{
s_TempRelatables [i].OnTransformParentChanged ();
}
s_TempRelatables.Clear ();
_renderer = cachedParticleSystem ? cachedParticleSystem.GetComponent<ParticleSystemRenderer> () : null;
if (_renderer && Application.isPlaying)
{
_renderer.enabled = false;
}
// Create objects.
_mesh = new Mesh ();
_mesh.MarkDynamic ();
CheckTrail ();
base.OnEnable ();
}
/// <summary>
/// This function is called when the behaviour becomes disabled.
/// </summary>
protected override void OnDisable ()
{
// Unregister.
s_ActiveParticles.Remove (this);
if (s_ActiveParticles.Count == 0)
{
Canvas.willRenderCanvases -= UpdateMeshes;
}
// Reset the parent-child relation.
for (int i = _children.Count - 1; 0 <= i; i--)
{
_children [i].SetParent (_parent);
}
_children.Clear ();
SetParent (null);
// Destroy objects.
DestroyImmediate (_mesh);
_mesh = null;
CheckTrail ();
base.OnDisable ();
}
/// <summary>
/// Call to update the geometry of the Graphic onto the CanvasRenderer.
/// </summary>
protected override void UpdateGeometry ()
{
}
/// <summary>
/// This function is called when the parent property of the transform of the GameObject has changed.
/// </summary>
protected override void OnTransformParentChanged ()
{
UIParticle newParent = null;
if (isActiveAndEnabled && !m_IgnoreParent)
{
var parentTransform = transform.parent;
while (parentTransform && (!newParent || !newParent.enabled))
{
newParent = parentTransform.GetComponent<UIParticle> ();
parentTransform = parentTransform.parent;
}
}
SetParent (newParent);
base.OnTransformParentChanged ();
}
/// <summary>
/// Callback for when properties have been changed by animation.
/// </summary>
protected override void OnDidApplyAnimationProperties ()
{
}
#if UNITY_EDITOR
/// <summary>
/// This function is called when the script is loaded or a value is changed in the inspector(Called in the editor only).
/// </summary>
protected override void OnValidate ()
{
OnTransformParentChanged ();
base.OnValidate ();
}
#endif
//################################
// Private Members.
//################################
Mesh _mesh;
ParticleSystemRenderer _renderer;
UIParticle _parent;
List<UIParticle> _children = new List<UIParticle> ();
Matrix4x4 scaleaMatrix = default (Matrix4x4);
/// <summary>
/// Update meshes.
/// </summary>
static void UpdateMeshes ()
{
for (int i = 0; i < s_ActiveParticles.Count; i++)
{
if (s_ActiveParticles [i])
{
s_ActiveParticles [i].UpdateMesh ();
}
}
}
/// <summary>
/// Update meshe.
/// </summary>
void UpdateMesh ()
{
try
{
Profiler.BeginSample ("CheckTrail");
CheckTrail ();
Profiler.EndSample ();
if (m_ParticleSystem && canvas)
{
if (canvas.renderMode != RenderMode.ScreenSpaceOverlay)
{
Vector3 pos = rectTransform.localPosition;
if (Mathf.Abs (pos.z) < 0.01f)
{
pos.z = 0.01f;
rectTransform.localPosition = pos;
}
}
var rootCanvas = canvas.rootCanvas;
Profiler.BeginSample ("Disable ParticleSystemRenderer");
if (Application.isPlaying)
{
_renderer.enabled = false;
}
Profiler.EndSample ();
Profiler.BeginSample ("Make Matrix");
scaleaMatrix = m_ParticleSystem.main.scalingMode == ParticleSystemScalingMode.Hierarchy
? Matrix4x4.Scale (scale * Vector3.one)
: Matrix4x4.Scale (scale * rootCanvas.transform.localScale);
Matrix4x4 matrix = default (Matrix4x4);
switch (m_ParticleSystem.main.simulationSpace)
{
case ParticleSystemSimulationSpace.Local:
matrix =
scaleaMatrix
* Matrix4x4.Rotate (m_ParticleSystem.transform.rotation).inverse
* Matrix4x4.Scale (m_ParticleSystem.transform.lossyScale).inverse;
break;
case ParticleSystemSimulationSpace.World:
matrix =
scaleaMatrix
* m_ParticleSystem.transform.worldToLocalMatrix;
break;
case ParticleSystemSimulationSpace.Custom:
break;
}
Profiler.EndSample ();
_mesh.Clear ();
if (0 < m_ParticleSystem.particleCount)
{
Profiler.BeginSample ("Bake Mesh");
var cam = rootCanvas.renderMode == RenderMode.ScreenSpaceOverlay
? UIParticleOverlayCamera.GetCameraForOvrelay (rootCanvas)
: canvas.worldCamera ?? Camera.main;
if (!cam)
{
return;
}
if (m_IsTrail)
{
_renderer.BakeTrailsMesh (_mesh, cam, true);
}
else
{
_renderer.BakeMesh (_mesh, cam, true);
}
Profiler.EndSample ();
// Apply matrix.
Profiler.BeginSample ("Apply matrix to position");
_mesh.GetVertices (s_Vertices);
var count = s_Vertices.Count;
for (int i = 0; i < count; i++)
{
s_Vertices [i] = matrix.MultiplyPoint3x4 (s_Vertices [i]);
}
_mesh.SetVertices (s_Vertices);
s_Vertices.Clear ();
Profiler.EndSample ();
}
// Set mesh to CanvasRenderer.
Profiler.BeginSample ("Set mesh and texture to CanvasRenderer");
canvasRenderer.SetMesh (_mesh);
canvasRenderer.SetTexture (mainTexture);
Profiler.EndSample ();
}
}
catch (System.Exception e)
{
Debug.LogException (e);
}
}
/// <summary>
/// Checks the trail.
/// </summary>
void CheckTrail ()
{
if (isActiveAndEnabled && !m_IsTrail && m_ParticleSystem && m_ParticleSystem.trails.enabled)
{
if (!m_TrailParticle)
{
m_TrailParticle = new GameObject ("[UIParticle] Trail").AddComponent<UIParticle> ();
var trans = m_TrailParticle.transform;
trans.SetParent (transform);
trans.localPosition = Vector3.zero;
trans.localRotation = Quaternion.identity;
trans.localScale = Vector3.one;
m_TrailParticle._renderer = GetComponent<ParticleSystemRenderer> ();
m_TrailParticle.m_ParticleSystem = GetComponent<ParticleSystem> ();
m_TrailParticle.m_IsTrail = true;
}
m_TrailParticle.enabled = true;
}
else if (m_TrailParticle)
{
m_TrailParticle.enabled = false;
}
}
/// <summary>
/// Set the parent of the soft mask.
/// </summary>
/// <param name="newParent">The parent soft mask to use.</param>
void SetParent (UIParticle newParent)
{
if (_parent != newParent && this != newParent)
{
if (_parent && _parent._children.Contains (this))
{
_parent._children.Remove (this);
_parent._children.RemoveAll (x => x == null);
}
_parent = newParent;
}
if (_parent && !_parent._children.Contains (this))
{
_parent._children.Add (this);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 16f0b0b6d0b7542bfbd20a3e05b04ff1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: -100
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,154 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
#if UNITY_2018_3_OR_NEWER && UNITY_EDITOR
using PrefabStageUtility = UnityEditor.Experimental.SceneManagement.PrefabStageUtility;
#endif
namespace Coffee.UIExtensions
{
/// <summary>
/// </summary>
[ExecuteInEditMode]
public class UIParticleOverlayCamera : MonoBehaviour
{
//################################
// Public/Protected Members.
//################################
/// <summary>
/// Get instance object.
/// If instance does not exist, Find instance in scene, or create new one.
/// </summary>
public static UIParticleOverlayCamera instance
{
get
{
#if UNITY_2018_3_OR_NEWER && UNITY_EDITOR
// If current scene is prefab mode, create OverlayCamera for editor.
var prefabStage = PrefabStageUtility.GetCurrentPrefabStage ();
if (prefabStage != null && prefabStage.scene.isLoaded)
{
if (!s_InstanceForPrefabMode)
{
// This GameObject is not saved in prefab.
// This GameObject is not shown in the hierarchy view.
// When you exit prefab mode, this GameObject is destroyed automatically.
var go = new GameObject (typeof (UIParticleOverlayCamera).Name + "_ForEditor")
{
hideFlags = HideFlags.HideAndDontSave,
tag = "EditorOnly",
};
UnityEngine.SceneManagement.SceneManager.MoveGameObjectToScene (go, prefabStage.scene);
s_InstanceForPrefabMode = go.AddComponent<UIParticleOverlayCamera> ();
}
return s_InstanceForPrefabMode;
}
#endif
// Find instance in scene, or create new one.
if (object.ReferenceEquals (s_Instance, null))
{
s_Instance = FindObjectOfType<UIParticleOverlayCamera> () ?? new GameObject (typeof (UIParticleOverlayCamera).Name, typeof (UIParticleOverlayCamera)).GetComponent<UIParticleOverlayCamera> ();
s_Instance.gameObject.SetActive (true);
s_Instance.enabled = true;
}
return s_Instance;
}
}
public static Camera GetCameraForOvrelay (Canvas canvas)
{
var i = instance;
var rt = canvas.rootCanvas.transform as RectTransform;
var cam = i.cameraForOvrelay;
var trans = i.transform;
cam.enabled = false;
var pos = rt.localPosition;
cam.orthographic = true;
cam.orthographicSize = Mathf.Max (pos.x, pos.y);
cam.nearClipPlane = 0.3f;
cam.farClipPlane = 1000f;
pos.z -= 100;
trans.localPosition = pos;
return cam;
}
//################################
// Private Members.
//################################
Camera cameraForOvrelay { get { return m_Camera ? m_Camera : (m_Camera = GetComponent<Camera> ()) ? m_Camera : (m_Camera = gameObject.AddComponent<Camera> ()); } }
Camera m_Camera;
static UIParticleOverlayCamera s_Instance;
#if UNITY_2018_3_OR_NEWER && UNITY_EDITOR
static UIParticleOverlayCamera s_InstanceForPrefabMode;
#endif
/// <summary>
/// Awake is called when the script instance is being loaded.
/// </summary>
void Awake ()
{
#if UNITY_2018_3_OR_NEWER && UNITY_EDITOR
// OverlayCamera for editor.
if (hideFlags == HideFlags.HideAndDontSave || s_InstanceForPrefabMode == this)
{
s_InstanceForPrefabMode = GetComponent<UIParticleOverlayCamera> ();
return;
}
#endif
// Hold the instance.
if (s_Instance == null)
{
s_Instance = GetComponent<UIParticleOverlayCamera> ();
}
// If the instance is duplicated, destroy itself.
else if (s_Instance != this)
{
UnityEngine.Debug.LogWarning ("Multiple " + typeof (UIParticleOverlayCamera).Name + " in scene.", this.gameObject);
enabled = false;
#if UNITY_EDITOR
if (!Application.isPlaying)
{
DestroyImmediate (gameObject);
}
else
#endif
{
Destroy (gameObject);
}
return;
}
cameraForOvrelay.enabled = false;
// Singleton has DontDestroy flag.
if (Application.isPlaying)
{
DontDestroyOnLoad (gameObject);
}
}
/// <summary>
/// This function is called when the MonoBehaviour will be destroyed.
/// </summary>
void OnDestroy ()
{
#if UNITY_2018_3_OR_NEWER && UNITY_EDITOR
if (s_InstanceForPrefabMode == this)
{
s_InstanceForPrefabMode = null;
}
#endif
// Clear instance on destroy.
if (s_Instance == this)
{
s_Instance = null;
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f69dfb25b53b14addbd71dbebdbaa132
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: