自定义曲线编辑器, Trail界面跟进
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Ichni.RhythmGame;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Ichni.Editor
|
||||
{
|
||||
public class DynamicUICustomCurveKeyframeUnit : DynamicUICompositeUnit
|
||||
{
|
||||
public TMP_InputField timeInputField;
|
||||
public TMP_InputField valueInputField;
|
||||
public TMP_InputField inTangentInputField;
|
||||
public TMP_InputField outTangentInputField;
|
||||
|
||||
public override void SetUnit(CompositeParameterWindow window, object itemContent)
|
||||
{
|
||||
compositeParameterWindow = window;
|
||||
|
||||
Keyframe keyframe = (Keyframe)itemContent;
|
||||
timeInputField.text = keyframe.time.ToString();
|
||||
valueInputField.text = keyframe.value.ToString();
|
||||
inTangentInputField.text = keyframe.inTangent.ToString();
|
||||
outTangentInputField.text = keyframe.outTangent.ToString();
|
||||
|
||||
timeInputField.onEndEdit.AddListener(_ => compositeParameterWindow.ApplyParameters());
|
||||
valueInputField.onEndEdit.AddListener(_ => compositeParameterWindow.ApplyParameters());
|
||||
inTangentInputField.onEndEdit.AddListener(_ => compositeParameterWindow.ApplyParameters());
|
||||
outTangentInputField.onEndEdit.AddListener(_ => compositeParameterWindow.ApplyParameters());
|
||||
|
||||
removeButton.onClick.AddListener(() =>
|
||||
{
|
||||
compositeParameterWindow.RemoveUnit(this);
|
||||
compositeParameterWindow.ApplyParameters();
|
||||
});
|
||||
}
|
||||
|
||||
public Keyframe GetValue()
|
||||
{
|
||||
return new Keyframe(float.Parse(timeInputField.text), float.Parse(valueInputField.text),
|
||||
float.Parse(inTangentInputField.text), float.Parse(outTangentInputField.text));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0c94b92b2b3fa4d6fb7af3e01fccf4ba
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,57 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Ichni.RhythmGame;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Ichni.Editor
|
||||
{
|
||||
public class DynamicUICustomCurveWrapModeUnit : DynamicUICompositeUnit
|
||||
{
|
||||
public TMP_Dropdown preWrapModeDropdown;
|
||||
public TMP_Dropdown postWrapModeDropdown;
|
||||
|
||||
public override void SetUnit(CompositeParameterWindow window, object itemContent)
|
||||
{
|
||||
compositeParameterWindow = window;
|
||||
|
||||
WarpModes warpModes = (WarpModes)itemContent;
|
||||
List<string> enumNameList = System.Enum.GetNames(typeof(WrapMode)).ToList();
|
||||
|
||||
preWrapModeDropdown.ClearOptions();
|
||||
preWrapModeDropdown.AddOptions(enumNameList);
|
||||
preWrapModeDropdown.value = (int)warpModes.preWrapMode;
|
||||
|
||||
postWrapModeDropdown.ClearOptions();
|
||||
postWrapModeDropdown.AddOptions(enumNameList);
|
||||
postWrapModeDropdown.value = (int)warpModes.postWrapMode;
|
||||
|
||||
preWrapModeDropdown.onValueChanged.AddListener(_ => compositeParameterWindow.ApplyParameters());
|
||||
postWrapModeDropdown.onValueChanged.AddListener(_ => compositeParameterWindow.ApplyParameters());
|
||||
|
||||
removeButton.onClick.AddListener(() =>
|
||||
{
|
||||
compositeParameterWindow.RemoveUnit(this);
|
||||
compositeParameterWindow.ApplyParameters();
|
||||
});
|
||||
}
|
||||
|
||||
public WarpModes GetValue()
|
||||
{
|
||||
return new WarpModes((WrapMode)preWrapModeDropdown.value, (WrapMode)postWrapModeDropdown.value);
|
||||
}
|
||||
}
|
||||
|
||||
public struct WarpModes
|
||||
{
|
||||
public WrapMode preWrapMode;
|
||||
public WrapMode postWrapMode;
|
||||
|
||||
public WarpModes(WrapMode preWrapMode, WrapMode postWrapMode)
|
||||
{
|
||||
this.preWrapMode = preWrapMode;
|
||||
this.postWrapMode = postWrapMode;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d5c23f8ba72e5406692333306483b22e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Ichni.Editor
|
||||
@@ -10,5 +11,26 @@ namespace Ichni.Editor
|
||||
public Hierarchy hierarchy;
|
||||
public Inspector inspector;
|
||||
public Timeline timeline;
|
||||
|
||||
public List<StaticWindow> staticWindows;
|
||||
|
||||
/// <summary>
|
||||
/// 快捷设置所有静态窗口的激活状态
|
||||
/// </summary>
|
||||
public void SetAllStaticWindowsActive()
|
||||
{
|
||||
bool anyWindowActive = staticWindows.Any(window => window.gameObject.activeSelf);
|
||||
staticWindows.ForEach(window =>
|
||||
{
|
||||
if (anyWindowActive)
|
||||
{
|
||||
window.DisableWindow();
|
||||
}
|
||||
else
|
||||
{
|
||||
window.EnableWindow();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -206,12 +206,60 @@ namespace Ichni.Editor
|
||||
connectedBaseElement.GetType().GetField(parameterName).SetValue(connectedBaseElement, newFlexibleBool);
|
||||
};
|
||||
}
|
||||
|
||||
public void SetAsCustomCurve()
|
||||
{
|
||||
void GenerateUnit(Keyframe content)
|
||||
{
|
||||
DynamicUICustomCurveKeyframeUnit unit = Instantiate(unitPrefab, windowRect).GetComponent<DynamicUICustomCurveKeyframeUnit>();
|
||||
unitList.Add(unit);
|
||||
unit.SetUnit(this, content);
|
||||
}
|
||||
|
||||
unitPrefab = EditorManager.instance.basePrefabs.customCurveKeyframeUnit;
|
||||
AnimationCurve curve = connectedBaseElement.GetType().GetField(parameterName).GetValue(connectedBaseElement) as AnimationCurve;
|
||||
List<Keyframe> keyframes = curve.keys.ToList();
|
||||
WarpModes warpModes = new WarpModes(curve.preWrapMode, curve.postWrapMode);
|
||||
|
||||
//生成warpModes的Unit
|
||||
DynamicUICustomCurveWrapModeUnit warpModesUnit =
|
||||
Instantiate(EditorManager.instance.basePrefabs.customCurveWrapModeUnit, windowRect).GetComponent<DynamicUICustomCurveWrapModeUnit>();
|
||||
unitList.Add(warpModesUnit);
|
||||
warpModesUnit.SetUnit(this, warpModes);
|
||||
|
||||
foreach (Keyframe keyframe in keyframes)
|
||||
{
|
||||
GenerateUnit(keyframe);
|
||||
}
|
||||
|
||||
addNewUnitButton.GetComponent<RectTransform>().SetAsLastSibling();
|
||||
|
||||
addNewUnitButton.onClick.AddListener(() =>
|
||||
{
|
||||
GenerateUnit(new Keyframe(0, 0, 0, 0));
|
||||
addNewUnitButton.GetComponent<RectTransform>().SetAsLastSibling();
|
||||
});
|
||||
|
||||
ApplyParameters = () =>
|
||||
{
|
||||
AnimationCurve newCurve = new AnimationCurve();
|
||||
DynamicUICustomCurveWrapModeUnit warpModesUnit = unitList[0] as DynamicUICustomCurveWrapModeUnit;
|
||||
newCurve.preWrapMode = warpModesUnit.GetValue().preWrapMode;
|
||||
newCurve.postWrapMode = warpModesUnit.GetValue().postWrapMode;
|
||||
for(int i = 1; i < unitList.Count; i++)
|
||||
{
|
||||
DynamicUICustomCurveKeyframeUnit unit = unitList[i] as DynamicUICustomCurveKeyframeUnit;
|
||||
newCurve.AddKey(unit.GetValue());
|
||||
}
|
||||
connectedBaseElement.GetType().GetField(parameterName).SetValue(connectedBaseElement, newCurve);
|
||||
};
|
||||
}
|
||||
|
||||
public void Quit()
|
||||
{
|
||||
ApplyParameters();
|
||||
//StartCoroutine(WindowAnim.HidePanel(gameObject, true));
|
||||
Destroy(gameObject);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@ using UnityEngine;
|
||||
|
||||
namespace Ichni.Editor
|
||||
{
|
||||
public class MainPage : StaticWindow
|
||||
public class MainPage : MonoBehaviour
|
||||
{
|
||||
public Canvas mainCanvas;
|
||||
public ToolBar toolBar;
|
||||
|
||||
@@ -45,9 +45,9 @@ namespace Ichni.RhythmGame
|
||||
currentEulerAngles = Vector3.zero;
|
||||
currentScale = Vector3.one;
|
||||
|
||||
positionDirtyMark = false;
|
||||
eulerAnglesDirtyMark = false;
|
||||
scaleDirtyMark = false;
|
||||
positionDirtyMark = true;
|
||||
eulerAnglesDirtyMark = true;
|
||||
scaleDirtyMark = true;
|
||||
|
||||
eulerAnglesOffsetLock = false;
|
||||
|
||||
@@ -70,9 +70,9 @@ namespace Ichni.RhythmGame
|
||||
currentEulerAngles = originalEulerAngles;
|
||||
currentScale = originalScale;
|
||||
|
||||
positionDirtyMark = false;
|
||||
eulerAnglesDirtyMark = false;
|
||||
scaleDirtyMark = false;
|
||||
positionDirtyMark = true;
|
||||
eulerAnglesDirtyMark = true;
|
||||
scaleDirtyMark = true;
|
||||
|
||||
eulerAnglesOffsetLock = false;
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Dreamteck.Splines;
|
||||
using Ichni.Editor;
|
||||
using Ichni.RhythmGame.Beatmap;
|
||||
using Lean.Pool;
|
||||
using UniRx;
|
||||
@@ -75,6 +76,25 @@ namespace Ichni.RhythmGame
|
||||
parentElement.matchedBM as GameElement_BM,
|
||||
trackPercent.ConvertToBM());
|
||||
}
|
||||
|
||||
public override void SetUpInspector()
|
||||
{
|
||||
base.SetUpInspector();
|
||||
|
||||
IHaveInspection inspector = EditorManager.instance.uiManager.inspector;
|
||||
var container = inspector.GenerateContainer("Track Percent Point");
|
||||
var trackPercentButton = inspector.GenerateButton(this, container, "Track Percent", () =>
|
||||
{
|
||||
inspector.GenerateCompositeParameterWindow(this, "Track Percent", nameof(trackPercent)).SetAsFlexibleFloat();
|
||||
});
|
||||
|
||||
var generateTrailButton = inspector.GenerateButton(this, container, "Generate Trail", () =>
|
||||
{
|
||||
Trail.GenerateElement("New Trail", Guid.NewGuid(), new List<string>(),
|
||||
true, this, 1, true,
|
||||
1, AnimationCurve.Constant(0,1, 1));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
namespace Beatmap
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Ichni.Editor;
|
||||
using Ichni.RhythmGame.Beatmap;
|
||||
using UnityEngine;
|
||||
|
||||
@@ -12,20 +13,32 @@ namespace Ichni.RhythmGame
|
||||
public Material renderMaterial;
|
||||
|
||||
public float visibleTimeLength;
|
||||
public bool isAutoOrient;
|
||||
public float widthMultiplier;
|
||||
public AnimationCurve widthCurve;
|
||||
|
||||
public TransformSubmodule transformSubmodule { get; set; }
|
||||
|
||||
public static Trail GenerateElement(string name, Guid id, List<string> tags, bool isFirstGenerated,
|
||||
GameElement parentElement, float visibleTimeLength, Material material = null)
|
||||
GameElement parentElement, float visibleTimeLength, bool isAutoOrient, float widthMultiplier,
|
||||
AnimationCurve widthCurve, Material material = null)
|
||||
{
|
||||
Trail trail = Instantiate(EditorManager.instance.basePrefabs.trail).GetComponent<Trail>();
|
||||
Trail trail = Instantiate(EditorManager.instance.basePrefabs.trail, parentElement.transform).GetComponent<Trail>();
|
||||
trail.trailRenderer = trail.GetComponent<TrailRenderer>();
|
||||
|
||||
trail.Initialize(name, id, tags, isFirstGenerated, parentElement);
|
||||
trail.renderMaterial =
|
||||
material == null ? EditorManager.instance.basePrefabs.defaultTrailMaterial : material;
|
||||
|
||||
trail.renderMaterial = material == null ? EditorManager.instance.basePrefabs.defaultTrailMaterial : material;
|
||||
trail.trailRenderer.material = trail.renderMaterial;
|
||||
trail.visibleTimeLength = visibleTimeLength;
|
||||
trail.isAutoOrient = isAutoOrient;
|
||||
trail.widthMultiplier = widthMultiplier;
|
||||
trail.widthCurve = widthCurve;
|
||||
|
||||
trail.trailRenderer.time = visibleTimeLength;
|
||||
trail.trailRenderer.alignment = isAutoOrient ? LineAlignment.View : LineAlignment.TransformZ;
|
||||
trail.trailRenderer.widthMultiplier = widthMultiplier;
|
||||
trail.trailRenderer.widthCurve = widthCurve;
|
||||
|
||||
return trail;
|
||||
}
|
||||
@@ -42,7 +55,25 @@ namespace Ichni.RhythmGame
|
||||
public override void SaveBM()
|
||||
{
|
||||
matchedBM = new Trail_BM(elementName, elementGuid, tags, parentElement.matchedBM as GameElement_BM,
|
||||
visibleTimeLength, renderMaterial);
|
||||
visibleTimeLength, isAutoOrient, widthMultiplier, widthCurve, renderMaterial);
|
||||
}
|
||||
|
||||
public override void SetUpInspector()
|
||||
{
|
||||
base.SetUpInspector();
|
||||
|
||||
IHaveInspection inspector = EditorManager.instance.uiManager.inspector;
|
||||
Inspector inspectorMain = EditorManager.instance.uiManager.inspector;
|
||||
var container = inspector.GenerateContainer("Trail");
|
||||
var visibleTimeLengthInputField = inspector.GenerateInputField(this, container, "Visible Time Length", nameof(visibleTimeLength));
|
||||
var isAutoOrientToggle = inspector.GenerateToggle(this, container, "Is Auto Orient", nameof(isAutoOrient));
|
||||
var widthMultiplierInputField = inspector.GenerateInputField(this, container, "Width Multiplier", nameof(widthMultiplier));
|
||||
var widthCurveButton = inspector.GenerateButton(this, container, "Width Curve", () =>
|
||||
{
|
||||
var widthCurveWindow = inspector.GenerateCompositeParameterWindow(this, "Width Curve", nameof(widthCurve));
|
||||
widthCurveWindow.SetAsCustomCurve();
|
||||
widthCurveWindow.closeButton.onClick.AddListener(() => trailRenderer.widthCurve = widthCurve);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,6 +98,9 @@ namespace Ichni.RhythmGame
|
||||
{
|
||||
public float visibleTimeLength;
|
||||
public string renderMaterialName;
|
||||
public bool isAutoOrient;
|
||||
public float widthMultiplier;
|
||||
public AnimationCurve widthCurve;
|
||||
|
||||
public Trail_BM()
|
||||
{
|
||||
@@ -74,24 +108,29 @@ namespace Ichni.RhythmGame
|
||||
}
|
||||
|
||||
public Trail_BM(string elementName, Guid elementGuid, List<string> tags, GameElement_BM attachedElement,
|
||||
float visibleTimeLength, Material renderMaterial) : base(elementName, elementGuid, tags,
|
||||
float visibleTimeLength, bool isAutoOrient, float widthMultiplier,
|
||||
AnimationCurve widthCurve, Material renderMaterial) : base(elementName, elementGuid, tags,
|
||||
attachedElement)
|
||||
{
|
||||
this.visibleTimeLength = visibleTimeLength;
|
||||
this.renderMaterialName = renderMaterial.name;
|
||||
this.isAutoOrient = isAutoOrient;
|
||||
this.widthMultiplier = widthMultiplier;
|
||||
this.widthCurve = widthCurve;
|
||||
}
|
||||
|
||||
public override void ExecuteBM()
|
||||
{
|
||||
matchedElement = Trail.GenerateElement(elementName, elementGuid, tags,
|
||||
false, GetElement(attachedElementGuid),
|
||||
visibleTimeLength); //TODO: Implement Material
|
||||
visibleTimeLength, isAutoOrient, widthMultiplier, widthCurve);
|
||||
}
|
||||
|
||||
public override GameElement DuplicateBM(GameElement parent)
|
||||
{
|
||||
return Trail.GenerateElement(elementName, elementGuid, tags,
|
||||
false, parent, visibleTimeLength); //TODO: Implement Material
|
||||
false, parent, visibleTimeLength,
|
||||
isAutoOrient, widthMultiplier, widthCurve);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,10 +29,8 @@ public class BasePrefabsCollection : SerializedScriptableObject
|
||||
public AudioClip holdNoteEndSound;
|
||||
public AudioClip flickNoteSound;
|
||||
|
||||
[Title("Effect相关")]
|
||||
[FormerlySerializedAs("bloomShake")]
|
||||
[Title("Effect相关")]
|
||||
public GameObject bloomEffect;
|
||||
[FormerlySerializedAs("cameraShake")]
|
||||
public GameObject cameraShakeEffect;
|
||||
public GameObject chromaticAberrationEffect;
|
||||
public GameObject vignetteEffect;
|
||||
@@ -42,9 +40,9 @@ public class BasePrefabsCollection : SerializedScriptableObject
|
||||
|
||||
[Title("DynamicUI相关-Simple")]
|
||||
public GameObject dynamicUIContainer;
|
||||
[FormerlySerializedAs("parameterInputField")] public GameObject inputField;
|
||||
[FormerlySerializedAs("Vector3inputField")] public GameObject vector3InputField;
|
||||
[FormerlySerializedAs("text")] public GameObject parameterText;
|
||||
public GameObject inputField;
|
||||
public GameObject vector3InputField;
|
||||
public GameObject parameterText;
|
||||
public GameObject hintText;
|
||||
public GameObject button;
|
||||
public GameObject toggle;
|
||||
@@ -54,10 +52,12 @@ public class BasePrefabsCollection : SerializedScriptableObject
|
||||
public GameObject emissionColorPicker;
|
||||
[Title("DynamicUI相关-Composite")]
|
||||
public GameObject compositeParameterWindow;
|
||||
[FormerlySerializedAs("stringUnit")] public GameObject inputFieldUnit;
|
||||
public GameObject inputFieldUnit;
|
||||
public GameObject animatedFloatUnit;
|
||||
public GameObject animatedIntUnit;
|
||||
public GameObject animatedBoolUnit;
|
||||
public GameObject customCurveKeyframeUnit;
|
||||
public GameObject customCurveWrapModeUnit;
|
||||
|
||||
[Title("Background相关")]
|
||||
public Sprite defaultBackground;
|
||||
|
||||
@@ -113,6 +113,11 @@ namespace Ichni.Editor
|
||||
{
|
||||
EditorManager.instance.uiManager.mainPage.resolutionHints.SetSafeAreaFrame();
|
||||
}
|
||||
|
||||
if (Keyboard.current.uKey.wasPressedThisFrame)
|
||||
{
|
||||
EditorManager.instance.uiManager.SetAllStaticWindowsActive();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user