595 lines
27 KiB
C#
595 lines
27 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using UnityEditor;
|
|
using static JBooth.MicroVerseCore.SelectionGrid;
|
|
|
|
namespace JBooth.MicroVerseCore
|
|
{
|
|
|
|
[CustomEditor(typeof(ObjectStamp))]
|
|
public class ObjectStampEditor : Editor
|
|
{
|
|
static GUIContent CScaleMultiplierAtBoundaries = new GUIContent("Size Multiplier on Boundaries", "As weight of an area is reduced, you can increase or decrease the scale of objects");
|
|
static GUIContent CDensityByWeight = new GUIContent("Density by weight", "Areas with less weight will spawn less objects");
|
|
static GUIContent CSink = new GUIContent("Sink", "Pushes the object down into the terrain");
|
|
static GUIContent CWeight = new GUIContent("Weight", "Increases the chance that this object gets picked over others based on their weighting. Note this is not a percent where 0 is no chance; if 2 tree's are in the system, one with a weight of 0 and the other 100, then there is a 1 in 101 chance that the tree with 0 weights is placed");
|
|
static GUIContent CWeightRange = new GUIContent("Weight Range", "Range of weight values that will allow objects to be spawned");
|
|
static GUIContent CApplyToAll = new GUIContent("Apply to All", "Apply the settings of the current object instance to all the others in the object stamp");
|
|
static GUIContent CAlignDownhill = new GUIContent("Align Downhill", "Aligns rotation of the object to point downhill");
|
|
Selectable[] selectableObjects;
|
|
List<int> selectedObjectIndexes = new List<int>();
|
|
int selectedObjectInstance = -1;
|
|
|
|
void LoadObjectIcons(List<GameObject> objs)
|
|
{
|
|
if (objs == null || objs.Count == 0)
|
|
{
|
|
selectableObjects = new Selectable[0];
|
|
}
|
|
else
|
|
{
|
|
// Locate the proto types asset preview textures
|
|
selectableObjects = new Selectable[objs.Count];
|
|
for (int i = 0; i < objs.Count; i++)
|
|
{
|
|
selectableObjects[i] = new Selectable();
|
|
|
|
Texture tex = AssetPreview.GetAssetPreview(objs[i]);
|
|
|
|
selectableObjects[i].image = tex != null ? tex : null;
|
|
selectableObjects[i].text = selectableObjects[i].tooltip = objs[i] != null ? objs[i].name : "Missing";
|
|
selectableObjects[i].active = true;
|
|
|
|
}
|
|
|
|
// select focused instance for multi-selection in selection grid
|
|
if (selectedObjectInstance >= 0 && selectedObjectInstance < selectableObjects.Length)
|
|
selectableObjects[selectedObjectInstance].focused = true;
|
|
}
|
|
}
|
|
|
|
private void OnSceneGUI()
|
|
{
|
|
var stamp = (ObjectStamp)target;
|
|
if (stamp.filterSet.falloffFilter.filterType == FalloffFilter.FilterType.PaintMask)
|
|
{
|
|
GUIUtil.DoPaintSceneView(stamp, SceneView.currentDrawingSceneView, stamp.filterSet.falloffFilter.paintMask, stamp.GetBounds(), stamp.transform);
|
|
}
|
|
}
|
|
|
|
public override void OnInspectorGUI()
|
|
{
|
|
GUIUtil.DrawHeaderLogo();
|
|
serializedObject.Update();
|
|
using var changeScope = new EditorGUI.ChangeCheckScope();
|
|
|
|
ObjectStamp os = (ObjectStamp)target;
|
|
|
|
if (os.GetComponentInParent<MicroVerse>() == null)
|
|
{
|
|
EditorGUILayout.HelpBox("Stamp is not under MicroVerse in the heriarchy, will have no effect", MessageType.Warning);
|
|
}
|
|
|
|
if (os.poissonDisk == null)
|
|
{
|
|
os.poissonDisk = GUIUtil.FindDefaultTexture("microverse_default_poissondisk");
|
|
EditorUtility.SetDirty(os);
|
|
}
|
|
using (new GUILayout.VerticalScope(GUIUtil.boxStyle))
|
|
{
|
|
EditorGUILayout.LabelField("Placement Settings:");
|
|
EditorGUILayout.PropertyField(serializedObject.FindProperty("hideInHierarchy"));
|
|
|
|
EditorGUILayout.BeginHorizontal();
|
|
{
|
|
SerializedProperty parentObjectProperty = serializedObject.FindProperty("parentObject");
|
|
|
|
EditorGUI.BeginChangeCheck();
|
|
EditorGUILayout.PropertyField(parentObjectProperty);
|
|
|
|
if (GUILayout.Button("New", EditorStyles.miniButton, GUILayout.Width(50)))
|
|
{
|
|
// get object stamp for the name creation
|
|
ObjectStamp editorTarget = (ObjectStamp)target;
|
|
|
|
// create new container
|
|
GameObject newContainer = new GameObject();
|
|
newContainer.name = editorTarget.name + " (Container)";
|
|
|
|
// ensure name uniqueness
|
|
GameObjectUtility.EnsureUniqueNameForSibling(newContainer);
|
|
|
|
// set as new value
|
|
parentObjectProperty.objectReferenceValue = newContainer;
|
|
}
|
|
}
|
|
EditorGUILayout.EndHorizontal();
|
|
|
|
EditorGUILayout.PropertyField(serializedObject.FindProperty("spawnAsPrefab"));
|
|
if (EditorGUI.EndChangeCheck())
|
|
{
|
|
os.destroyOnNextClear = true;
|
|
}
|
|
EditorGUILayout.PropertyField(serializedObject.FindProperty("seed"));
|
|
EditorGUILayout.PropertyField(serializedObject.FindProperty("poissonDisk"));
|
|
EditorGUILayout.PropertyField(serializedObject.FindProperty("poissonDiskStrength"));
|
|
EditorGUILayout.PropertyField(serializedObject.FindProperty("density"));
|
|
EditorGUILayout.PropertyField(serializedObject.FindProperty("occludeOthers"));
|
|
serializedObject.ApplyModifiedProperties();
|
|
if (os.occludeOthers)
|
|
{
|
|
EditorGUILayout.HelpBox("Stamp objects will not be included in signed distance field generation", MessageType.Info);
|
|
}
|
|
EditorGUILayout.PropertyField(serializedObject.FindProperty("occludedByOthers"));
|
|
GUIUtil.DoSDFFilter(serializedObject);
|
|
EditorGUILayout.PropertyField(serializedObject.FindProperty("minHeight"));
|
|
EditorGUILayout.PropertyField(serializedObject.FindProperty("heightModAmount"));
|
|
serializedObject.ApplyModifiedProperties();
|
|
if (os.heightModAmount != 0)
|
|
{
|
|
EditorGUILayout.PropertyField(serializedObject.FindProperty("heightModWidth"));
|
|
}
|
|
GUIUtil.DrawTextureLayerSelector(serializedObject.FindProperty("layer"), os.GetBounds(), "Texture Mod Layer");
|
|
serializedObject.ApplyModifiedProperties();
|
|
if (os.layer != null)
|
|
{
|
|
EditorGUILayout.PropertyField(serializedObject.FindProperty("layerWeight"));
|
|
EditorGUILayout.PropertyField(serializedObject.FindProperty("layerWidth"));
|
|
}
|
|
|
|
}
|
|
|
|
|
|
var otherTextureWeight = serializedObject.FindProperty("filterSet").FindPropertyRelative("otherTextureWeight");
|
|
var filters = serializedObject.FindProperty("filterSet").FindPropertyRelative("textureFilters");
|
|
var filtersEnabled = serializedObject.FindProperty("filterSet").FindPropertyRelative("textureFilterEnabled");
|
|
GUIUtil.DrawFilterSet(os, os.filterSet, otherTextureWeight, filters, filtersEnabled, os.transform, true);
|
|
|
|
LoadObjectIcons(os.prototypes);
|
|
|
|
EditorGUILayout.LabelField("Object variations to place");
|
|
|
|
|
|
// drop area
|
|
Rect prefabDropArea = GUILayoutUtility.GetRect(0.0f, 34.0f, GUIUtil.DropAreaStyle, GUILayout.ExpandWidth(true));
|
|
|
|
Color prevColor = GUI.backgroundColor;
|
|
GUI.color = GUIUtil.DropAreaBackgroundColor;
|
|
GUI.Box(prefabDropArea, "Drop Prefabs Here", GUIUtil.DropAreaStyle);
|
|
GUI.color = prevColor;
|
|
|
|
switch (Event.current.type)
|
|
{
|
|
case EventType.DragUpdated:
|
|
case EventType.DragPerform:
|
|
|
|
if (prefabDropArea.Contains(Event.current.mousePosition))
|
|
{
|
|
|
|
DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
|
|
|
|
if (Event.current.type == EventType.DragPerform)
|
|
{
|
|
DragAndDrop.AcceptDrag();
|
|
|
|
foreach (Object droppedObject in DragAndDrop.objectReferences)
|
|
{
|
|
// Debug.Log($"Dropped {droppedObject}");
|
|
|
|
if (!(droppedObject is GameObject))
|
|
{
|
|
Debug.LogError("Not a gameobject: " + droppedObject);
|
|
continue;
|
|
}
|
|
|
|
ObjectManager objectManager = new ObjectManager(os, -1, os.prototypes, os.randomizations);
|
|
objectManager.SetObject(droppedObject as GameObject);
|
|
objectManager.DoApply();
|
|
}
|
|
|
|
EditorUtility.SetDirty(os);
|
|
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
// get current active state
|
|
for (int i = 0; i < selectableObjects.Length; i++)
|
|
{
|
|
selectableObjects[i].active = !os.randomizations[i].disabled;
|
|
}
|
|
|
|
// grid selection
|
|
bool changed = SelectionGrid.ShowSelectionGrid(selectedObjectIndexes, selectableObjects, 128);
|
|
|
|
// set the attributes of the objects in case anything changed on the selection grid
|
|
if (changed)
|
|
{
|
|
for (int i = 0; i < selectableObjects.Length; i++)
|
|
{
|
|
var randoms = os.randomizations[i];
|
|
|
|
randoms.disabled = !selectableObjects[i].active;
|
|
|
|
os.randomizations[i] = randoms;
|
|
}
|
|
|
|
EditorUtility.SetDirty(os);
|
|
}
|
|
|
|
bool multiObjectEditMode = selectedObjectIndexes.Count > 1;
|
|
|
|
|
|
GUILayout.BeginHorizontal();
|
|
|
|
selectedObjectInstance = selectedObjectIndexes.Count > 0 ? selectedObjectIndexes[0] : -1;
|
|
|
|
if (GUILayout.Button("Remove"))
|
|
{
|
|
// get top index, we need to select any cell after all selected were removed
|
|
int topIndex = selectedObjectIndexes.Count > 0 ? selectedObjectIndexes[0] : -1;
|
|
|
|
// iterate backwards for multi-delete
|
|
selectedObjectIndexes.Reverse();
|
|
|
|
// remove cells
|
|
foreach (int index in selectedObjectIndexes)
|
|
{
|
|
if (index >= 0 && os.prototypes.Count > index)
|
|
{
|
|
os.prototypes.RemoveAt(index);
|
|
os.randomizations.RemoveAt(index);
|
|
}
|
|
}
|
|
|
|
EditorUtility.SetDirty(os);
|
|
|
|
// pre-select cell: either previous one of the selected cell or the first one
|
|
int newSelectedIndex = topIndex >= 0 ? topIndex - 1 : -1;
|
|
if (newSelectedIndex < 0 && selectedObjectIndexes.Count > 0)
|
|
{
|
|
newSelectedIndex = 0;
|
|
}
|
|
|
|
selectedObjectIndexes.Clear();
|
|
selectedObjectIndexes.Add(newSelectedIndex);
|
|
}
|
|
|
|
GUI.enabled = true;
|
|
|
|
if (GUILayout.Button("Clear"))
|
|
{
|
|
os.prototypes.Clear();
|
|
os.randomizations.Clear();
|
|
EditorUtility.SetDirty(os);
|
|
}
|
|
|
|
GUILayout.EndHorizontal();
|
|
|
|
if (os.prototypes.Count == 0)
|
|
{
|
|
EditorGUILayout.HelpBox("Please add one or more objects to begin", MessageType.Info);
|
|
}
|
|
else
|
|
{
|
|
using (new GUILayout.VerticalScope(GUIUtil.boxStyle))
|
|
{
|
|
EditorGUILayout.LabelField("Randomization:");
|
|
if (os.prototypes.Count > 0 && os.randomizations.Count == os.prototypes.Count && selectedObjectInstance >= 0 && selectedObjectInstance < os.randomizations.Count)
|
|
{
|
|
// prototype
|
|
EditorGUI.BeginChangeCheck();
|
|
|
|
if (multiObjectEditMode)
|
|
{
|
|
EditorGUILayout.LabelField("Prefab", "<Multiple Objects>");
|
|
}
|
|
else
|
|
{
|
|
Object prefab = EditorGUILayout.ObjectField("Prefab", os.prototypes[selectedObjectInstance], typeof(GameObject), true);
|
|
|
|
if (EditorGUI.EndChangeCheck())
|
|
{
|
|
ObjectManager objectManager = new ObjectManager(os, selectedObjectInstance, os.prototypes, os.randomizations);
|
|
objectManager.SetObject(prefab as GameObject);
|
|
objectManager.DoApply();
|
|
}
|
|
|
|
}
|
|
|
|
// details
|
|
|
|
EditorGUI.BeginChangeCheck();
|
|
|
|
var randoms = os.randomizations[selectedObjectInstance];
|
|
float weight = EditorGUILayout.Slider(CWeight, randoms.weight, 0, 100);
|
|
Vector2 weightRange = EditorGUILayout.Vector2Field(CWeightRange, randoms.weightRange);
|
|
|
|
|
|
var rotLock = randoms.rotationLock;
|
|
|
|
GUILayout.BeginHorizontal();
|
|
{
|
|
rotLock = (ObjectStamp.Lock)EditorGUILayout.EnumPopup("Rotation Lock", randoms.rotationLock);
|
|
|
|
|
|
// right align the quick buttons
|
|
GUILayout.FlexibleSpace();
|
|
|
|
if (GUILayout.Button("X", EditorStyles.miniButton))
|
|
{
|
|
randoms.rotationRangeX = new Vector2(-180, 180);
|
|
randoms.rotationRangeY = Vector2.zero;
|
|
randoms.rotationRangeZ = Vector2.zero;
|
|
}
|
|
if (GUILayout.Button("Y", EditorStyles.miniButton))
|
|
{
|
|
randoms.rotationRangeX = Vector2.zero;
|
|
randoms.rotationRangeY = new Vector2(-180, 180);
|
|
randoms.rotationRangeZ = Vector2.zero;
|
|
}
|
|
if (GUILayout.Button("Z", EditorStyles.miniButton))
|
|
{
|
|
randoms.rotationRangeX = Vector2.zero;
|
|
randoms.rotationRangeY = Vector2.zero;
|
|
randoms.rotationRangeZ = new Vector2(-180, 180);
|
|
}
|
|
if (GUILayout.Button("XYZ", EditorStyles.miniButton))
|
|
{
|
|
randoms.rotationRangeX = new Vector2(-180, 180);
|
|
randoms.rotationRangeY = new Vector2(-180, 180);
|
|
randoms.rotationRangeZ = new Vector2(-180, 180);
|
|
}
|
|
|
|
|
|
}
|
|
GUILayout.EndHorizontal();
|
|
|
|
var rotX = randoms.rotationRangeX;
|
|
var rotY = randoms.rotationRangeY;
|
|
var rotZ = randoms.rotationRangeZ;
|
|
switch (rotLock)
|
|
{
|
|
case ObjectStamp.Lock.None:
|
|
GUIUtil.DrawMinMax(new GUIContent("Rotation X"), ref rotX.x, ref rotX.y, -180, 180);
|
|
GUIUtil.DrawMinMax(new GUIContent("Rotation Y"), ref rotY.x, ref rotY.y, -180, 180);
|
|
GUIUtil.DrawMinMax(new GUIContent("Rotation Z"), ref rotZ.x, ref rotZ.y, -180, 180);
|
|
break;
|
|
case ObjectStamp.Lock.XY:
|
|
GUIUtil.DrawMinMax(new GUIContent("Rotation XY"), ref rotX.x, ref rotX.y, -180, 180);
|
|
GUIUtil.DrawMinMax(new GUIContent("Rotation Z"), ref rotZ.x, ref rotZ.y, -180, 180);
|
|
rotY = rotX;
|
|
break;
|
|
case ObjectStamp.Lock.XZ:
|
|
GUIUtil.DrawMinMax(new GUIContent("Rotation XZ"), ref rotX.x, ref rotX.y, -180, 180);
|
|
GUIUtil.DrawMinMax(new GUIContent("Rotation Y"), ref rotY.x, ref rotY.y, -180, 180);
|
|
rotZ = rotX;
|
|
break;
|
|
case ObjectStamp.Lock.YZ:
|
|
GUIUtil.DrawMinMax(new GUIContent("Rotation X"), ref rotX.x, ref rotX.y, -180, 180);
|
|
GUIUtil.DrawMinMax(new GUIContent("Rotation YZ"), ref rotY.x, ref rotY.y, -180, 180);
|
|
rotZ = rotY;
|
|
break;
|
|
case ObjectStamp.Lock.XYZ:
|
|
GUIUtil.DrawMinMax(new GUIContent("Rotation XYZ"), ref rotX.x, ref rotX.y, -180, 180);
|
|
rotY = rotX;
|
|
rotZ = rotX;
|
|
break;
|
|
}
|
|
|
|
var slopeAlignment = EditorGUILayout.Slider("Slope Alignment", randoms.slopeAlignment, 0, 1);
|
|
var alignDownhill = EditorGUILayout.Toggle(CAlignDownhill, randoms.alignDownhill);
|
|
|
|
// scale
|
|
var scaleLock = (ObjectStamp.Lock)EditorGUILayout.EnumPopup("Scale Lock", randoms.scaleLock);
|
|
|
|
var scaleX = randoms.scaleRangeX;
|
|
var scaleY = randoms.scaleRangeY;
|
|
var scaleZ = randoms.scaleRangeZ;
|
|
|
|
switch (scaleLock)
|
|
{
|
|
case ObjectStamp.Lock.None:
|
|
scaleX = GUIUtil.ScaleRange("Scale X", ref randoms.scaleRangeX);
|
|
scaleY = GUIUtil.ScaleRange("Scale Y", ref randoms.scaleRangeY);
|
|
scaleZ = GUIUtil.ScaleRange("Scale Z", ref randoms.scaleRangeZ);
|
|
break;
|
|
case ObjectStamp.Lock.XY:
|
|
scaleX = GUIUtil.ScaleRange("Scale XY", ref randoms.scaleRangeX);
|
|
scaleY = scaleX;
|
|
scaleZ = GUIUtil.ScaleRange("Scale Z", ref randoms.scaleRangeZ);
|
|
break;
|
|
case ObjectStamp.Lock.XZ:
|
|
scaleX = GUIUtil.ScaleRange("Scale XZ", ref randoms.scaleRangeX);
|
|
scaleY = GUIUtil.ScaleRange("Scale Y", ref randoms.scaleRangeY);
|
|
scaleZ = scaleX;
|
|
break;
|
|
case ObjectStamp.Lock.YZ:
|
|
scaleX = GUIUtil.ScaleRange("Scale X", ref randoms.scaleRangeX);
|
|
scaleY = GUIUtil.ScaleRange("Scale YZ", ref randoms.scaleRangeY);
|
|
scaleZ = scaleY;
|
|
break;
|
|
case ObjectStamp.Lock.XYZ:
|
|
scaleX = GUIUtil.ScaleRange("Scale X", ref randoms.scaleRangeX);
|
|
scaleY = scaleX;
|
|
scaleZ = scaleX;
|
|
break;
|
|
}
|
|
|
|
float scaleAtBoundaries = EditorGUILayout.Slider(CScaleMultiplierAtBoundaries, randoms.scaleMultiplierAtBoundaries, 0.2f, 4.0f);
|
|
bool densityByWeight = EditorGUILayout.Toggle(CDensityByWeight, randoms.densityByWeight);
|
|
Vector2 sink = EditorGUILayout.Vector2Field(CSink, randoms.sink);
|
|
|
|
if (EditorGUI.EndChangeCheck())
|
|
{
|
|
Undo.RegisterCompleteObjectUndo(os, "Object Parameter Change");
|
|
|
|
foreach (var targetIndex in selectedObjectIndexes)
|
|
{
|
|
var target = os.randomizations[targetIndex];
|
|
|
|
if (weight != randoms.weight) { target.weight = weight; }
|
|
if (weightRange != randoms.weightRange) { target.weightRange = weightRange; }
|
|
|
|
if (target.scaleRangeX != scaleX) target.scaleRangeX = scaleX;
|
|
if (target.scaleRangeY != scaleY) target.scaleRangeY = scaleY;
|
|
if (target.scaleRangeZ != scaleZ) target.scaleRangeZ = scaleZ;
|
|
|
|
if (target.rotationRangeX != rotX) target.rotationRangeX = rotX;
|
|
if (target.rotationRangeY != rotY) target.rotationRangeY = rotY;
|
|
if (target.rotationRangeZ != rotZ) target.rotationRangeZ = rotZ;
|
|
|
|
if (target.scaleLock != scaleLock) target.scaleLock = scaleLock;
|
|
if (target.rotationLock != rotLock) target.rotationLock = rotLock;
|
|
if (target.alignDownhill != alignDownhill) target.alignDownhill = alignDownhill;
|
|
|
|
if (target.slopeAlignment != slopeAlignment) target.slopeAlignment = slopeAlignment;
|
|
if (target.sink != sink) target.sink = sink;
|
|
if (target.scaleMultiplierAtBoundaries != scaleAtBoundaries) target.scaleMultiplierAtBoundaries = scaleAtBoundaries;
|
|
if (target.densityByWeight != densityByWeight) target.densityByWeight = densityByWeight;
|
|
|
|
os.randomizations[targetIndex] = target;
|
|
}
|
|
|
|
EditorUtility.SetDirty(os);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
// mini toolbar: apply settings to all
|
|
EditorGUILayout.BeginHorizontal();
|
|
{
|
|
GUILayout.FlexibleSpace();
|
|
if (GUILayout.Button(CApplyToAll, EditorStyles.miniButton, GUILayout.ExpandWidth(false)))
|
|
{
|
|
if (selectedObjectInstance >= 0 && selectedObjectInstance < os.randomizations.Count)
|
|
{
|
|
|
|
Undo.RegisterCompleteObjectUndo(os, "Apply Object Parameters to All");
|
|
|
|
List<int> allIndexes = new List<int>();
|
|
|
|
for (int i = 0; i < os.randomizations.Count; i++)
|
|
{
|
|
allIndexes.Add(i);
|
|
}
|
|
|
|
ApplySettings(selectedObjectInstance, allIndexes);
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
EditorGUILayout.EndHorizontal();
|
|
}
|
|
|
|
serializedObject.ApplyModifiedProperties();
|
|
|
|
if (changeScope.changed)
|
|
{
|
|
MicroVerse.instance?.Invalidate(os.GetBounds(), MicroVerse.InvalidateType.All);
|
|
}
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// Apply the settings of the object at a source index to all at the given target indexes
|
|
/// </summary>
|
|
/// <param name="sourceIndex"></param>
|
|
/// <param name="targetIndexes"></param>
|
|
private void ApplySettings(int sourceIndex, List<int> targetIndexes)
|
|
{
|
|
ObjectStamp os = (ObjectStamp)target;
|
|
|
|
var source = os.randomizations[sourceIndex];
|
|
|
|
foreach (int targetIndex in targetIndexes)
|
|
{
|
|
if (sourceIndex == targetIndex)
|
|
continue;
|
|
|
|
var target = os.randomizations[targetIndex];
|
|
|
|
// target.disabled = source.disabled; // don't use the active flag anymore, it's depending on the selection
|
|
target.weight = source.weight;
|
|
target.weightRange = source.weightRange;
|
|
|
|
target.scaleRangeX = source.scaleRangeX;
|
|
target.scaleRangeY = source.scaleRangeY;
|
|
target.scaleRangeZ = source.scaleRangeZ;
|
|
|
|
target.rotationRangeX = source.rotationRangeX;
|
|
target.rotationRangeY = source.rotationRangeY;
|
|
target.rotationRangeZ = source.rotationRangeZ;
|
|
|
|
target.scaleLock = source.scaleLock;
|
|
target.rotationLock = source.rotationLock;
|
|
|
|
target.slopeAlignment = source.slopeAlignment;
|
|
target.sink = source.sink;
|
|
target.scaleMultiplierAtBoundaries = source.scaleMultiplierAtBoundaries;
|
|
target.densityByWeight = source.densityByWeight;
|
|
|
|
os.randomizations[targetIndex] = target;
|
|
}
|
|
|
|
}
|
|
|
|
private void OnEnable()
|
|
{
|
|
EditorApplication.update += OnUpdate;
|
|
SceneView.duringSceneGui += OnSceneRepaint;
|
|
}
|
|
|
|
private void OnDisable()
|
|
{
|
|
EditorApplication.update -= OnUpdate;
|
|
SceneView.duringSceneGui -= OnSceneRepaint;
|
|
}
|
|
|
|
static Texture2D overlayTex;
|
|
private void OnSceneRepaint(SceneView sceneView)
|
|
{
|
|
RenderTexture.active = sceneView.camera.activeTexture;
|
|
if (MicroVerse.instance != null)
|
|
{
|
|
if (overlayTex == null)
|
|
{
|
|
overlayTex = Resources.Load<Texture2D>("microverse_stamp_tree");
|
|
}
|
|
var terrains = MicroVerse.instance.terrains;
|
|
var hs = (target as ObjectStamp);
|
|
if (hs == null) return;
|
|
Color color = Color.green;
|
|
if (MicroVerse.instance != null)
|
|
{
|
|
color = MicroVerse.instance.options.colors.objectStampColor;
|
|
}
|
|
PreviewRenderer.DrawStampPreview(hs, terrains, hs.transform, hs.filterSet.falloffFilter, color, overlayTex);
|
|
}
|
|
}
|
|
|
|
|
|
private void OnUpdate()
|
|
{
|
|
foreach (var target in targets)
|
|
{
|
|
if (target == null)
|
|
continue;
|
|
var objectPlacement = (ObjectStamp)target;
|
|
if (objectPlacement != null && objectPlacement.transform.hasChanged)
|
|
{
|
|
objectPlacement.transform.hasChanged = false;
|
|
var r = objectPlacement.transform.localRotation.eulerAngles;
|
|
r.z = 0;
|
|
objectPlacement.transform.localRotation = Quaternion.Euler(r);
|
|
MicroVerse.instance?.Invalidate(objectPlacement.GetBounds(), MicroVerse.InvalidateType.All);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|