BITFALL/Assets/Plugins/FImpossible Creations/Plugins - Level Design/Object Stamper/ObjectStampMultiEmitter.cs

1103 lines
44 KiB
C#

#if UNITY_EDITOR
using FIMSpace.FEditor;
using UnityEditor;
#endif
using System.Collections.Generic;
using UnityEngine;
using System;
namespace FIMSpace.Generating
{
/// <summary>
/// Implementation of spawning groups of prefabs with multiple OStamperSets on multiple spawn areas
/// </summary>
[AddComponentMenu("FImpossible Creations/Level Design/Object Stamp Multi Emitter", 2)]
public partial class ObjectStampMultiEmitter : ObjectStampEmitterBase, IGenerating
{
public OStampPhysicalPlacementSetup PhysicalPlacement;
public OStamperMultiSet MultiSet;
public List<SpawnArea> Areas;
public List<GameObject> Spawned;
public int Selected = -1;
private int internalSelected = 0;
private ObjectStamperEmittedInfo spawningInfo;
public int editorSelected = -1;
protected override OStamperSet GetStamperSet() { return MultiSet.PrefabsSets[internalSelected]; }
protected override ObjectStamperEmittedInfo GetSpawnInfo() { return spawningInfo; }
private void Start()
{
if (MultiSet == null)
{
Debug.Log("[Objects Stamper] No 'MultiSet' assigned to '" + name + "'!");
return;
}
if (SpawnOnStart)
{
if (Spawned == null || Spawned.Count == 0)
{
MultiSpawn();
IG_CallAfterGenerated();
}
}
}
public void Generate()
{
if (Spawned == null || Spawned.Count == 0) MultiSpawn();
}
public void PreviewGenerate() { }
/// <summary>
/// For physical simulation, call IG_CallAfterGenerated(); after MultiSpawn!
/// </summary>
public void MultiSpawn(bool multiDetach = false)
{
Vector3 startPosition = transform.position;
Quaternion startRotation = transform.rotation;
ClearAlreadySpawned();
//try
//{
for (int i = 0; i < Areas.Count; i++) // Each Area - can be one but more often few
{
SpawnArea area = Areas[i];
Transform parentSpace = null;
if (area.Shape != SpawnArea.EShape.Points) parentSpace = transform.parent;
for (int s = 0; s < area.Sets.Count; s++) // Each selected spawn set in area - can be one or can be multiple
{
#region Null checks and preparation for references (stamperSet, setParams)
if (MultiSet == null) { UnityEngine.Debug.Log("[Object Stamp Multi Emitter] Null Multi Set! (" + name + ")"); break; }
if (MultiSet.PrefabSetSettings == null) { UnityEngine.Debug.Log("[Object Stamp Multi Emitter] Null PrefabSetSettings! (" + name + ")"); break; }
int setId = area.Sets[s];
if (setId >= MultiSet.PrefabsSets.Count || setId >= MultiSet.PrefabSetSettings.Count)
{
Debug.Log("[Object Stamp Multi Emitter] Wrong Set ID (out of bounds) (" + name + ")");
break;
}
if (setId < 0)
{
if (MultiSet.PrefabsSets.Count == 1) setId = 0;
UnityEngine.Debug.Log("[Object Stamp Multi Emitter] Not assigned Spawns Set in Spawn Area? (" + name + ")");
}
OStamperSet stamperSet = MultiSet.PrefabsSets[setId];
OStamperMultiSet.MultiStamperSetParameters setParams = MultiSet.PrefabSetSettings[setId];
internalSelected = setId;
if (stamperSet == null || setParams == null)
{
Debug.Log("[Object Stamp Multi Emitter] Null Stamper! (" + name + ")");
break;
}
#endregion
// One limit and randomly choosing prefabs
if (setParams.LimitMode == OStamperMultiSet.MultiStamperSetParameters.ECountLimit.OneLimitForThisSet)
{
int targetSpawnCount = Mathf.RoundToInt((float)setParams.GetRandomLimitCount() * area.Multiply[s]);
int count = 0;
for (int sp = 0; sp < targetSpawnCount; sp++)
{
if (area.Shape == SpawnArea.EShape.Points)
if (count >= area.Points.Count) break;
// Tries to find right position to spawn
for (int r = 0; r < MaxRetryAttempts + 1; r++) // When spawned successfully then loop breaks
{
transform.position = startPosition;
transform.rotation = startRotation;
EmitPoint ep = area.GetRandomLocalPoint();
Vector3 randomPosition = transform.TransformPoint(ep.pos);
transform.position = randomPosition;
transform.rotation = transform.rotation * ep.rot;
spawningInfo = stamperSet.Emit(false, parentSpace);
GameObject spawned = SpawnEmitPrefab(stamperSet);
if (spawned)
{
area.LatestSpawned.Add(spawned);
count++; break; // Succesfully spawned
}
}
}
}
else // Spawn limit per prefab in stamper set
{
for (int prId = 0; prId < MultiSet.PrefabsSets[internalSelected].Prefabs.Count; prId++)
{
int targetSpawnCount = Mathf.RoundToInt((float)setParams.GetRandomLimitCount(prId, MultiSet) * area.Multiply[s]);
//Debug.Log(MultiSet.PrefabsSets[internalSelected].Prefabs[prId].Prefab.name + " Spawn: " + targetSpawnCount);
for (int spawnEmissions = 0; spawnEmissions < targetSpawnCount; spawnEmissions++)
{
// Tries to find right position to spawn
for (int r = 0; r < MaxRetryAttempts + 1; r++) // When spawned successfully then loop breaks
{
transform.position = startPosition;
transform.rotation = startRotation;
EmitPoint ep = area.GetRandomLocalPoint();
Vector3 randomPosition = transform.TransformPoint(ep.pos);
transform.position = randomPosition;
transform.rotation = transform.rotation * ep.rot;
spawningInfo = stamperSet.GenerateInfoForPrefab(MultiSet.PrefabsSets[internalSelected].Prefabs[prId], parentSpace);
GameObject spawned = SpawnEmitPrefab(stamperSet);
if (spawned) break; // Succesfully spawned
}
}
}
}
}
}
//}
//catch (System.Exception exc)
//{
// Debug.LogException(exc);
// transform.position = startPosition;
//}
transform.position = startPosition;
transform.rotation = startRotation;
if (multiDetach || AlwaysDetachSpawned)
{
for (int i = 0; i < Spawned.Count; i++)
{
if (Spawned[i] == null) continue;
Spawned[i].transform.SetParent(transform.parent, true);
}
if (multiDetach) Spawned.Clear();
}
else
{
for (int i = 0; i < Spawned.Count; i++)
{
if (Spawned[i] == null) continue;
Spawned[i].transform.SetParent(transform, true);
}
}
}
protected override GameObject InternalInstatiatePrefab(bool raycasted, bool setParent = true)
{
//if (raycasted == false) return null;
GameObject instantiated = base.InternalInstatiatePrefab(raycasted, false);
if (instantiated) Spawned.Add(instantiated);
return instantiated;
}
/// <summary>
/// Destroying already instantiated objects by multi emitter from scene
/// </summary>
public void ClearAlreadySpawned()
{
if (Spawned == null) Spawned = new List<GameObject>();
for (int i = 0; i < Spawned.Count; i++) FGenerators.DestroyObject(Spawned[i]);
for (int a = 0; a < Areas.Count; a++)
{
var ar = Areas[a];
if (ar == null) continue;
if (ar.LatestSpawned == null) ar.LatestSpawned = new List<GameObject>(); else ar.LatestSpawned.Clear();
}
Spawned.Clear();
}
#if UNITY_EDITOR
private void OnDrawGizmos()
{
if (Selection.activeGameObject == gameObject) return;
Color pc = Gizmos.color;
Gizmos.matrix = transform.localToWorldMatrix;
if (Areas != null)
if (Areas.Count > 0) if (Areas[0] != null)
{
Gizmos.color = new Color(0.2f, 1f, 0.2f, 0.2f);
Gizmos.DrawCube(Vector3.zero, new Vector3(Areas[0].Size.x, Areas[0].Size.magnitude * 0.1f, Areas[0].Size.y));
}
Gizmos.matrix = Matrix4x4.identity;
Gizmos.color = pc;
}
#endif
private static List<GameObject> _toPhysSimulate;
public void IG_CallAfterGenerated()
{
if (PhysicalPlacement.Enabled == false) return;
if (_toPhysSimulate == null) _toPhysSimulate = new List<GameObject>(); else _toPhysSimulate.Clear();
for (int a = 0; a < Areas.Count; a++)
{
if (Areas[a].ApplyPhysicalSimulation == false) continue;
for (int g = 0; g < Areas[a].LatestSpawned.Count; g++)
{
_toPhysSimulate.Add(Areas[a].LatestSpawned[g]);
}
}
PhysicalPlacement.ProceedOn(_toPhysSimulate);
}
public override void SpawnIfNotEmittedYet()
{
if (Spawned == null || Spawned.Count == 0) MultiSpawn();
}
#region Spawn Area
[System.Serializable]
public class SpawnArea
{
public string Name;
public SpawnArea(string name)
{
Name = name;
}
public enum EShape { Rectangle, Circle, Points, Volume }
public EShape Shape = EShape.Rectangle;
[Tooltip("For example making circle shape out of disc shape for spawning objects\nFollow editor scene window gizmos")]
[Range(0f, 1f)] public float NoInside = 0f;
//[Range(0f, 1f)] public float NoNearEdges = 0f;
public Vector3 Center = Vector3.zero;
public Vector2 Size = Vector2.one;
public Vector3 VSize = Vector3.one;
public List<int> Sets;
public List<float> Multiply;
public bool PointsFoldout = true;
public List<EmitPoint> Points;
[Tooltip("If using physical placement simulation settigns then you can exclude some areas from simulation if you wish.")]
public bool ApplyPhysicalSimulation = true;
[NonSerialized] public List<GameObject> LatestSpawned = new List<GameObject>();
public EmitPoint GetRandomLocalPoint()
{
if (Shape == EShape.Rectangle)
{
float r = FGenerators.GetRandom(NoInside, 1f) / 2f;
float x = FGenerators.GetRandom(r, .5f);
float y = FGenerators.GetRandom(r, .5f);
if (FGenerators.GetRandom(0f, 1f) < 0.5f) x = -x;
if (FGenerators.GetRandom(0f, 1f) < 0.5f) y = -y;
if (FGenerators.GetRandom(0f, 1f) < 0.5f)
x *= FGenerators.GetRandom(-1f, 1f);
else
y *= FGenerators.GetRandom(-1f, 1f);
return new EmitPoint(new Vector3(Size.x * x, 0f, Size.y * y) + Center);
}
else
if (Shape == EShape.Circle)
{
float radius = FGenerators.GetRandom(NoInside, 1f) * Size.x;
float per = FGenerators.GetRandom(0f, Mathf.PI * 2f);
return new EmitPoint(new Vector3(Mathf.Sin(per) * radius, 0f, Mathf.Cos(per) * radius) + Center);
}
else if (Shape == EShape.Points)
{
return Points[FGenerators.GetRandom(0, Points.Count)];
}
else if (Shape == EShape.Volume)
{
float x = FGenerators.GetRandom(-.5f, .5f);
float y = FGenerators.GetRandom(-.5f, .5f);
float z = FGenerators.GetRandom(-.5f, .5f);
return new EmitPoint(new Vector3(VSize.x * x, VSize.y * y, VSize.z * z) + Center);
}
return new EmitPoint(Vector3.zero);
}
}
#endregion
[System.Serializable]
public class EmitPoint
{
public Vector3 pos;
public Quaternion rot;
public EmitPoint(Vector3 pos)
{
this.pos = pos;
rot = Quaternion.identity;
}
public EmitPoint(Vector3 pos, Quaternion rot) : this(pos)
{
this.rot = rot;
}
}
}
#if UNITY_EDITOR
[UnityEditor.CanEditMultipleObjects]
[UnityEditor.CustomEditor(typeof(ObjectStampMultiEmitter))]
public class ObjectsStampMultiEmitterEditor : ObjectsStampEmitterBaseEditor
{
public ObjectStampMultiEmitter Get { get { if (_get == null) _get = (ObjectStampMultiEmitter)target; return _get; } }
private ObjectStampMultiEmitter _get;
SerializedProperty sp_pf;
SerializedProperty sp_areas;
private SerializedProperty sp_PhysicalPlacement;
private SerializedProperty sp_PhysicalPlacementEnabled;
protected override void OnEnable()
{
base.OnEnable();
if (Get.Areas == null) Get.Areas = new List<ObjectStampMultiEmitter.SpawnArea>();
if (Get.Spawned == null) Get.Spawned = new List<GameObject>();
sp_pf = serializedObject.FindProperty("MultiSet");
sp_areas = serializedObject.FindProperty("Areas");
sp_PhysicalPlacement = serializedObject.FindProperty("PhysicalPlacement");
sp_PhysicalPlacementEnabled = sp_PhysicalPlacement.FindPropertyRelative("Enabled");
}
private string[] setEmitters;
private int[] setEmittersId;
protected override void DrawProperties()
{
base.DrawProperties();
GUILayout.Space(5);
Color bc = GUI.backgroundColor;
// Prefabs Set Field -------------------------------
EditorGUILayout.BeginHorizontal();
EditorGUIUtility.labelWidth = 90;
EditorGUILayout.PropertyField(sp_pf);
if (Get.MultiSet && Get.MultiSet.PrefabsSets != null) EditorGUILayout.LabelField("(" + Get.MultiSet.PrefabsSets.Count + ")", GUILayout.Width(24));
if (GUILayout.Button("Create New", GUILayout.Width(84))) Get.MultiSet = (OStamperMultiSet)FGenerators.GenerateScriptable(CreateInstance<OStamperMultiSet>(), "OMS_");
EditorGUILayout.EndHorizontal();
EditorGUIUtility.labelWidth = 0;
GUILayout.Space(4f);
if (Get.MultiSet == null)
{
EditorGUILayout.HelpBox(" First assign Multi Objects Stamper Set!", MessageType.Info);
serializedObject.ApplyModifiedProperties();
return;
}
if (Get.MultiSet != null)
{
if (Get.MultiSet.PrefabsSets != null)
{
setEmitters = new string[Get.MultiSet.PrefabsSets.Count + 1];
setEmittersId = new int[Get.MultiSet.PrefabsSets.Count + 1];
setEmitters[0] = "None";
setEmittersId[0] = -1;
}
}
if (setEmitters != null)
if (Get.MultiSet != null)
for (int i = 1; i < setEmitters.Length; i++)
{
if (Get.MultiSet.PrefabsSets[i - 1] == null) continue;
setEmitters[i] = Get.MultiSet.PrefabsSets[i - 1].name;
setEmittersId[i] = i - 1;
}
if (Get.Areas.Count == 0)
{
GUI.backgroundColor = Color.green;
GUI.color = Color.yellow;
}
EditorGUILayout.BeginVertical(FGUI_Resources.BGInBoxStyle);
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField(new GUIContent("Spawn Areas (" + Get.Areas.Count + ")", "Add spawn areas to prepare placement for generated objects"));
if (Get.Areas.Count == 0)
{
GUI.backgroundColor = Color.white;
GUI.color = Color.white;
}
if (GUILayout.Button("+", GUILayout.Width(24)))
{
var nArea = new ObjectStampMultiEmitter.SpawnArea("Area " + Get.Areas.Count.ToString());
if (Get.MultiSet.PrefabsSets.Count > 0)
{
if (nArea.Sets == null) nArea.Sets = new List<int>();
if (nArea.Multiply == null) nArea.Multiply = new List<float>();
nArea.Sets.Add(0);
nArea.Multiply.Add(1f);
Get.Selected = 0;
}
Get.Areas.Add(nArea);
Changed();
EditorGUILayout.EndHorizontal();
return;
}
EditorGUILayout.EndHorizontal();
float width = 0;
float size = 24;
GUILayoutOption opt = GUILayout.Width(size);
if (Get.Selected >= Get.Areas.Count) Get.Selected = -1;
EditorGUILayout.BeginHorizontal();
for (int i = 0; i < Get.Areas.Count; i++)
{
width += 24;
if (i == Get.Selected) GUI.backgroundColor = Color.green;
if (GUILayout.Button(i.ToString(), opt)) { if (Get.Selected == i) Get.Selected = -1; else Get.Selected = i; }
if (i == Get.Selected) GUI.backgroundColor = bc;
if (width + size > EditorGUIUtility.currentViewWidth - 60) { width = 0f; EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); }
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.EndVertical();
if (Get.Selected > -1)
{
ObjectStampMultiEmitter.SpawnArea area = Get.Areas[Get.Selected];
if (area != null)
{
GUILayout.Space(7);
SerializedProperty prop = sp_areas.GetArrayElementAtIndex(Get.Selected);
SerializedProperty spc = prop.Copy();
EditorGUILayout.BeginVertical(FGUI_Resources.BGInBoxStyle);
prop.Next(true);
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField(new GUIContent(area.Name, "Select desired shape of how you want to place your generated objects"), GUILayout.Width(100));
prop.NextVisible(false); EditorGUILayout.PropertyField(prop, GUIContent.none);
GUILayout.FlexibleSpace();
Color prebc = GUI.backgroundColor;
GUI.backgroundColor = new Color(1f, 0.635f, 0.635f, 1f);
if (GUILayout.Button(new GUIContent(FGUI_Resources.Tex_Remove), FGUI_Resources.ButtonStyle, new GUILayoutOption[2] { GUILayout.Width(24), GUILayout.Height(24) })) { Get.Areas.RemoveAt(Get.Selected); Changed(); }
GUI.backgroundColor = prebc;
EditorGUILayout.EndHorizontal();
if (Get.PhysicalPlacement.Enabled)
{
EditorGUIUtility.labelWidth = 160;
EditorGUILayout.BeginHorizontal();
EditorGUILayout.PropertyField(spc.FindPropertyRelative("ApplyPhysicalSimulation"));
GUILayout.FlexibleSpace();
if (GUILayout.Button(FGUI_Resources.Tex_Physics, EditorStyles.label, GUILayout.Height(18), GUILayout.Width(20))) { area.ApplyPhysicalSimulation = !area.ApplyPhysicalSimulation; Changed(); }
EditorGUILayout.EndHorizontal();
EditorGUIUtility.labelWidth = 0;
GUILayout.Space(4);
}
if (area.Shape == ObjectStampMultiEmitter.SpawnArea.EShape.Volume)
{
//prop.NextVisible(false);
prop.NextVisible(false); prop.NextVisible(false); EditorGUILayout.PropertyField(prop); prop.NextVisible(false);
//prop.NextVisible(false); EditorGUILayout.PropertyField(prop);
}
else if (area.Shape != ObjectStampMultiEmitter.SpawnArea.EShape.Points)
{
prop.NextVisible(false); EditorGUILayout.PropertyField(prop);
//prop.NextVisible(false); EditorGUILayout.PropertyField(prop);
}
else
{
prop.NextVisible(false);
//prop.NextVisible(false);
}
prop.NextVisible(false);
if (area.Shape != ObjectStampMultiEmitter.SpawnArea.EShape.Points) EditorGUILayout.PropertyField(prop);
//EditorGUILayout.PropertyField(prop, new GUIContent("Offset Points"));
prop.NextVisible(false);
if (area.Shape == ObjectStampMultiEmitter.SpawnArea.EShape.Rectangle)
EditorGUILayout.PropertyField(prop);
else
if (area.Shape == ObjectStampMultiEmitter.SpawnArea.EShape.Circle)
prop.vector2Value = new Vector2(EditorGUILayout.FloatField("Radius", prop.vector2Value.x), prop.vector2Value.x);
else
if (area.Shape == ObjectStampMultiEmitter.SpawnArea.EShape.Points)
{
if (area.Points.Count == 0) area.Points.Add(new ObjectStampMultiEmitter.EmitPoint(Vector3.right));
GUILayout.Space(2);
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
GUILayout.Space(2);
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button(" " + (area.PointsFoldout ? "▼" : "►") + " Points (" + area.Points.Count + ")", EditorStyles.label)) { area.PointsFoldout = !area.PointsFoldout; }
//GUILayout.FlexibleSpace();
if (GUILayout.Button("+", GUILayout.Width(24))) { area.Points.Add(new ObjectStampMultiEmitter.EmitPoint(Vector3.forward)); Changed(); }
EditorGUILayout.EndHorizontal();
if (area.PointsFoldout)
{
SerializedProperty sp_p = sp_areas.GetArrayElementAtIndex(Get.Selected).FindPropertyRelative("Points");
SerializedProperty sp_pf = sp_p.Copy();
sp_pf.NextVisible(true);
for (int i = 0; i < sp_p.arraySize; i++)
{
sp_pf.NextVisible(false);
SerializedProperty sp_v = sp_pf.FindPropertyRelative("pos");
sp_v.vector3Value = EditorGUILayout.Vector3Field(new GUIContent("Point [" + i + "]"), sp_v.vector3Value);
sp_v.NextVisible(false); sp_v.quaternionValue = Quaternion.Euler(EditorGUILayout.Vector3Field(new GUIContent("Rotation"), sp_v.quaternionValue.eulerAngles));
//EditorGUILayout.PropertyField(sp_pf, new GUIContent("Point [" + i + "]"));
GUILayout.Space(7);
}
}
EditorGUILayout.EndVertical();
}
GUILayout.Space(5);
EditorGUILayout.BeginVertical(FGUI_Resources.BGInBoxStyleH);
if (area.Sets == null)
{
area.Sets = new List<int>();
area.Multiply = new List<float>();
}
if (area.Points == null) area.Points = new List<ObjectStampMultiEmitter.EmitPoint>();
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField(new GUIContent("Spawns for this area (" + area.Sets.Count + ")" + (area.Sets.Count == 0 ? " !!!" : ""), "Select stampers from stamper multi set to spawn with this shape"));
GUILayout.FlexibleSpace();
if (GUILayout.Button("+", GUILayout.Width(24))) { area.Sets.Add(-1); area.Multiply.Add(1f); Changed(); }
EditorGUILayout.EndHorizontal();
for (int i = 0; i < area.Sets.Count; i++)
{
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
EditorGUILayout.BeginHorizontal();
area.Sets[i] = EditorGUILayout.IntPopup(area.Sets[i], setEmitters, setEmittersId);
GUI.backgroundColor = new Color(1f, 0.635f, 0.635f, 1f);
if (GUILayout.Button(new GUIContent(FGUI_Resources.Tex_Remove), FGUI_Resources.ButtonStyle, new GUILayoutOption[2] { GUILayout.Width(24), GUILayout.Height(24) }))
{
area.Sets.RemoveAt(i);
area.Multiply.RemoveAt(i);
serializedObject.ApplyModifiedProperties();
Changed();
return;
}
GUI.backgroundColor = prebc;
EditorGUILayout.EndHorizontal();
EditorGUIUtility.fieldWidth = 36;
area.Multiply[i] = EditorGUILayout.Slider(new GUIContent("Multiply Count", "Multiplying defined spawn count inside stamper file"), area.Multiply[i], 0f, 2f);
EditorGUIUtility.fieldWidth = 0;
EditorGUILayout.EndVertical();
}
EditorGUILayout.EndVertical();
EditorGUILayout.EndVertical();
}
}
GUI.backgroundColor = bc;
GUILayout.Space(6);
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button(new GUIContent(" Test Emit", FGUI_Resources.Tex_Movement), GUILayout.Height(22)))
{
Get.MultiSpawn();
Get.IG_CallAfterGenerated();
//Get._EditorEmitPreview();
}
if (GUILayout.Button(new GUIContent(" Emit and Detach", FGUI_Resources.Tex_Movement), GUILayout.Height(22)))
{
Get.MultiSpawn(true);
Get.IG_CallAfterGenerated();
//Get._EditorEmitPreview();
}
EditorGUILayout.EndHorizontal();
if (Get.Spawned.Count > 0)
if (GUILayout.Button(new GUIContent(" Clear Spawned", FGUI_Resources.Tex_Remove), GUILayout.Height(22)))
{
Get.ClearAlreadySpawned();
Changed();
//if (Get._editorPreview) FGenerators.DestroyObject(Get._editorPreview);
//Get.spawningInfo = Get.PrefabsSet.Emit();
}
}
protected override void _DrawLastProperties()
{
GUILayout.Space(8);
EditorGUI.BeginChangeCheck();
Get.PhysicalPlacement._Editor_DrawSetupToggle(sp_PhysicalPlacementEnabled);
if (Get.PhysicalPlacement._Editor_Foldout)
{
Get.PhysicalPlacement._Editor_DrawSetup(sp_PhysicalPlacement, false);
GUILayout.Space(4);
}
if (EditorGUI.EndChangeCheck()) EditorUtility.SetDirty(Get);
GUILayout.Space(6);
}
private void Changed()
{
EditorUtility.SetDirty(Get);
}
private void OnSceneGUI()
{
if (Get.Spawned == null) Get.Spawned = new List<GameObject>();
//CompareFunction compare = Handles.zTest;
Color preH = Handles.color;
float step = 1f / (float)Get.Areas.Count;
refSize = 0.05f;
for (int i = 0; i < Get.Areas.Count; i++)
{
float sz = Get.transform.TransformVector(Get.Areas[i].Size).magnitude;
if (sz > refSize) refSize = sz;
}
for (int i = 0; i < Get.Areas.Count; i++)
{
if (i == Get.Selected) continue;
Color newCol = Color.HSVToRGB(step * (float)i, 0.9f, 0.9f);
newCol.a = 0.3f;
Handles.color = newCol;
if (FGenerators.CheckIfExist_NOTNULL(Get.Areas[i])) DrawArea(Get.Areas[i], i);
}
if (Get.Selected > -1)
{
if (Get.Areas != null)
if (Get.Areas.Count > 0)
if (Get.Selected >= 0)
{
if (Get.Areas[Get.Selected].Shape == ObjectStampMultiEmitter.SpawnArea.EShape.Circle)
Handles.color = new Color(1f, 1f, 1f, 0.25f);
else
Handles.color = new Color(1f, 1f, 1f, 0.7f);
DrawArea(Get.Areas[Get.Selected], Get.Selected, true);
}
}
Handles.color = preH;
//Handles.zTest = compare;
}
float refSize = 0.1f;
//float refScale = 0f;
private void DrawArea(ObjectStampMultiEmitter.SpawnArea area, int id, bool selected = false)
{
if (area == null) return;
Color backCol = Handles.color;
//float refSize = Get.transform.TransformVector(area.Size).magnitude;
//if (Event.current == null && Event.current.type == EventType.MouseDown) refScale = refSize;
Handles.matrix = Get.transform.localToWorldMatrix;
//Handles.Label(area.Center, "[" + id + "]");
//Handles.Label(area.Center, new GUIContent(Get.MultiSet.PrefabsSets[id].Prefabs[0].Preview));
if (area.Shape == ObjectStampMultiEmitter.SpawnArea.EShape.Circle)
{
//if (selected)
DrawCircle(area.Center, area.Size.x, area.NoInside);
//else
// Handles.DrawWireArc(area.Center, Vector3.up, Vector3.forward, 360f, area.Size.x);
}
else
if (area.Shape == ObjectStampMultiEmitter.SpawnArea.EShape.Rectangle)
{
//if (selected)
DrawRect(area.Center, area.Size, area.NoInside);
//else
// Handles.DrawWireCube(area.Center, new Vector3(area.Size.x, 0.01f, area.Size.y));
}
else if (area.Shape == ObjectStampMultiEmitter.SpawnArea.EShape.Volume)
{
Handles.DrawWireCube(area.Center, area.VSize);
}
Handles.matrix = Matrix4x4.identity;
Vector3 p = Get.transform.TransformPoint(area.Center);
Handles.color = Color.cyan;
area.Center = Get.transform.InverseTransformPoint(FEditor_TransformHandles.PositionHandle(p, Get.transform.rotation, 0.3f, true, false, false));
//area.Center = Get.transform.InverseTransformPoint( Handles.FreeMoveHandle(p, Quaternion.identity, refSize * 0.1f, Vector3.zero, Handles.CircleHandleCap));
Handles.color = backCol;
if (selected)
{
if (area.Shape == ObjectStampMultiEmitter.SpawnArea.EShape.Volume)
{
Vector3 VSize = FEditor_TransformHandles.ScaleHandle(new Vector3(area.VSize.x, area.VSize.y, area.VSize.z), p + Get.transform.TransformVector(new Vector3(refSize * 0.15f, 0f, refSize * 0.15f)), Quaternion.identity, 0.4f, area.Shape == ObjectStampMultiEmitter.SpawnArea.EShape.Circle, true);
area.VSize = VSize;
}
else
if (area.Shape != ObjectStampMultiEmitter.SpawnArea.EShape.Points)
{
Vector3 size = FEditor_TransformHandles.ScaleHandle(new Vector3(area.Size.x, area.Size.x, area.Size.y), p + Get.transform.TransformVector(new Vector3(refSize * 0.15f, 0f, refSize * 0.15f)), Quaternion.identity, 0.4f, area.Shape == ObjectStampMultiEmitter.SpawnArea.EShape.Circle, true);
area.Size = new Vector2(size.x, size.z);
}
if (area.Shape == ObjectStampMultiEmitter.SpawnArea.EShape.Points)
for (int i = 0; i < area.Points.Count; i++)
{
Handles.DrawSolidDisc(Get.transform.TransformPoint(area.Points[i].pos), Vector3.up, refSize * 0.0075f);
area.Points[i].pos = Get.transform.InverseTransformPoint(FEditor_TransformHandles.PositionHandle(Get.transform.TransformPoint(area.Points[i].pos), Get.transform.rotation * area.Points[i].rot, 0.4f, true, false));
//area.Points[i].rot = FEditor_TransformHandles.RotationHandle(area.Points[i].rot, Get.transform.TransformPoint(area.Points[i].pos), 0.2f, true);
}
}
else
{
bool drawedButton = false;
if (SceneView.currentDrawingSceneView != null && SceneView.currentDrawingSceneView.camera != null)
if (Get.MultiSet)
if (Get.MultiSet.PrefabsSets.Count > 0)
if (id < Get.MultiSet.PrefabsSets.Count)
if (Get.MultiSet.PrefabsSets[id])
if (Get.MultiSet.PrefabsSets[id].Prefabs != null)
if (Get.MultiSet.PrefabsSets[id].Prefabs.Count > 0)
{
if (area.Sets != null && area.Sets.Count > 0)
{
drawedButton = true;
Handles.BeginGUI();
Handles.SetCamera(SceneView.currentDrawingSceneView.camera);
Vector3 buttonPos;
if (area.Shape == ObjectStampMultiEmitter.SpawnArea.EShape.Points)
buttonPos = Get.transform.TransformPoint(area.Center);
else
buttonPos = Get.transform.TransformPoint(area.Center + area.Size.x * (Vector3.left / 2) * area.NoInside);
if (DrawButton(new GUIContent(Get.MultiSet.PrefabSetSettings[area.Sets[0]].Preview), buttonPos + Vector3.left * refSize * 0.05f, 2200f)) Get.Selected = id;
//if (DrawButton(new GUIContent(Get.MultiSet.PrefabsSets[id].Prefabs[0].Preview), Get.transform.TransformPoint(area.Center), 2200f)) Get.Selected = id;
Handles.EndGUI();
}
}
if (!drawedButton)
if (Handles.Button(p, Quaternion.identity, refSize * 0.1f, refSize * (drawedButton ? 0.0025f : 0.1f), Handles.SphereHandleCap))
Get.Selected = id;
if (area.Shape == ObjectStampMultiEmitter.SpawnArea.EShape.Points)
for (int i = 0; i < area.Points.Count; i++)
Handles.SphereHandleCap(0, Get.transform.TransformPoint(area.Points[i].pos), Quaternion.identity, refSize * 0.05f, EventType.Repaint);
}
}
bool DrawButton(GUIContent content, Vector3 pos, float size)
{
float sc = HandleUtility.GetHandleSize(pos);
float hSize = Mathf.Sqrt(size) * 2f - sc * 16;
hSize /= 2f;
if (hSize > 0f)
{
Handles.BeginGUI();
Vector2 pos2D = HandleUtility.WorldToGUIPoint(pos);
float hhSize = hSize / 2f;
if (GUI.Button(new Rect(pos2D.x - hhSize, pos2D.y - hhSize, hSize, hSize), content))
{
Handles.EndGUI();
return true;
}
Handles.EndGUI();
}
return false;
}
private Vector3 sizeW;
private Vector3 sizeF;
void DrawRect(Vector3 position, Vector2 size, float noInside = 1f)
{
List<Vector3> verts = new List<Vector3>();
sizeW = new Vector3(size.x / 2f, 1f, size.y / 2f);
sizeF = new Vector3(size.x / 2f, 1f, size.y / 2f) * noInside;
if (noInside <= 0f)
{
verts.Add(VWrld(new Vector3(-1f, 0f, 1f)));
verts.Add(VWrld(new Vector3(1f, 0f, 1f)));
verts.Add(VWrld(new Vector3(1f, 0f, -1f)));
verts.Add(VWrld(new Vector3(-1f, 0f, -1f)));
for (int i = 0; i < verts.Count; i++) verts[i] += position;
Handles.DrawAAConvexPolygon(verts.ToArray());
}
else
{
verts.Add(VWrld(new Vector3(-1f, 0f, 1f)));
verts.Add(VWrld(new Vector3(1f, 0f, 1f)));
verts.Add(VFill(new Vector3(1f, 0f, 1f)));
verts.Add(VFill(new Vector3(-1f, 0f, 1f)));
for (int i = 0; i < verts.Count; i++) verts[i] += position;
Handles.DrawAAConvexPolygon(verts.ToArray());
verts.Clear();
verts.Add(VWrld(new Vector3(-1f, 0f, 1f)));
verts.Add(VWrld(new Vector3(-1f, 0f, -1f)));
verts.Add(VFill(new Vector3(-1f, 0f, -1f)));
verts.Add(VFill(new Vector3(-1f, 0f, 1f)));
for (int i = 0; i < verts.Count; i++) verts[i] += position;
Handles.DrawAAConvexPolygon(verts.ToArray());
verts.Clear();
verts.Add(VWrld(new Vector3(-1f, 0f, -1f)));
verts.Add(VWrld(new Vector3(1f, 0f, -1f)));
verts.Add(VFill(new Vector3(1f, 0f, -1f)));
verts.Add(VFill(new Vector3(-1f, 0f, -1f)));
for (int i = 0; i < verts.Count; i++) verts[i] += position;
Handles.DrawAAConvexPolygon(verts.ToArray());
verts.Clear();
verts.Add(VWrld(new Vector3(1f, 0f, 1f)));
verts.Add(VWrld(new Vector3(1f, 0f, -1f)));
verts.Add(VFill(new Vector3(1f, 0f, -1f)));
verts.Add(VFill(new Vector3(1f, 0f, 1f)));
for (int i = 0; i < verts.Count; i++) verts[i] += position;
Handles.DrawAAConvexPolygon(verts.ToArray());
verts.Clear();
}
}
void DrawCircle(Vector3 position, float radius, float noInside = 1f)
{
List<Vector3> verts = new List<Vector3>();
sizeW = new Vector3(radius, 1f, radius);
sizeF = new Vector3(radius, 1f, radius) * noInside;
float steps = 20f;
float step = 360f / steps;
if (noInside <= 0f)
{
for (int r = 0; r < (int)steps; r++)
{
float sin = Mathf.Sin(step * r * Mathf.Deg2Rad);
float cos = Mathf.Cos(step * r * Mathf.Deg2Rad);
verts.Add(VWrld(new Vector3(sin, 0f, cos)));
}
for (int i = 0; i < verts.Count; i++) verts[i] += position;
Handles.DrawAAConvexPolygon(verts.ToArray());
}
else
{
int quart = (int)(steps / 4f);
for (int r = 0; r <= quart; r++)
{
float sin = Mathf.Sin(step * r * Mathf.Deg2Rad); float cos = Mathf.Cos(step * r * Mathf.Deg2Rad);
verts.Add(VWrld(new Vector3(sin, 0f, cos)));
}
for (int r = quart; r >= 2; r -= 1)
{
float sin = Mathf.Sin(step * r * Mathf.Deg2Rad); float cos = Mathf.Cos(step * r * Mathf.Deg2Rad);
verts.Add(VFill(new Vector3(sin, 0f, cos)));
}
for (int i = 0; i < verts.Count; i++) verts[i] += position;
Handles.DrawAAConvexPolygon(verts.ToArray());
verts.Clear();
for (int r = quart; r <= quart * 2; r++)
{
float sin = Mathf.Sin(step * r * Mathf.Deg2Rad); float cos = Mathf.Cos(step * r * Mathf.Deg2Rad);
verts.Add(VWrld(new Vector3(sin, 0f, cos)));
}
for (int r = quart * 2; r >= quart + 2; r -= 1)
{
float sin = Mathf.Sin(step * r * Mathf.Deg2Rad); float cos = Mathf.Cos(step * r * Mathf.Deg2Rad);
verts.Add(VFill(new Vector3(sin, 0f, cos)));
}
for (int i = 0; i < verts.Count; i++) verts[i] += position;
Handles.DrawAAConvexPolygon(verts.ToArray());
verts.Clear();
for (int r = quart * 2; r <= quart * 3; r++)
{
float sin = Mathf.Sin(step * r * Mathf.Deg2Rad); float cos = Mathf.Cos(step * r * Mathf.Deg2Rad);
verts.Add(VWrld(new Vector3(sin, 0f, cos)));
}
for (int r = quart * 3; r >= quart * 2 + 2; r -= 1)
{
float sin = Mathf.Sin(step * r * Mathf.Deg2Rad); float cos = Mathf.Cos(step * r * Mathf.Deg2Rad);
verts.Add(VFill(new Vector3(sin, 0f, cos)));
}
for (int i = 0; i < verts.Count; i++) verts[i] += position;
Handles.DrawAAConvexPolygon(verts.ToArray());
verts.Clear();
for (int r = quart * 3; r <= quart * 4; r++)
{
float sin = Mathf.Sin(step * r * Mathf.Deg2Rad); float cos = Mathf.Cos(step * r * Mathf.Deg2Rad);
verts.Add(VWrld(new Vector3(sin, 0f, cos)));
}
for (int r = quart * 4; r >= quart * 3 + 2; r -= 1)
{
float sin = Mathf.Sin(step * r * Mathf.Deg2Rad); float cos = Mathf.Cos(step * r * Mathf.Deg2Rad);
verts.Add(VFill(new Vector3(sin, 0f, cos)));
}
for (int i = 0; i < verts.Count; i++) verts[i] += position;
Handles.DrawAAConvexPolygon(verts.ToArray());
verts.Clear();
}
}
private Vector3 VWrld(Vector3 pos) { return Vector3.Scale(pos, sizeW); }
private Vector3 VFill(Vector3 pos) { return Vector3.Scale(pos, sizeF); }
}
#endif
}