Files
ichni_Creator_Studio/Assets/Scripts/CommandSystem/ChangeValueCommand.cs

85 lines
2.9 KiB
C#
Raw Normal View History

2026-03-22 12:05:32 -04:00
using System.Collections;
using System.Collections.Generic;
using System;
using UnityEngine;
using Ichni.RhythmGame;
namespace Ichni.Editor.Commands
{
public class ChangeValueCommand : ICommand
{
private IBaseElement target;
private string path;
private object oldValue;
private object newValue;
private float timestamp;
// 合并窗口期:同一字段 1 秒内的接连覆盖,只算作一次编辑行为
private const float MERGE_WINDOW = 1f;
public ChangeValueCommand(IBaseElement target, string path, object newValue)
{
this.target = target;
this.path = path;
this.newValue = newValue;
this.oldValue = ReflectionHelper.GetDeepValue(target, path);
this.timestamp = Time.realtimeSinceStartup;
}
public void Execute()
{
if (target == null) return;
ReflectionHelper.SetDeepValue(target, path, newValue);
}
public void Undo()
{
// 防暴毙机制:如果所附着的对象因为其它原因在场景中已被销毁(如删除该 Note自动拦截撤销并停止访问底层数据。
if (target == null) return;
ReflectionHelper.SetDeepValue(target, path, oldValue);
target.Refresh();
2026-03-26 14:48:04 -04:00
2026-03-22 12:05:32 -04:00
}
public void Redo()
{
if (target == null) return;
ReflectionHelper.SetDeepValue(target, path, newValue);
target.Refresh();
2026-03-26 14:48:04 -04:00
2026-03-22 12:05:32 -04:00
}
public bool TryMerge(ICommand other)
{
if (other is ChangeValueCommand otherCommand)
{
// 若对象、路径完全一致,则尝试吞并它的新值
if (System.Object.ReferenceEquals(this.target, otherCommand.target) &&
this.path == otherCommand.path &&
(otherCommand.timestamp - this.timestamp) < MERGE_WINDOW)
{
this.newValue = otherCommand.newValue;
this.timestamp = otherCommand.timestamp;
return true;
}
}
return false;
}
private void RefreshInspectorIfMatched()
{
var inspector = EditorManager.instance.uiManager.inspector;
if (inspector != null && inspector.connectedGameElement != null)
{
// 由于目前 DynamicUI 未实现细粒度的数据绑定事件派发,发生撤回时,我们重新装载选择一次右侧属性窗面板以完成显示同步。
// 借由我们之前的对象池机制,这个 SetInspector 消耗会在低于 1ms 的时间内无感重构。
inspector.SetInspector(inspector.connectedGameElement);
}
}
}
}