#if UNITY_EDITOR using FIMSpace.FEditor; using UnityEditor; #endif using System.Collections.Generic; using UnityEngine; using System; namespace FIMSpace.Generating { /// /// Implementation of spawning groups of prefabs with multiple OStamperSets on multiple spawn areas /// [AddComponentMenu("FImpossible Creations/Level Design/Object Stamp Multi Emitter", 2)] public partial class ObjectStampMultiEmitter : ObjectStampEmitterBase, IGenerating { public OStampPhysicalPlacementSetup PhysicalPlacement; public OStamperMultiSet MultiSet; public List Areas; public List 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() { } /// /// For physical simulation, call IG_CallAfterGenerated(); after MultiSpawn! /// 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; } /// /// Destroying already instantiated objects by multi emitter from scene /// public void ClearAlreadySpawned() { if (Spawned == null) Spawned = new List(); 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(); 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 _toPhysSimulate; public void IG_CallAfterGenerated() { if (PhysicalPlacement.Enabled == false) return; if (_toPhysSimulate == null) _toPhysSimulate = new List(); 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 Sets; public List Multiply; public bool PointsFoldout = true; public List 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 LatestSpawned = new List(); 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(); if (Get.Spawned == null) Get.Spawned = new List(); 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(), "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(); if (nArea.Multiply == null) nArea.Multiply = new List(); 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(); area.Multiply = new List(); } if (area.Points == null) area.Points = new List(); 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(); //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 verts = new List(); 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 verts = new List(); 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 }