737 lines
37 KiB
C#
737 lines
37 KiB
C#
#if UNITY_EDITOR
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
using UnityEngine.UIElements;
|
|
|
|
namespace GSpawn
|
|
{
|
|
public class CurveObjectSpawnUI : PluginUI
|
|
{
|
|
[NonSerialized]
|
|
private ProfileSelectionUI<CurveObjectSpawnSettingsProfileDb, CurveObjectSpawnSettingsProfile> _curveCreationSettingsProfileSelectionUI;
|
|
|
|
[SerializeField]
|
|
private ListViewState _curveViewState;
|
|
[NonSerialized]
|
|
private ListView<UIObjectSpawnCurveItem, ObjectSpawnCurve> _curveView;
|
|
[NonSerialized]
|
|
private EntitySearchField _curveSearchField;
|
|
[NonSerialized]
|
|
private Button _useDefaultsBtn;
|
|
[SerializeField]
|
|
private UISection _curveCreationSettingsSection;
|
|
[SerializeField]
|
|
private UISection _curvesSection;
|
|
[NonSerialized]
|
|
private VisualElement _createCurveContainer;
|
|
[NonSerialized]
|
|
private bool _deleteCurveObjects;
|
|
[NonSerialized]
|
|
private List<ObjectSpawnCurve> _curveBuffer = new List<ObjectSpawnCurve>();
|
|
[NonSerialized]
|
|
private List<PluginGuid> _curveIdBuffer = new List<PluginGuid>();
|
|
[NonSerialized]
|
|
private List<CurveObjectSpawnSettings> _curveSpawnSettingsBuffer = new List<CurveObjectSpawnSettings>();
|
|
|
|
public static CurveObjectSpawnUI instance { get { return GSpawn.active.curveObjectSpawnUI; } }
|
|
|
|
public void getVisibleSelectedCurves(List<ObjectSpawnCurve> curves)
|
|
{
|
|
if (_curveView == null) return;
|
|
|
|
curves.Clear();
|
|
var selectedCurves = new List<ObjectSpawnCurve>();
|
|
_curveView.getVisibleSelectedItemData(selectedCurves);
|
|
|
|
foreach (var itemData in selectedCurves)
|
|
curves.Add(itemData);
|
|
}
|
|
|
|
public void getSelectedCurves(List<ObjectSpawnCurve> curves)
|
|
{
|
|
if (_curveView == null) return;
|
|
|
|
curves.Clear();
|
|
var selectedCurves = new List<ObjectSpawnCurve>();
|
|
_curveView.getSelectedItemData(selectedCurves);
|
|
|
|
foreach (var itemData in selectedCurves)
|
|
curves.Add(itemData);
|
|
}
|
|
|
|
public void setSelectedCurve(ObjectSpawnCurve curve)
|
|
{
|
|
if (_curveView == null) return;
|
|
|
|
_curveView.setAllItemsSelected(false, false, false);
|
|
_curveView.setItemSelected(curve.guid, true, false);
|
|
}
|
|
|
|
public void setSelectedCurves(List<ObjectSpawnCurve> curves)
|
|
{
|
|
if (_curveView == null) return;
|
|
|
|
_curveView.setAllItemsSelected(false, false, false);
|
|
UIObjectSpawnCurveItem.getItemIds(curves, _curveIdBuffer);
|
|
_curveView.setItemsSelected(_curveIdBuffer, true, false, false);
|
|
}
|
|
|
|
protected override void onBuild()
|
|
{
|
|
contentContainer.style.flexGrow = 1.0f;
|
|
|
|
_curveCreationSettingsSection.build("Curve Creation", TexturePool.instance.settings, true, contentContainer);
|
|
|
|
_curveCreationSettingsProfileSelectionUI = new ProfileSelectionUI<CurveObjectSpawnSettingsProfileDb, CurveObjectSpawnSettingsProfile>();
|
|
_curveCreationSettingsProfileSelectionUI.build(CurveObjectSpawnSettingsProfileDb.instance, "curve object spawn settings", _curveCreationSettingsSection.contentContainer);
|
|
createCreateCurveUI(_curveCreationSettingsSection.contentContainer);
|
|
|
|
UI.createUISectionRowSeparator(contentContainer);
|
|
_curvesSection.build("Curves", TexturePool.instance.curveSpawn, true, contentContainer);
|
|
createSearchToolbar(_curvesSection.contentContainer);
|
|
createCurveViewToolbar(_curvesSection.contentContainer);
|
|
createCurveView(_curvesSection.contentContainer);
|
|
populateCurveView();
|
|
createCurveSettingsControls(_curvesSection.contentContainer);
|
|
}
|
|
|
|
protected override void onRefresh()
|
|
{
|
|
if (_curveCreationSettingsProfileSelectionUI != null)
|
|
_curveCreationSettingsProfileSelectionUI.refresh();
|
|
|
|
createCreateCurveUI(_curveCreationSettingsSection.contentContainer);
|
|
populateCurveView();
|
|
}
|
|
|
|
protected override void onEnabled()
|
|
{
|
|
if (_curveViewState == null)
|
|
{
|
|
_curveViewState = ScriptableObject.CreateInstance<ListViewState>();
|
|
_curveViewState.name = GetType().Name + "_CurveViewState";
|
|
}
|
|
if (_curveCreationSettingsSection == null)
|
|
_curveCreationSettingsSection = ScriptableObject.CreateInstance<UISection>();
|
|
if (_curvesSection == null)
|
|
_curvesSection = ScriptableObject.CreateInstance<UISection>();
|
|
|
|
if (FileSystem.folderExists(PluginFolders.curveObjectSpawnSettingsProfiles))
|
|
CurveObjectSpawnSettingsProfileDb.instance.activeProfileChanged += onActiveCurveCreationSettingsProfileChanged;
|
|
}
|
|
|
|
protected override void onDisabled()
|
|
{
|
|
if (FileSystem.folderExists(PluginFolders.curveObjectSpawnSettingsProfiles))
|
|
CurveObjectSpawnSettingsProfileDb.instance.activeProfileChanged -= onActiveCurveCreationSettingsProfileChanged;
|
|
}
|
|
|
|
protected override void onUndoRedo()
|
|
{
|
|
if (_curveCreationSettingsProfileSelectionUI != null)
|
|
_curveCreationSettingsProfileSelectionUI.refresh();
|
|
|
|
populateCurveView();
|
|
}
|
|
|
|
protected override void onDestroy()
|
|
{
|
|
ScriptableObjectEx.destroyImmediate(_curvesSection);
|
|
ScriptableObjectEx.destroyImmediate(_curveCreationSettingsSection);
|
|
ScriptableObjectEx.destroyImmediate(_curveViewState);
|
|
}
|
|
|
|
private void createCreateCurveUI(VisualElement parent)
|
|
{
|
|
if (_createCurveContainer != null &&
|
|
parent.Contains(_createCurveContainer))
|
|
{
|
|
parent.Remove(_createCurveContainer);
|
|
}
|
|
|
|
_createCurveContainer = new VisualElement();
|
|
parent.Add(_createCurveContainer);
|
|
CurveObjectSpawnSettingsProfileDb.instance.activeProfile.settings.buildUI(_createCurveContainer);
|
|
|
|
var createCurveBtnAndField = new VisualElement();
|
|
_createCurveContainer.Add(createCurveBtnAndField);
|
|
createCurveBtnAndField.style.flexDirection = FlexDirection.Row;
|
|
|
|
TextField curveObjectNameField = new TextField();
|
|
curveObjectNameField.style.flexGrow = 1.0f;
|
|
Button createNewCurveBtn = new Button();
|
|
createNewCurveBtn.text = "Create curve";
|
|
createNewCurveBtn.tooltip = "Create a new spawn curve by placing control points in the scene.";
|
|
createNewCurveBtn.style.width = UIValues.useDefaultsButtonWidth;
|
|
createNewCurveBtn.clicked += () => { ObjectSpawn.instance.curveObjectSpawn.createNewCurve(curveObjectNameField.text); };
|
|
createCurveBtnAndField.Add(createNewCurveBtn);
|
|
createCurveBtnAndField.Add(curveObjectNameField);
|
|
}
|
|
|
|
private void onActiveCurveCreationSettingsProfileChanged(CurveObjectSpawnSettingsProfile newActiveProfile)
|
|
{
|
|
onRefresh();
|
|
}
|
|
|
|
private void createSearchToolbar(VisualElement parent)
|
|
{
|
|
var toolbar = UI.createStylizedToolbar(parent);
|
|
|
|
_curveSearchField = new EntitySearchField(toolbar, (entityNames) =>
|
|
{ ObjectSpawnCurveDb.instance.getCurveNames(entityNames, null); },
|
|
(name) => { _curveView.filterItems(filterCurve); });
|
|
}
|
|
|
|
private bool filterCurve(ObjectSpawnCurve curve)
|
|
{
|
|
if (!_curveSearchField.matchName(curve.curveName)) return false;
|
|
return true;
|
|
}
|
|
|
|
private void createCurveViewToolbar(VisualElement parent)
|
|
{
|
|
var toolbar = UI.createStylizedToolbar(parent);
|
|
|
|
var btn = UI.createToolbarButton(TexturePool.instance.refresh, UI.ButtonStyle.Push, UIValues.smallToolbarButtonSize, toolbar);
|
|
btn.tooltip = "Refresh selected curves.";
|
|
btn.clicked += () =>
|
|
{
|
|
if (_curveView != null)
|
|
{
|
|
getVisibleSelectedCurves(_curveBuffer);
|
|
foreach (var curve in _curveBuffer)
|
|
curve.refresh(ObjectSpawnCurveRefreshReason.Refresh);
|
|
}
|
|
};
|
|
UI.useDefaultMargins(btn);
|
|
|
|
btn = UI.createToolbarButton(TexturePool.instance.sync, UI.ButtonStyle.Push, UIValues.smallToolbarButtonSize, toolbar);
|
|
btn.tooltip = "Sync selected curve settings with curve creation settings.";
|
|
btn.clicked += () =>
|
|
{
|
|
if (_curveView != null)
|
|
{
|
|
getVisibleSelectedCurves(_curveBuffer);
|
|
foreach (var curve in _curveBuffer)
|
|
{
|
|
curve.settings.copy(CurveObjectSpawnSettingsProfileDb.instance.activeProfile.settings);
|
|
}
|
|
}
|
|
};
|
|
UI.useDefaultMargins(btn);
|
|
|
|
btn = UI.createToolbarButton(TexturePool.instance.delete, UI.ButtonStyle.Push, UIValues.smallToolbarButtonSize, toolbar);
|
|
btn.tooltip = "Delete selected curves.";
|
|
btn.clicked += () =>
|
|
{
|
|
if (_curveView != null) _curveView.deleteSelectedItems();
|
|
};
|
|
UI.useDefaultMargins(btn);
|
|
}
|
|
|
|
private void createCurveView(VisualElement parent)
|
|
{
|
|
_curveView = new ListView<UIObjectSpawnCurveItem, ObjectSpawnCurve>(_curveViewState, parent);
|
|
_curveView.canDelete = true;
|
|
_curveView.canRenameItems = true;
|
|
_curveView.canMultiSelect = true;
|
|
|
|
_curveView.canDeleteSelectedItems += onCanDeleteSelectedItems;
|
|
_curveView.selectedItemsWillBeDeleted += onSelectedCurveItemsWillBeDeleted;
|
|
_curveView.selectionChanged += onSelectionChanged;
|
|
_curveView.selectionDeleted += onSelectionDeleted;
|
|
|
|
_curveView.style.setBorderWidth(1.0f);
|
|
_curveView.style.setBorderColor(UIValues.listViewBorderColor);
|
|
_curveView.style.flexGrow = 1.0f;
|
|
_curveView.style.height = 200.0f;
|
|
}
|
|
|
|
private void createCurveSettingsControls(VisualElement parent)
|
|
{
|
|
const float labelWidth = 130.0f;
|
|
IMGUIContainer imGUIContainer = UI.createIMGUIContainer(parent);
|
|
imGUIContainer.style.flexGrow = 1.0f;
|
|
imGUIContainer.style.marginTop = 1.0f;
|
|
imGUIContainer.onGUIHandler = () =>
|
|
{
|
|
getVisibleSelectedCurves(_curveBuffer);
|
|
_curveSpawnSettingsBuffer.Clear();
|
|
foreach (var curve in _curveBuffer)
|
|
_curveSpawnSettingsBuffer.Add(curve.settings);
|
|
|
|
if (_curveSpawnSettingsBuffer.Count == 0)
|
|
{
|
|
if (_useDefaultsBtn.isDisplayVisible()) _useDefaultsBtn.setDisplayVisible(false);
|
|
imGUIContainer.style.marginLeft = 0.0f;
|
|
EditorGUILayout.HelpBox("No curves selected. Select curves in order to change their settings.", MessageType.Info);
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
if (!_useDefaultsBtn.isDisplayVisible()) _useDefaultsBtn.setDisplayVisible(true);
|
|
imGUIContainer.style.marginLeft = 3.0f;
|
|
|
|
var guiContent = new GUIContent();
|
|
EditorUIEx.saveLabelWidth();
|
|
EditorUIEx.saveShowMixedValue();
|
|
EditorGUIUtility.labelWidth = labelWidth;
|
|
var diff = CurveObjectSpawnSettings.checkDiff(_curveSpawnSettingsBuffer);
|
|
|
|
#pragma warning disable 0612
|
|
// Curve prefab profile
|
|
EditorGUI.BeginChangeCheck();
|
|
string profileName = diff.curvePrefabProfileName ? string.Empty : _curveSpawnSettingsBuffer[0].curvePrefabProfileName;
|
|
string newProfileName = EditorUIEx.profileNameSelectionField<CurvePrefabProfileDb, CurvePrefabProfile>
|
|
(CurvePrefabProfileDb.instance, "Curve prefab profile", labelWidth, profileName, diff.curvePrefabProfileName);
|
|
if (EditorGUI.EndChangeCheck())
|
|
{
|
|
foreach (var s in _curveSpawnSettingsBuffer)
|
|
s.curvePrefabProfileName = newProfileName;
|
|
|
|
foreach (var c in _curveBuffer)
|
|
c.refresh(ObjectSpawnCurveRefreshReason.CurvePrefabProfileChanged);
|
|
}
|
|
|
|
// Curve up axis
|
|
/*
|
|
EditorGUILayout.Separator();
|
|
CurveObjectSpawnUpAxis curveUpAxis = diff.curveUpAxis ? CurveObjectSpawnUpAxis.UIMixed : _curveSpawnSettingsBuffer[0].curveUpAxis;
|
|
EditorGUI.showMixedValue = diff.curveUpAxis;
|
|
EditorGUI.BeginChangeCheck();
|
|
guiContent.text = "Up axis";
|
|
guiContent.tooltip = "The curve up axis used when spawning objects. It specifies which way is up.";
|
|
CurveObjectSpawnUpAxis newCurveUpAxis = (CurveObjectSpawnUpAxis)EditorGUILayout.EnumPopup(guiContent, curveUpAxis, GUILayout.ExpandWidth(true));
|
|
if (EditorGUI.EndChangeCheck())
|
|
{
|
|
foreach (var s in _curveSpawnSettingsBuffer)
|
|
s.curveUpAxis = newCurveUpAxis;
|
|
|
|
foreach (var c in _curveBuffer)
|
|
c.refresh(ObjectSpawnCurveRefreshReason.Other);
|
|
}*/
|
|
|
|
// Invert up axis
|
|
/*
|
|
bool invertUpAxis = _curveSpawnSettingsBuffer[0].invertUpAxis;
|
|
EditorGUI.showMixedValue = diff.invertUpAxis;
|
|
EditorGUI.BeginChangeCheck();
|
|
guiContent.text = "Invert axis";
|
|
guiContent.tooltip = "If this is checked, the up axis will be inverted.";
|
|
bool newInvertAxis = EditorGUILayout.Toggle(guiContent, invertUpAxis, GUILayout.ExpandWidth(true));
|
|
if (EditorGUI.EndChangeCheck())
|
|
{
|
|
foreach (var s in _curveSpawnSettingsBuffer)
|
|
s.invertUpAxis = newInvertAxis;
|
|
|
|
foreach (var c in _curveBuffer)
|
|
c.refresh(ObjectSpawnCurveRefreshReason.Other);
|
|
}*/
|
|
|
|
// Avoid overlaps
|
|
bool avoidOverlaps = _curveSpawnSettingsBuffer[0].avoidOverlaps;
|
|
EditorGUI.showMixedValue = diff.avoidOverlaps;
|
|
EditorGUI.BeginChangeCheck();
|
|
guiContent.text = "Avoid overlaps";
|
|
guiContent.tooltip = "If this is checked, no objects will be created in places where they would overlap with already existing objects. " +
|
|
"Note: The checks are performed against objects that are not part of the curve. Objects that are part of the curve, are not affected and may overlap.";
|
|
bool newAvoidOverlaps = EditorGUILayout.Toggle(guiContent, avoidOverlaps, GUILayout.ExpandWidth(true));
|
|
if (EditorGUI.EndChangeCheck())
|
|
{
|
|
foreach (var s in _curveSpawnSettingsBuffer)
|
|
s.avoidOverlaps = newAvoidOverlaps;
|
|
|
|
foreach (var c in _curveBuffer)
|
|
c.refresh(ObjectSpawnCurveRefreshReason.Other);
|
|
}
|
|
|
|
// Volumeless object size
|
|
float vlmsObjectSize = _curveSpawnSettingsBuffer[0].volumlessObjectSize;
|
|
EditorGUI.showMixedValue = diff.volumelessObjectSize;
|
|
EditorGUI.BeginChangeCheck();
|
|
guiContent.text = "Volumeless object size";
|
|
guiContent.tooltip = "The size that should be used for objects that don't have a volume.";
|
|
float newVlmsObjectSize = EditorGUILayout.FloatField(guiContent, vlmsObjectSize, GUILayout.ExpandWidth(true));
|
|
if (EditorGUI.EndChangeCheck())
|
|
{
|
|
foreach (var s in _curveSpawnSettingsBuffer)
|
|
s.volumlessObjectSize = newVlmsObjectSize;
|
|
|
|
foreach (var c in _curveBuffer)
|
|
c.refresh(ObjectSpawnCurveRefreshReason.Other);
|
|
}
|
|
|
|
// Step
|
|
/*
|
|
float step = _curveSpawnSettingsBuffer[0].step;
|
|
EditorGUI.showMixedValue = diff.step;
|
|
EditorGUI.BeginChangeCheck();
|
|
guiContent.text = "Step";
|
|
guiContent.tooltip = "When spawning objects along a curve, the curve will be approximated " +
|
|
"by taking sample points using this step value. The smaller the value the better the approximation.";
|
|
float newStep = EditorGUILayout.FloatField(guiContent, step, GUILayout.ExpandWidth(true));
|
|
if (EditorGUI.EndChangeCheck())
|
|
{
|
|
foreach (var s in _curveSpawnSettingsBuffer)
|
|
s.step = newStep;
|
|
|
|
foreach (var c in _curveBuffer)
|
|
c.refresh(ObjectSpawnCurveRefreshReason.Other);
|
|
}*/
|
|
|
|
// Object skip chance
|
|
float objectSkipChance = _curveSpawnSettingsBuffer[0].objectSkipChance;
|
|
EditorGUI.showMixedValue = diff.objectSkipChance;
|
|
EditorGUI.BeginChangeCheck();
|
|
guiContent.text = "Object skip chance";
|
|
guiContent.tooltip = "Specifies the probability of an object being skipped during the spawn process.";
|
|
float newObjectSkipChance = EditorGUILayout.FloatField(guiContent, objectSkipChance, GUILayout.ExpandWidth(true));
|
|
if (EditorGUI.EndChangeCheck())
|
|
{
|
|
foreach (var s in _curveSpawnSettingsBuffer)
|
|
s.objectSkipChance = newObjectSkipChance;
|
|
|
|
foreach (var c in _curveBuffer)
|
|
c.refresh(ObjectSpawnCurveRefreshReason.Other);
|
|
}
|
|
|
|
// Curve padding mode
|
|
EditorGUILayout.Separator();
|
|
CurveObjectSpawnPaddingMode curvePaddingMode = diff.paddingMode ? CurveObjectSpawnPaddingMode.UIMixed : _curveSpawnSettingsBuffer[0].paddingMode;
|
|
EditorGUI.showMixedValue = diff.paddingMode;
|
|
EditorGUI.BeginChangeCheck();
|
|
guiContent.text = "Padding mode";
|
|
guiContent.tooltip = "Allows you to select the padding mode (i.e. constant or random). " +
|
|
"Padding represents the distance between successive objects in the curve.";
|
|
CurveObjectSpawnPaddingMode newCurvePaddingMode = (CurveObjectSpawnPaddingMode)EditorGUILayout.EnumPopup(guiContent, curvePaddingMode, GUILayout.ExpandWidth(true));
|
|
if (EditorGUI.EndChangeCheck())
|
|
{
|
|
foreach (var s in _curveSpawnSettingsBuffer)
|
|
s.paddingMode = newCurvePaddingMode;
|
|
|
|
foreach (var c in _curveBuffer)
|
|
c.refresh(ObjectSpawnCurveRefreshReason.Other);
|
|
}
|
|
|
|
if (newCurvePaddingMode == CurveObjectSpawnPaddingMode.Constant)
|
|
{
|
|
// Padding
|
|
float padding = _curveSpawnSettingsBuffer[0].padding;
|
|
EditorGUI.showMixedValue = diff.padding;
|
|
EditorGUI.BeginChangeCheck();
|
|
guiContent.text = "Padding";
|
|
guiContent.tooltip = "The distance between successive objects in the curve.";
|
|
float newPadding = EditorGUILayout.FloatField(guiContent, padding, GUILayout.ExpandWidth(true));
|
|
if (EditorGUI.EndChangeCheck())
|
|
{
|
|
foreach (var s in _curveSpawnSettingsBuffer)
|
|
s.padding = newPadding;
|
|
|
|
foreach (var c in _curveBuffer)
|
|
c.refresh(ObjectSpawnCurveRefreshReason.Other);
|
|
}
|
|
}
|
|
else
|
|
if (newCurvePaddingMode == CurveObjectSpawnPaddingMode.Random)
|
|
{
|
|
// Min random padding
|
|
float minRandomPadding = _curveSpawnSettingsBuffer[0].minRandomPadding;
|
|
EditorGUI.showMixedValue = diff.minRandomPadding;
|
|
EditorGUI.BeginChangeCheck();
|
|
guiContent.text = "Min padding";
|
|
guiContent.tooltip = "The minimum random padding.";
|
|
float newMinRandomPadding = EditorGUILayout.FloatField(guiContent, minRandomPadding, GUILayout.ExpandWidth(true));
|
|
if (EditorGUI.EndChangeCheck())
|
|
{
|
|
foreach (var s in _curveSpawnSettingsBuffer)
|
|
s.minRandomPadding = newMinRandomPadding;
|
|
|
|
foreach (var c in _curveBuffer)
|
|
c.refresh(ObjectSpawnCurveRefreshReason.Other);
|
|
}
|
|
|
|
// Max random padding
|
|
float maxRandomPadding = _curveSpawnSettingsBuffer[0].maxRandomPadding;
|
|
EditorGUI.showMixedValue = diff.maxRandomPadding;
|
|
EditorGUI.BeginChangeCheck();
|
|
guiContent.text = "Max padding";
|
|
guiContent.tooltip = "The maximum random padding.";
|
|
float newMaxRandomPadding = EditorGUILayout.FloatField(guiContent, maxRandomPadding, GUILayout.ExpandWidth(true));
|
|
if (EditorGUI.EndChangeCheck())
|
|
{
|
|
foreach (var s in _curveSpawnSettingsBuffer)
|
|
s.maxRandomPadding = newMaxRandomPadding;
|
|
|
|
foreach (var c in _curveBuffer)
|
|
c.refresh(ObjectSpawnCurveRefreshReason.Other);
|
|
}
|
|
}
|
|
|
|
// Try fix overlap
|
|
EditorGUILayout.Separator();
|
|
bool tryFixOverlap = _curveSpawnSettingsBuffer[0].tryFixOverlap;
|
|
EditorGUI.showMixedValue = diff.tryFixOverlap;
|
|
EditorGUI.BeginChangeCheck();
|
|
guiContent.text = "Try fix overlap";
|
|
guiContent.tooltip = "If checked, the plugin will attempt to ensure that curve objects will not overlap. " +
|
|
"Note: This applies only to the main lane.";
|
|
bool newTryFixOverlap = EditorGUILayout.Toggle(guiContent, tryFixOverlap, GUILayout.ExpandWidth(true));
|
|
if (EditorGUI.EndChangeCheck())
|
|
{
|
|
foreach (var s in _curveSpawnSettingsBuffer)
|
|
s.tryFixOverlap = newTryFixOverlap;
|
|
|
|
foreach (var c in _curveBuffer)
|
|
c.refresh(ObjectSpawnCurveRefreshReason.Other);
|
|
}
|
|
|
|
// Lane mode
|
|
EditorGUILayout.Separator();
|
|
CurveObjectSpawnLaneMode laneMode = diff.laneMode ? CurveObjectSpawnLaneMode.UIMixed : _curveSpawnSettingsBuffer[0].laneMode;
|
|
EditorGUI.showMixedValue = diff.laneMode;
|
|
EditorGUI.BeginChangeCheck();
|
|
guiContent.text = "Lane mode";
|
|
guiContent.tooltip = "Allows you to specify the way in which the number of lanes will be generated.";
|
|
CurveObjectSpawnLaneMode newLaneMode = (CurveObjectSpawnLaneMode)EditorGUILayout.EnumPopup(guiContent, laneMode, GUILayout.ExpandWidth(true));
|
|
if (EditorGUI.EndChangeCheck())
|
|
{
|
|
foreach (var s in _curveSpawnSettingsBuffer)
|
|
s.laneMode = newLaneMode;
|
|
|
|
foreach (var c in _curveBuffer)
|
|
c.refresh(ObjectSpawnCurveRefreshReason.Other);
|
|
}
|
|
|
|
if (newLaneMode == CurveObjectSpawnLaneMode.Constant)
|
|
{
|
|
// Num lanes
|
|
int numLanes = _curveSpawnSettingsBuffer[0].numLanes;
|
|
EditorGUI.showMixedValue = diff.numLanes;
|
|
EditorGUI.BeginChangeCheck();
|
|
guiContent.text = "Num lanes";
|
|
guiContent.tooltip = "The number of lanes running parallel to each other.";
|
|
int newNumLanes = EditorGUILayout.IntField(guiContent, numLanes, GUILayout.ExpandWidth(true));
|
|
if (EditorGUI.EndChangeCheck())
|
|
{
|
|
foreach (var s in _curveSpawnSettingsBuffer)
|
|
s.numLanes = newNumLanes;
|
|
|
|
foreach (var c in _curveBuffer)
|
|
c.refresh(ObjectSpawnCurveRefreshReason.Other);
|
|
}
|
|
}
|
|
else
|
|
if (newLaneMode == CurveObjectSpawnLaneMode.Random)
|
|
{
|
|
// Min num random lanes
|
|
int minNumLanes = _curveSpawnSettingsBuffer[0].minRandomNumLanes;
|
|
EditorGUI.showMixedValue = diff.minRandomNumLanes;
|
|
EditorGUI.BeginChangeCheck();
|
|
guiContent.text = "Min num lanes";
|
|
guiContent.tooltip = "The minimum number of lanes running parallel to each other.";
|
|
int newMinNumLanes = EditorGUILayout.IntField(guiContent, minNumLanes, GUILayout.ExpandWidth(true));
|
|
if (EditorGUI.EndChangeCheck())
|
|
{
|
|
foreach (var s in _curveSpawnSettingsBuffer)
|
|
s.minRandomNumLanes = newMinNumLanes;
|
|
|
|
foreach (var c in _curveBuffer)
|
|
c.refresh(ObjectSpawnCurveRefreshReason.Other);
|
|
}
|
|
|
|
// Max num random lanes
|
|
int maxNumLanes = _curveSpawnSettingsBuffer[0].maxRandomNumLanes;
|
|
EditorGUI.showMixedValue = diff.maxRandomNumLanes;
|
|
EditorGUI.BeginChangeCheck();
|
|
guiContent.text = "Max num lanes";
|
|
guiContent.tooltip = "The maximum number of lanes running parallel to each other.";
|
|
int newMaxNumLanes = EditorGUILayout.IntField(guiContent, maxNumLanes, GUILayout.ExpandWidth(true));
|
|
if (EditorGUI.EndChangeCheck())
|
|
{
|
|
foreach (var s in _curveSpawnSettingsBuffer)
|
|
s.maxRandomNumLanes = newMaxNumLanes;
|
|
|
|
foreach (var c in _curveBuffer)
|
|
c.refresh(ObjectSpawnCurveRefreshReason.Other);
|
|
}
|
|
}
|
|
|
|
// Lane padding mode
|
|
CurveObjectSpawnLanePaddingMode lanePaddingMode = diff.lanePaddingMode ? CurveObjectSpawnLanePaddingMode.UIMixed : _curveSpawnSettingsBuffer[0].lanePaddingMode;
|
|
EditorGUI.showMixedValue = diff.lanePaddingMode;
|
|
EditorGUI.BeginChangeCheck();
|
|
guiContent.text = "Lane padding mode";
|
|
guiContent.tooltip = "Allows you to specify the lane padding mode. Lane padding is the distance between successive lanes.";
|
|
CurveObjectSpawnLanePaddingMode newLanePaddingMode = (CurveObjectSpawnLanePaddingMode)EditorGUILayout.EnumPopup(guiContent, lanePaddingMode, GUILayout.ExpandWidth(true));
|
|
if (EditorGUI.EndChangeCheck())
|
|
{
|
|
foreach (var s in _curveSpawnSettingsBuffer)
|
|
s.lanePaddingMode = newLanePaddingMode;
|
|
|
|
foreach (var c in _curveBuffer)
|
|
c.refresh(ObjectSpawnCurveRefreshReason.Other);
|
|
}
|
|
|
|
if (newLanePaddingMode == CurveObjectSpawnLanePaddingMode.Constant)
|
|
{
|
|
// Lane padding
|
|
float lanePadding = _curveSpawnSettingsBuffer[0].lanePadding;
|
|
EditorGUI.showMixedValue = diff.lanePadding;
|
|
EditorGUI.BeginChangeCheck();
|
|
guiContent.text = "Lane padding";
|
|
guiContent.tooltip = "The distance between successive lanes.";
|
|
float newLanePadding = EditorGUILayout.FloatField(guiContent, lanePadding, GUILayout.ExpandWidth(true));
|
|
if (EditorGUI.EndChangeCheck())
|
|
{
|
|
foreach (var s in _curveSpawnSettingsBuffer)
|
|
s.lanePadding = newLanePadding;
|
|
|
|
foreach (var c in _curveBuffer)
|
|
c.refresh(ObjectSpawnCurveRefreshReason.Other);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Min random lane padding
|
|
float minRandomLanePadding = _curveSpawnSettingsBuffer[0].minRandomLanePadding;
|
|
EditorGUI.showMixedValue = diff.minRandomLanePadding;
|
|
EditorGUI.BeginChangeCheck();
|
|
guiContent.text = "Min lane padding";
|
|
guiContent.tooltip = "The minimum random lane padding.";
|
|
float newMinRandomLanePadding = EditorGUILayout.FloatField(guiContent, minRandomLanePadding, GUILayout.ExpandWidth(true));
|
|
if (EditorGUI.EndChangeCheck())
|
|
{
|
|
foreach (var s in _curveSpawnSettingsBuffer)
|
|
s.minRandomLanePadding = newMinRandomLanePadding;
|
|
|
|
foreach (var c in _curveBuffer)
|
|
c.refresh(ObjectSpawnCurveRefreshReason.Other);
|
|
}
|
|
|
|
// Max random lane padding
|
|
float maxRandomLanePadding = _curveSpawnSettingsBuffer[0].maxRandomLanePadding;
|
|
EditorGUI.showMixedValue = diff.maxRandomLanePadding;
|
|
EditorGUI.BeginChangeCheck();
|
|
guiContent.text = "Max lane padding";
|
|
guiContent.tooltip = "The maximum random lane padding.";
|
|
float newMaxRandomLanePadding = EditorGUILayout.FloatField(guiContent, maxRandomLanePadding, GUILayout.ExpandWidth(true));
|
|
if (EditorGUI.EndChangeCheck())
|
|
{
|
|
foreach (var s in _curveSpawnSettingsBuffer)
|
|
s.maxRandomLanePadding = newMaxRandomLanePadding;
|
|
|
|
foreach (var c in _curveBuffer)
|
|
c.refresh(ObjectSpawnCurveRefreshReason.Other);
|
|
}
|
|
}
|
|
|
|
// Projection mode
|
|
EditorGUILayout.Separator();
|
|
CurveObjectSpawnProjectionMode projectionMode = diff.projectionMode ? CurveObjectSpawnProjectionMode.UIMixed : _curveSpawnSettingsBuffer[0].projectionMode;
|
|
EditorGUI.showMixedValue = diff.projectionMode;
|
|
EditorGUI.BeginChangeCheck();
|
|
guiContent.text = "Projection mode";
|
|
guiContent.tooltip = "Allows you to specify how the spawned objects will be projected in the scene.";
|
|
CurveObjectSpawnProjectionMode newProjectionMode = (CurveObjectSpawnProjectionMode)EditorGUILayout.EnumPopup(guiContent, projectionMode, GUILayout.ExpandWidth(true));
|
|
if (EditorGUI.EndChangeCheck())
|
|
{
|
|
foreach (var s in _curveSpawnSettingsBuffer)
|
|
s.projectionMode = newProjectionMode;
|
|
|
|
foreach (var c in _curveBuffer)
|
|
c.refresh(ObjectSpawnCurveRefreshReason.Other);
|
|
}
|
|
#pragma warning restore 0612
|
|
EditorUIEx.restoreShowMixedValue();
|
|
EditorUIEx.restoreLabelWidth();
|
|
}
|
|
};
|
|
|
|
_useDefaultsBtn = UI.createUseDefaultsButton(() =>
|
|
{
|
|
_curveView.getSelectedItemData(_curveBuffer);
|
|
|
|
foreach (var itemData in _curveBuffer)
|
|
itemData.settings.useDefaults();
|
|
|
|
foreach (var c in _curveBuffer)
|
|
c.refresh(ObjectSpawnCurveRefreshReason.UseDefaultSettings);
|
|
|
|
}, parent);
|
|
_useDefaultsBtn.setDisplayVisible(_curveView.getNumVisibleSelectedItems() != 0);
|
|
}
|
|
|
|
private void onSelectionChanged(ListView<UIObjectSpawnCurveItem, ObjectSpawnCurve> listView)
|
|
{
|
|
SceneView.RepaintAll();
|
|
}
|
|
|
|
private void onSelectionDeleted(ListView<UIObjectSpawnCurveItem, ObjectSpawnCurve> listView)
|
|
{
|
|
SceneView.RepaintAll();
|
|
}
|
|
|
|
private void populateCurveView()
|
|
{
|
|
if (_curveView == null) return;
|
|
_curveSearchField.refreshMatchNames();
|
|
|
|
_curveView.onBeginBuild();
|
|
ObjectSpawnCurveDb.instance.getCurves(_curveBuffer);
|
|
|
|
foreach (var curve in _curveBuffer)
|
|
_curveView.addItem(curve, filterCurve(curve));
|
|
|
|
_curveView.onEndBuild();
|
|
}
|
|
|
|
private void onCanDeleteSelectedItems(ListView<UIObjectSpawnCurveItem, ObjectSpawnCurve> listView, List<PluginGuid> itemIds, YesNoAnswer answer)
|
|
{
|
|
_curveView.getItemData(itemIds, _curveBuffer);
|
|
|
|
if (!askDeleteCurveObjects(_curveBuffer, out _deleteCurveObjects))
|
|
{
|
|
answer.no();
|
|
return;
|
|
}
|
|
|
|
answer.yes();
|
|
}
|
|
|
|
private bool askDeleteCurveObjects(List<ObjectSpawnCurve> curves, out bool deleteCurveObjects)
|
|
{
|
|
deleteCurveObjects = false;
|
|
int numSpawnedObjects = ObjectSpawnCurve.calcNumSpawnedObjects(curves);
|
|
if (numSpawnedObjects != 0)
|
|
{
|
|
int answerId = EditorUtility.DisplayDialogComplex("Delete Curve Objects?",
|
|
"Warning: This operation can not be undone.\nWould you also like to delete the objects associated with the curve(s)?",
|
|
"Yes", "No", "Cancel");
|
|
|
|
if (answerId == 2) return false;
|
|
deleteCurveObjects = (answerId == 0);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
private void onSelectedCurveItemsWillBeDeleted(ListView<UIObjectSpawnCurveItem, ObjectSpawnCurve> listView, List<PluginGuid> itemIds)
|
|
{
|
|
_curveView.getItemData(itemIds, _curveBuffer);
|
|
deleteCurves(_curveBuffer, _deleteCurveObjects);
|
|
}
|
|
|
|
private void deleteCurves(List<ObjectSpawnCurve> curves, bool deleteCurveObjects)
|
|
{
|
|
if (deleteCurveObjects)
|
|
{
|
|
foreach (var curve in curves)
|
|
curve.destroySpawnedObjectsNoUndoRedo();
|
|
}
|
|
ObjectSpawnCurveDb.instance.deleteCurves(curves);
|
|
}
|
|
}
|
|
}
|
|
#endif |