123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284 |
- // Animancer // https://kybernetik.com.au/animancer // Copyright 2018-2024 Kybernetik //
- #if UNITY_EDITOR
- using System;
- using System.Collections.Generic;
- using UnityEditor;
- using UnityEditor.IMGUI.Controls;
- using UnityEngine;
- using static Animancer.Editor.AnimancerGUI;
- namespace Animancer.Editor
- {
- /// <summary>An <see cref="TransformTreeWindow{TTarget, TDefinition}"/> for editing spring definitions.</summary>
- /// https://kybernetik.com.au/animancer/api/Animancer.Editor/WeightedMaskLayersDefinitionWindow
- public class WeightedMaskLayersDefinitionWindow :
- TransformTreeWindow<WeightedMaskLayers, WeightedMaskLayersDefinition>
- {
- /************************************************************************************************************************/
- /// <inheritdoc/>
- public override IList<Transform> Transforms
- => Data.Transforms;
- /// <inheritdoc/>
- public override WeightedMaskLayersDefinition SourceData
- {
- get => SourceObject.Definition;
- set => SourceObject.Definition = value;
- }
- /************************************************************************************************************************/
- /// <inheritdoc/>
- protected override MultiColumnHeaderState.Column[] CreateColumns(float width)
- {
- const float TransformWidth = 300;
- const float GroupWidth = 100;
- var groupCount = Data.GroupCount;
- var oldColumns = HeaderState?.columns;
- var newColumns = new MultiColumnHeaderState.Column[groupCount + 2];
- int index;
- if (oldColumns == null)
- {
- var tooltip = "Select which objects to control the weight of";
- newColumns[0] = CreateColumn(
- "Transform",
- tooltip,
- TransformWidth);
- var includedColumn = newColumns[1] = CreateColumn(
- "?",
- tooltip,
- LineHeight + StandardSpacing);
- includedColumn.minWidth = includedColumn.maxWidth = includedColumn.width;
- index = 2;
- }
- else
- {
- var copyCount = Math.Min(oldColumns.Length, groupCount + 2);
- for (int i = 0; i < copyCount; i++)
- newColumns[i] = oldColumns[i];
- index = copyCount;
- }
- for (int i = index; i < groupCount + 2; i++)
- {
- var groupIndex = i - 2;
- var name = "Group " + groupIndex.ToStringCached();
- var tooltip = "The weights for " + name;
- if (groupIndex == 0)
- {
- name = "Default " + name;
- tooltip += " (this group will be applied on startup by default)";
- }
- newColumns[i] = CreateColumn(
- name,
- tooltip,
- GroupWidth);
- }
- return newColumns;
- }
- /************************************************************************************************************************/
- /// <inheritdoc/>
- protected override Color GetRowColor(TreeViewItem item)
- {
- if (!TreeView.Transforms.TryGetObject(item.id, out var transform))
- return default;
- if (Transforms.IndexOf(transform) < 0)
- return default;
- return GetChainColor(transform, Transforms, 0.15f);
- }
- /// <summary>Returns a color based on the name of the `transform`'s highest included parent.</summary>
- public static Color GetChainColor(Transform transform, IList<Transform> transforms, float alpha)
- {
- transform = GetChainRoot(transform, transforms);
- return GetHashColor(transform.name.GetHashCode(), 1, 1, alpha);
- }
- /// <summary>Gets the highest parent of `transform` which is included in the `transforms`.</summary>
- public static Transform GetChainRoot(Transform transform, IList<Transform> transforms)
- {
- var parent = transform.parent;
- while (parent != null)
- {
- if (transforms.IndexOf(parent) >= 0)
- transform = parent;
- parent = parent.parent;
- }
- return transform;
- }
- /************************************************************************************************************************/
- /// <inheritdoc/>
- public override void DrawCellGUI(Rect area, int column, int row, TreeViewItem item, ref bool isSelectionClick)
- {
- if (!TreeView.Transforms.TryGetObject(item.id, out var transform))
- return;
- var definitionIndex = GetDefinitionIndex(item.id);
- switch (column)
- {
- case 0:// Transform.
- DrawTransformCellGUI(area, transform);
- break;
- case 1:// Included.
- DrawIsIncludedCellGUI(area, item.id, definitionIndex, ref isSelectionClick);
- break;
- default:// Groups.
- DrawWeightGUI(area, item.id, column - 2, definitionIndex);
- break;
- }
- }
- /************************************************************************************************************************/
- /// <inheritdoc/>
- protected override void SetIncluded(
- int treeItemID,
- int definitionIndex,
- bool isIncluded)
- {
- var data = RecordUndo();
- if (isIncluded)
- {
- if (definitionIndex < 0 &&
- TreeView.Transforms.TryGetObject(treeItemID, out var transform))
- {
- var groupCount = data.GroupCount;
- data.AddTransform(transform);
- if (groupCount != data.GroupCount)
- CreateHeader();
- }
- }
- else
- {
- if (definitionIndex >= 0)
- {
- data.RemoveTransform(definitionIndex);
- if (data.GroupCount <= 0)
- CreateHeader();
- }
- }
- }
- /************************************************************************************************************************/
- private void DrawWeightGUI(
- Rect area,
- int treeItemID,
- int groupIndex,
- int transformIndex)
- {
- if (transformIndex < 0)
- return;
- var weight = Data.GetWeight(groupIndex, transformIndex);
- if (float.IsNaN(weight))
- return;
- EditorGUI.BeginChangeCheck();
- weight = EditorGUI.FloatField(area, weight);
- if (EditorGUI.EndChangeCheck())
- {
- weight = Mathf.Clamp01(weight);
- SetValue(treeItemID, i => RecordUndo().SetWeight(groupIndex, i, weight));
- }
- }
- /************************************************************************************************************************/
- private static readonly GUIContent
- AddGroupLabel = new(
- "Add Group",
- "Add another weight group"),
- RemoveGroupLabel = new(
- "Remove Group",
- "Remove the last weight group");
- /// <inheritdoc/>
- protected override void DoFooterCenterGUI()
- {
- var hasTransforms = !Data.Transforms.IsNullOrEmpty();
- GUI.enabled = hasTransforms;
- if (GUILayout.Button(AddGroupLabel))
- {
- RecordUndo().GroupCount++;
- CreateHeader();
- }
- if (hasTransforms)
- GUI.enabled = Data.GroupCount > 1;
- if (GUILayout.Button(RemoveGroupLabel))
- {
- RecordUndo().GroupCount--;
- CreateHeader();
- }
- }
- /************************************************************************************************************************/
- /// <inheritdoc/>
- public override void Apply()
- {
- base.Apply();
- CreateHeader();
- SceneView.RepaintAll();
- }
- /// <inheritdoc/>
- public override void Revert()
- {
- base.Revert();
- CreateHeader();
- SceneView.RepaintAll();
- }
- /************************************************************************************************************************/
- /// <inheritdoc/>
- public override WeightedMaskLayersDefinition RecordUndo(string name = "Animancer")
- {
- SceneView.RepaintAll();
- return base.RecordUndo(name);
- }
- /************************************************************************************************************************/
- }
- }
- #endif
|