先修复一下,错误的场景 删除不必要的钓场资产 修复into场景 update:更新meta文件,修复报错 update:修复资源 修复第一章节建造 修复建造第三章 update:删除多余内容 update:更新README.md update:还原图标 update:更新README update:更新配置
268 lines
9.2 KiB
C#
268 lines
9.2 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
using UnityEngine.Assertions;
|
|
using UnityEngine.Serialization;
|
|
using UnityEditor.Timeline;
|
|
using UnityEngine.Playables;
|
|
using UnityEngine.Timeline;
|
|
|
|
public class CampToolBobo : EditorWindow
|
|
{
|
|
[MenuItem("Window/CampTool/Refactor Build Process")]
|
|
public static void RefactorBuildProcess()
|
|
{
|
|
var selectedObjects = Selection.objects;
|
|
if (selectedObjects.Length != 1)
|
|
Debug.LogError($"Expect only one target, got {selectedObjects.Length}");
|
|
var targetGo = selectedObjects[0] as GameObject;
|
|
if (targetGo is null)
|
|
{
|
|
Debug.LogError($"Target {selectedObjects[0].name} not a game object.");
|
|
return;
|
|
}
|
|
|
|
foreach (Transform child in targetGo.transform)
|
|
{
|
|
RefactorStep(child);
|
|
}
|
|
}
|
|
|
|
private static void RefactorStep(Transform step)
|
|
{
|
|
Debug.Log($"<color=white>咱瞅瞅步骤{step.name}有没有重复的...</color>");
|
|
bool hasRepeat = false;
|
|
foreach (Transform miniStep in step)
|
|
{
|
|
if (miniStep.childCount > 0)
|
|
continue;
|
|
var goAnimRoot = new GameObject
|
|
{
|
|
name = "AnimRoot",
|
|
transform =
|
|
{
|
|
parent = miniStep,
|
|
}
|
|
};
|
|
goAnimRoot.transform.SetLocalPositionAndRotation(Vector3.zero, Quaternion.identity);
|
|
goAnimRoot.transform.localScale = Vector3.one;
|
|
var newMiniStep = Instantiate(miniStep.gameObject, goAnimRoot.transform);
|
|
newMiniStep.transform.SetLocalPositionAndRotation(Vector3.zero, Quaternion.identity);
|
|
newMiniStep.transform.localScale = Vector3.one;
|
|
newMiniStep.name = "obj";
|
|
DestroyImmediate(miniStep.GetComponent<MeshFilter>());
|
|
DestroyImmediate(miniStep.GetComponent<MeshRenderer>());
|
|
DestroyImmediate(newMiniStep.transform.GetChild(0).gameObject);
|
|
}
|
|
|
|
var children = step.Cast<Transform>().ToList();
|
|
children.Sort((Transform t1, Transform t2) =>
|
|
{
|
|
var a = int.Parse(t1.name);
|
|
var b = int.Parse(t2.name);
|
|
if (a != b) return a.CompareTo(b);
|
|
Debug.Log($"<color=red> 旭哥我跟你讲啊,{a}有重复的啊!</color>");
|
|
hasRepeat = true;
|
|
return a.CompareTo(b);
|
|
});
|
|
for (int i = 0; i < step.childCount; i++)
|
|
{
|
|
Undo.SetTransformParent(children[i], children[i].parent, "SortChildren");
|
|
children[i].SetSiblingIndex(i);
|
|
}
|
|
|
|
if (!hasRepeat)
|
|
Debug.Log($"<color=white>哦,好像没有。</color>");
|
|
}
|
|
|
|
[MenuItem("Window/CampTool/Rename Child of AnimRoot")]
|
|
public static void RenameChildOfAnimRoot()
|
|
{
|
|
var selectedObjects = Selection.objects;
|
|
foreach (var selectedObject in selectedObjects)
|
|
{
|
|
var go = selectedObject as GameObject;
|
|
Assert.IsTrue(go);
|
|
foreach (var stepTransform in go.transform.Cast<Transform>())
|
|
{
|
|
foreach (var miniStep in stepTransform.Cast<Transform>())
|
|
{
|
|
var animRoot = miniStep.GetChild(0);
|
|
if (animRoot.name == "AnimRoot")
|
|
{
|
|
animRoot.GetChild(0).name = "obj";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
[MenuItem("Window/CampTool/Scale Animation Clips")]
|
|
public static void OpenScaleAnimationClipsWindow()
|
|
{
|
|
GetWindow<CampToolBobo>("Rescale Animation Clips");
|
|
}
|
|
|
|
[SerializeField] private AnimationClip[] animationClips;
|
|
private float _targetLength = 5f;
|
|
|
|
private void OnGUI()
|
|
{
|
|
GUILayout.Label("Animation Clip Rescaler", EditorStyles.boldLabel);
|
|
|
|
// Field for selecting animation clips
|
|
var serializedObject = new SerializedObject(this);
|
|
var clipsProperty = serializedObject.FindProperty("animationClips");
|
|
if (clipsProperty != null)
|
|
EditorGUILayout.PropertyField(clipsProperty, true);
|
|
else
|
|
{
|
|
Debug.Log("Bad...");
|
|
}
|
|
|
|
serializedObject.ApplyModifiedProperties();
|
|
|
|
// Target duration field
|
|
_targetLength = EditorGUILayout.FloatField("Target Length (seconds):", _targetLength);
|
|
|
|
// Button to scale animation clips
|
|
if (GUILayout.Button("Scale Animation Clips"))
|
|
{
|
|
ScaleAnimationClips();
|
|
}
|
|
}
|
|
|
|
private void ScaleAnimationClips()
|
|
{
|
|
if (animationClips == null || animationClips.Length == 0)
|
|
{
|
|
Debug.LogWarning("No animation clips selected.");
|
|
return;
|
|
}
|
|
|
|
foreach (var clip in animationClips)
|
|
{
|
|
if (!clip) continue;
|
|
|
|
// Get the original length of the clip
|
|
float originalLength = clip.length;
|
|
if (originalLength <= 0)
|
|
{
|
|
Debug.LogWarning($"Clip '{clip.name}' has no length to scale.");
|
|
continue;
|
|
}
|
|
|
|
// Calculate the new speed to scale the animation
|
|
float scaleFactor = originalLength / _targetLength;
|
|
|
|
// Scale the animation clip speed by adjusting its frame rates
|
|
ScaleClip(clip, scaleFactor);
|
|
EditorUtility.SetDirty(clip); // Mark as modified
|
|
}
|
|
|
|
// AssetDatabase.SaveAssets(); // Save the modified asset
|
|
// AssetDatabase.Refresh();
|
|
Debug.Log("Animation clips scaled successfully.");
|
|
}
|
|
|
|
private void ScaleClip(AnimationClip clip, float scaleFactor)
|
|
{
|
|
// Debug.Log($"<color=red>{scaleFactor} for {clip}</color>");
|
|
// Scale all curves in the clip
|
|
foreach (var binding in AnimationUtility.GetCurveBindings(clip))
|
|
{
|
|
var curve = AnimationUtility.GetEditorCurve(clip, binding);
|
|
var curveKeyFrames = curve.keys;
|
|
// Adjust keyframe times
|
|
for (int i = 0; i < curveKeyFrames.Length; i++)
|
|
{
|
|
// Debug.Log($" before: {curveKeyFrames[i].time}");
|
|
// var t = curveKeyFrames[i].time / scaleFactor;
|
|
// curve.keys[i].time = t;
|
|
curveKeyFrames[i].time /= scaleFactor;
|
|
// Debug.Log($" after: {curveKeyFrames[i].time}");
|
|
// Debug.Log($" after t: {t}");
|
|
}
|
|
|
|
curve.keys = curveKeyFrames;
|
|
AnimationUtility.SetEditorCurve(clip, binding, curve);
|
|
}
|
|
|
|
foreach (var binding in AnimationUtility.GetObjectReferenceCurveBindings(clip))
|
|
{
|
|
var curve = AnimationUtility.GetEditorCurve(clip, binding);
|
|
for (int i = 0; i < curve.keys.Length; i++)
|
|
{
|
|
curve.keys[i].time /= scaleFactor;
|
|
}
|
|
|
|
AnimationUtility.SetEditorCurve(clip, binding, curve);
|
|
}
|
|
|
|
// Scale events
|
|
foreach (var animEvent in AnimationUtility.GetAnimationEvents(clip))
|
|
{
|
|
animEvent.time /= scaleFactor;
|
|
}
|
|
|
|
// Apply changes back to the clip
|
|
AnimationUtility.SetAnimationEvents(clip, AnimationUtility.GetAnimationEvents(clip));
|
|
Debug.Log($"Scaled clip '{clip.name}' to {clip.length / scaleFactor} seconds.");
|
|
}
|
|
|
|
#region Duplicate Timeline
|
|
|
|
[MenuItem("Window/CampTool/CreateTimelineSteps")]
|
|
public static void ShowDuplicateTimelineWindow()
|
|
{
|
|
GetWindow<DuplicateTimeline>("复制Timeline轨道");
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
|
|
public class DuplicateTimeline : EditorWindow
|
|
{
|
|
private PlayableDirector _playableDirector;
|
|
private Animator _animator;
|
|
private void OnGUI()
|
|
{
|
|
GUILayout.Label("复制Timeline轨道", EditorStyles.boldLabel);
|
|
_playableDirector = (PlayableDirector)EditorGUILayout.ObjectField("PlayableDirector",
|
|
_playableDirector, typeof(PlayableDirector), true);
|
|
_animator = (Animator)EditorGUILayout.ObjectField("Dynamic", _animator, typeof(Animator), true);
|
|
if (!GUILayout.Button("走你"))
|
|
return;
|
|
try
|
|
{
|
|
var asset = _playableDirector?.playableAsset as TimelineAsset;
|
|
DuplicateTracks(asset, _playableDirector, _animator);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Debug.Log($"<color=red>{e.Message}</color>");
|
|
}
|
|
}
|
|
|
|
private static void DuplicateTracks(TimelineAsset timeline, PlayableDirector director, Animator animator)
|
|
{
|
|
Undo.RecordObject(timeline, "Duplicate Timeline Track");
|
|
var originTrack = timeline.GetOutputTracks().ToList()[0];
|
|
var clips = originTrack.GetClips().ToList();
|
|
foreach (var clip in clips)
|
|
{
|
|
var newTrack = timeline.CreateTrack(originTrack.GetType(), null,
|
|
originTrack.name + ": " + clip.displayName);
|
|
director.SetGenericBinding(newTrack, animator);
|
|
Debug.Log(clip.TryMoveToTrack(newTrack)
|
|
? $"{clip.displayName} 完成。"
|
|
: $"{clip.displayName} 失败。");
|
|
}
|
|
timeline.DeleteTrack(originTrack);
|
|
AssetDatabase.SaveAssets();
|
|
EditorUtility.SetDirty(timeline);
|
|
Debug.Log("处理完成!");
|
|
}
|
|
} |