BITFALL/Assets/GSpawn - Level Designer/Scripts/Level Design/Object Spawn/UITileRuleGridItem.cs

336 lines
15 KiB
C#
Raw Normal View History

2024-01-27 04:09:57 +08:00
#if UNITY_EDITOR
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;
using UnityEditor;
namespace GSpawn
{
public class UITileRuleGridItem : ListViewItem<TileRuleGrid>
{
private VisualElement _row0;
private VisualElement _row1;
private VisualElement _row2;
private VisualElement _row3;
private VisualElement _row4;
private VisualElement _expandedStateBtn;
private Button _toggleActiveBtn;
public override PluginGuid guid { get { return getItemId(data); } }
public override string displayName { get { return data.gridName; } }
public static PluginGuid getItemId(TileRuleGrid grid)
{
return grid.guid;
}
public static void getItemIds(List<TileRuleGrid> grids, List<PluginGuid> ids)
{
ids.Clear();
foreach (var curve in grids)
ids.Add(getItemId(curve));
}
protected override void onRefreshUI()
{
applyVariableStates();
}
protected override void onSelectedStateChanged(bool selected)
{
applyVariableStates();
}
protected override void onBuildUIBeforeDisplayName()
{
style.flexDirection = FlexDirection.Column;
_row0 = createRow();
_row1 = createRow();
_row2 = createRow();
UI.createRowSeparator(this);
_row3 = createRow();
_row4 = createRow();
_expandedStateBtn = UI.createIcon(TexturePool.instance.itemArrowRight, _row0);
_expandedStateBtn.RegisterCallback<MouseDownEvent>(p =>
{
data.uiExpanded = !data.uiExpanded;
applyVariableStates();
p.StopPropagation(); // Note: To disable selection/deselection of the item itself when pressing the expand/collapse button.
});
var icon = UI.createIcon(TexturePool.instance.tileGrid, UIValues.smallIconSize, _row0);
icon.style.marginTop = 2.0f;
_toggleActiveBtn = UI.createButton(TexturePool.instance.lightBulb, UI.ButtonStyle.Push, UIValues.smallButtonSize, _row0);
UI.useDefaultMargins(_toggleActiveBtn);
_toggleActiveBtn.clicked += () =>
{
UndoEx.record(data.gameObject);
if (data.gameObject.activeSelf) data.gameObject.SetActive(false);
else data.gameObject.SetActive(true);
applyToggleActiveButtonStates();
};
var btn = UI.createButton(TexturePool.instance.clear, UI.ButtonStyle.Push, UIValues.smallButtonSize, _row0);
btn.tooltip = "Clear grid. Deletes all tiles inside the grid. Note: Objects groups will remain.";
btn.style.marginTop = 2.0f;
btn.style.marginLeft = -2.0f;
btn.clicked += () => { data.deleteAllTiles(); };
}
protected override void onBuildUIAfterDisplayName()
{
reparentMainControls(_row0);
_displayNameLabel.style.flexGrow = 1.0f;
_displayNameLabel.style.marginLeft = 2.0f;
_displayNameLabel.style.color = UIValues.listItemTextColor;
_displayNameLabel.style.unityFontStyleAndWeight = FontStyle.Normal;
_displayNameLabel.style.alignSelf = Align.FlexStart;
_displayNameLabel.style.marginTop = 2.0f;
_displayNameLabel.style.width = 90.0f;
_renameField.style.flexGrow = 1.0f;
_renameField.style.height = 20.0f;
UI.createHorizontalSpacer(_row0);
var btn = UI.createButton(TexturePool.instance.refresh, UI.ButtonStyle.Push, UIValues.smallButtonSize, _row0);
btn.tooltip = "Use default settings.";
btn.style.marginTop = 2.0f;
btn.clicked += () =>
{
data.settings.wireColor = TileRuleGridSettings.defaultWireColor;
data.settings.fillColor = TileRuleGridSettings.defaultFillColor;
if (data.settings.tileRuleNeighborRadius != TileRuleGridSettings.defaultTileRuleNeighborRadius)
{
data.settings.tileRuleNeighborRadius = TileRuleGridSettings.defaultTileRuleNeighborRadius;
data.refreshTiles();
}
};
// Note: Can't use UIElements here because they would need to be bound to the data.settings.serializedObject properties
// and this can cause issues because the same list item can be reused for different grid items (i.e. they are pooled).
// A grid may be deleted, the item will be freed (stored in the pool) and then reused later for another grid,
// but its UI elements would still be linked to the old serialized object which no longer exists. Although there
// may be ways around this, it seems much cleaner to just use an IMGUIContainer.
var guiContainer = UI.createIMGUIContainer(_row0);
guiContainer.style.flexGrow = 1.0f;
guiContainer.onGUIHandler = () =>
{
const float colorFieldWidth = 40.0f;
var guiContent = new GUIContent();
EditorGUILayout.BeginHorizontal();
EditorGUI.BeginChangeCheck();
guiContent.text = "";
guiContent.tooltip = "This is the radius that will be used to check for adjacent tile neighbors.";
var newRadius = (TileRuleNeighborRadius)EditorGUILayout.EnumPopup(guiContent, data.settings.tileRuleNeighborRadius, GUILayout.MaxWidth(55.0f));
if (EditorGUI.EndChangeCheck())
{
data.settings.tileRuleNeighborRadius = newRadius;
data.refreshTiles();
}
EditorGUI.BeginChangeCheck();
guiContent.text = "";
guiContent.tooltip = "Grid cell line color.";
var color = EditorGUILayout.ColorField(guiContent, data.settings.wireColor, GUILayout.MaxWidth(colorFieldWidth));
if (EditorGUI.EndChangeCheck()) data.settings.wireColor = color;
EditorGUI.BeginChangeCheck();
guiContent.text = "";
guiContent.tooltip = "Grid cell area color.";
color = EditorGUILayout.ColorField(guiContent, data.settings.fillColor, GUILayout.MaxWidth(colorFieldWidth));
if (EditorGUI.EndChangeCheck()) data.settings.fillColor = color;
EditorGUILayout.EndHorizontal();
};
const float labelWidth = 90.0f;
const float floatFieldWidth = 30.0f;
// Reset origin to 0
_row1.style.marginTop = 3.0f;
var parent = new VisualElement();
parent.style.flexGrow = 1.0f;
parent.style.flexDirection = FlexDirection.Row;
_row1.Add(parent);
btn = UI.createButton(TexturePool.instance.refresh, UI.ButtonStyle.Push, UIValues.smallButtonSize, parent);
btn.style.marginTop = 2.0f;
btn.tooltip = "Reset origin to 0.";
btn.clicked += () => { data.gridOrigin = Vector3.zero; };
guiContainer = UI.createIMGUIContainer(parent);
guiContainer.style.flexGrow = 1.0f;
guiContainer.onGUIHandler = () =>
{
var guiContent = new GUIContent();
EditorGUILayout.BeginHorizontal();
guiContent.text = "Origin";
guiContent.tooltip = "The position of the grid origin.";
EditorGUILayout.LabelField(guiContent, GUILayout.Width(labelWidth));
var vecRes = EditorUIEx.vector3FieldEx(data.gridOrigin, floatFieldWidth);
if (vecRes.hasChanged)
{
UndoEx.record(data.transform);
data.gridOrigin = vecRes.newValue;
}
EditorGUILayout.EndHorizontal();
};
// Reset rotation to 0
parent = new VisualElement();
parent.style.flexGrow = 1.0f;
parent.style.flexDirection = FlexDirection.Row;
_row2.Add(parent);
btn = UI.createButton(TexturePool.instance.refresh, UI.ButtonStyle.Push, UIValues.smallButtonSize, parent);
btn.style.marginTop = 2.0f;
btn.tooltip = "Reset rotation to 0.";
btn.clicked += () => { data.gridRotation = Quaternion.identity; };
guiContainer = UI.createIMGUIContainer(parent);
guiContainer.style.flexGrow = 1.0f;
guiContainer.onGUIHandler = () =>
{
var guiContent = new GUIContent();
EditorGUILayout.BeginHorizontal();
guiContent.text = "Rotation";
guiContent.tooltip = "The grid rotation.";
EditorGUILayout.LabelField(guiContent, GUILayout.Width(labelWidth));
var vecRes = EditorUIEx.vector3FieldEx(data.gridRotation.eulerAngles, floatFieldWidth);
if (vecRes.hasChanged)
{
UndoEx.record(data.transform);
data.gridRotation = Quaternion.Euler(vecRes.newValue);
}
EditorGUILayout.EndHorizontal();
};
// Mirroring
parent = new VisualElement();
parent.style.flexGrow = 1.0f;
parent.style.flexDirection = FlexDirection.Row;
_row3.Add(parent);
guiContainer = UI.createIMGUIContainer(parent);
guiContainer.style.flexGrow = 1.0f;
guiContainer.onGUIHandler = () =>
{
var guiContent = new GUIContent();
EditorGUILayout.BeginHorizontal();
guiContent.text = "Mirroring enabled";
guiContent.tooltip =
ShortcutProfileDb.instance.activeProfile.getShortcutUITooltip(GlobalShortcutNames.mirrorGizmo_Toggle,
"If checked, mirroring will be used when painting or erasing tiles.");
EditorGUI.BeginChangeCheck();
var mirroringEnabled = EditorGUILayout.ToggleLeft(guiContent, data.mirroringEnabled);
if (EditorGUI.EndChangeCheck())
{
data.mirroringEnabled = mirroringEnabled;
}
EditorGUILayout.EndHorizontal();
};
guiContainer = new IMGUIContainer();
guiContainer.style.marginLeft = 4.0f;
parent.Add(guiContainer);
guiContainer.onGUIHandler = () =>
{
EditorUIEx.objectMirrorGizmoPlaneToggle(data.mirrorGizmoSettings);
};
btn = UI.createButton(TexturePool.instance.refresh, UI.ButtonStyle.Push, UIValues.smallButtonSize, _row4);
btn.style.marginTop = 2.0f;
btn.tooltip = "Reset mirror cell coordinates to 0.";
btn.clicked += () =>
{
data.mirrorGizmoCellCoords = Vector3Int.zero;
};
guiContainer = new IMGUIContainer();
guiContainer.style.marginLeft = 4.0f;
_row4.Add(guiContainer);
guiContainer.onGUIHandler = () =>
{
var guiContent = new GUIContent();
guiContent.text = "Mirror cell";
guiContent.tooltip = "The cell coordinate of the mirror gizmo.";
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField(guiContent, GUILayout.Width(labelWidth));
EditorGUI.BeginChangeCheck();
var cellCoords = EditorGUILayout.Vector3IntField("", data.mirrorGizmoCellCoords);
if (EditorGUI.EndChangeCheck())
{
data.mirrorGizmoCellCoords = cellCoords;
}
EditorGUILayout.EndHorizontal();
};
applyVariableStates();
}
protected override void onBeginRename()
{
_renameField.SetValueWithoutNotify(displayName);
}
protected override void onEndRename(bool commit)
{
if (commit)
{
TileRuleGridDb.instance.renameGrid(data, _renameField.text);
}
}
private void applyVariableStates()
{
if (data.uiExpanded) style.height = 110.0f;
else style.height = 20.0f;
_row1.setDisplayVisible(data.uiExpanded);
_row2.setDisplayVisible(data.uiExpanded);
_row3.setDisplayVisible(data.uiExpanded);
_row4.setDisplayVisible(data.uiExpanded);
_displayNameLabel.text = displayName;
_displayNameLabel.style.color = UIValues.listItemTextColor;
_displayNameLabel.style.unityFontStyleAndWeight = FontStyle.Normal;
_expandedStateBtn.style.backgroundImage = data.uiExpanded ? TexturePool.instance.itemArrowDown : TexturePool.instance.itemArrowRight;
if (selected)
{
if (ObjectSpawn.instance.tileRuleObjectSpawn.findCurrentGrid() == data)
{
_displayNameLabel.style.color = UIValues.isProSkin ? Color.green : Color.green;
_displayNameLabel.style.unityFontStyleAndWeight = FontStyle.Bold;
}
}
applyToggleActiveButtonStates();
}
private void applyToggleActiveButtonStates()
{
bool active = data.gameObject.activeSelf;
if (active)
{
_toggleActiveBtn.style.backgroundImage = TexturePool.instance.lightBulbGray;
_toggleActiveBtn.tooltip = "Deactivate grid object.";
}
else
{
_toggleActiveBtn.style.backgroundImage = TexturePool.instance.lightBulb;
_toggleActiveBtn.tooltip = "Activate grid object.";
}
}
}
}
#endif