mirror of
https://gitgud.io/AbstractConcept/rimworld-animation-studio.git
synced 2024-08-15 00:43:27 +00:00
Code refactor
This commit is contained in:
parent
757badf4f6
commit
a55ba7b95b
232 changed files with 1282 additions and 936 deletions
|
@ -14,81 +14,32 @@ namespace RimWorldAnimationStudio
|
|||
[Header("Animation settings")]
|
||||
public bool isAnimating = false;
|
||||
|
||||
|
||||
[Header("Object references")]
|
||||
public Slider stageTimelineSlider;
|
||||
public Dropdown stageLoopDropdown;
|
||||
public InputField cyclesNormalField;
|
||||
public InputField cyclesFastField;
|
||||
public InputField animationClipTimeField;
|
||||
public InputField animationClipLengthField;
|
||||
public ActorCard actorCard;
|
||||
public Transform animationTimelines;
|
||||
public Transform actorBodies;
|
||||
public Toggle stretchKeyframesToggle;
|
||||
public InputField playBackSpeedField;
|
||||
public Button playToggleButton;
|
||||
public Text stageLengthText;
|
||||
public Text animationLengthText;
|
||||
public GameObject handLeftControls;
|
||||
public GameObject handRightControls;
|
||||
public GameObject sexToyControls;
|
||||
public Dropdown stageLoopDropdown;
|
||||
|
||||
[Header("Prefabs")]
|
||||
public ActorBody actorBodyPrefab;
|
||||
public GameObject animationTimelinePrefab;
|
||||
|
||||
// Private timing variables
|
||||
private int lastStageTick = Constants.minTick;
|
||||
private float timeSinceLastUpdate = 0;
|
||||
private int cycleIndex = 0;
|
||||
private bool isDirty = true;
|
||||
private bool isTimelineDirty = true;
|
||||
private int loopCount = 0;
|
||||
private float playBackSpeed = 1f;
|
||||
|
||||
public void MakeDirty()
|
||||
{ isDirty = true; isTimelineDirty = true; }
|
||||
|
||||
public void MakeTimelineDirty()
|
||||
{ isTimelineDirty = true; }
|
||||
|
||||
public bool IsDirty()
|
||||
{ return isDirty; }
|
||||
|
||||
public bool IsTimelineDirty()
|
||||
{ return isTimelineDirty; }
|
||||
public void Start()
|
||||
{
|
||||
EventsManager.onAnimationChanged.AddListener(delegate{ Initialize(); });
|
||||
EventsManager.onStageIDChanged.AddListener(delegate { Initialize(); });
|
||||
EventsManager.onActorCountChanged.AddListener(delegate { Initialize(); });
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// No animation, exit
|
||||
if (Workspace.animationDef == null) { return; }
|
||||
|
||||
// Dirty animation, reset
|
||||
if (Workspace.animationDef != null && isDirty)
|
||||
{ Initialize(); }
|
||||
|
||||
// Update animation lengths
|
||||
if (stageLoopDropdown.value == 3)
|
||||
{
|
||||
stageLengthText.text = "Stage length (quickie): " + Workspace.GetCurrentAnimationStage().PlayTimeTicksQuick + " (" + Workspace.animationDef.AnimationStages[Workspace.StageID].PlayTimeTicksQuick / 60f + " s)";
|
||||
animationLengthText.text = "Animation length (quickie): " + Workspace.animationDef.animationTimeTicksQuick + " (" + Workspace.animationDef.animationTimeTicksQuick / 60f + " s)";
|
||||
|
||||
LayoutRebuilder.ForceRebuildLayoutImmediate(stageLengthText.GetComponent<RectTransform>());
|
||||
LayoutRebuilder.ForceRebuildLayoutImmediate(animationLengthText.GetComponent<RectTransform>());
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
stageLengthText.text = "Stage length (normal): " + Workspace.animationDef.AnimationStages[Workspace.StageID].PlayTimeTicks + " (" + Workspace.animationDef.AnimationStages[Workspace.StageID].PlayTimeTicks / 60f + " s)";
|
||||
animationLengthText.text = "Animation length (normal): " + Workspace.animationDef.animationTimeTicks + " (" + Workspace.animationDef.animationTimeTicks / 60f + " s)";
|
||||
|
||||
LayoutRebuilder.ForceRebuildLayoutImmediate(stageLengthText.GetComponent<RectTransform>());
|
||||
LayoutRebuilder.ForceRebuildLayoutImmediate(animationLengthText.GetComponent<RectTransform>());
|
||||
}
|
||||
|
||||
// Update tick if animating
|
||||
Workspace.StageTick = Mathf.Clamp(Workspace.StageTick, Constants.minTick, Workspace.StageWindowSize);
|
||||
if (Workspace.animationDef == null) return;
|
||||
|
||||
// Update stage tick / loop count if animating
|
||||
if (isAnimating)
|
||||
{
|
||||
timeSinceLastUpdate += Time.deltaTime;
|
||||
|
@ -101,204 +52,150 @@ namespace RimWorldAnimationStudio
|
|||
|
||||
if (Workspace.StageTick > Workspace.StageWindowSize)
|
||||
{
|
||||
if (stageLoopDropdown.value == 1)
|
||||
{ Workspace.StageTick = Constants.minTick; }
|
||||
|
||||
else if (stageLoopDropdown.value >= 2)
|
||||
switch (stageLoopDropdown.value)
|
||||
{
|
||||
++cycleIndex;
|
||||
Workspace.StageTick = Constants.minTick;
|
||||
|
||||
if ((stageLoopDropdown.value == 2 && cycleIndex >= int.Parse(cyclesNormalField.text)) ||
|
||||
(stageLoopDropdown.value == 3 && cycleIndex >= int.Parse(cyclesFastField.text)))
|
||||
{
|
||||
++Workspace.StageID;
|
||||
cycleIndex = 0;
|
||||
}
|
||||
|
||||
if (Workspace.StageID > Workspace.animationDef.AnimationStages.Count - 1)
|
||||
{
|
||||
Workspace.StageID = Workspace.animationDef.AnimationStages.Count - 1;
|
||||
Workspace.StageTick = Workspace.StageWindowSize;
|
||||
isAnimating = false;
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
//stageTick = Workspace.StageWindowSize;
|
||||
//isAnimating = false;
|
||||
case 1: Workspace.StageTick = Constants.minTick; break;
|
||||
case 2: UpdateLoopCount(Workspace.GetCurrentAnimationStage().StageLoopsNormal); break;
|
||||
case 3: UpdateLoopCount(Workspace.GetCurrentAnimationStage().StageLoopsQuick); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update stage timeline
|
||||
animationClipTimeField.interactable = isAnimating == false;
|
||||
animationClipLengthField.interactable = isAnimating == false;
|
||||
|
||||
if (lastStageTick != Workspace.StageTick)
|
||||
{
|
||||
stageTimelineSlider.value = Workspace.StageTick;
|
||||
animationClipTimeField.text = Workspace.StageTick.ToString();
|
||||
|
||||
lastStageTick = Workspace.StageTick;
|
||||
}
|
||||
|
||||
playToggleButton.image.color = isAnimating ? Constants.ColorGoldYellow : Constants.ColorWhite;
|
||||
|
||||
// Update animation
|
||||
UpdateAnimation();
|
||||
// Update animation preview
|
||||
UpdateAnimationPReview();
|
||||
}
|
||||
|
||||
public void UpdateAnimation()
|
||||
public void UpdateLoopCount(int stageLoops)
|
||||
{
|
||||
List<ActorBody> _actorBodies = actorBodies.GetComponentsInChildren<ActorBody>().ToList();
|
||||
++loopCount;
|
||||
Workspace.StageTick = Constants.minTick;
|
||||
|
||||
for (int actorID = 0; actorID < _actorBodies.Count; actorID++)
|
||||
if (loopCount >= stageLoops)
|
||||
{
|
||||
if (Workspace.StageID >= Workspace.animationDef?.AnimationStages.Count) return;
|
||||
++Workspace.StageID;
|
||||
loopCount = 0;
|
||||
}
|
||||
|
||||
if (Workspace.StageID >= Workspace.animationDef.AnimationStages.Count - 1)
|
||||
{
|
||||
Workspace.StageTick = Workspace.StageWindowSize;
|
||||
Workspace.isAnimating = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateAnimationPReview()
|
||||
{
|
||||
if (Workspace.animationDef == null || Workspace.StageID >= Workspace.animationDef?.AnimationStages.Count) return;
|
||||
|
||||
List<ActorBody> actorBodiesList = actorBodies.GetComponentsInChildren<ActorBody>().ToList();
|
||||
|
||||
for (int actorID = 0; actorID < actorBodiesList.Count; actorID++)
|
||||
{
|
||||
// Get the current actor and their animation clip
|
||||
Actor actor = Workspace.GetActor(actorID);
|
||||
PawnAnimationClip clip = Workspace.GetPawnAnimationClip(actorID);
|
||||
|
||||
// Get flags
|
||||
bool quiver = isAnimating && Workspace.GetCurrentOrPreviousKeyframe(actorID).Quiver == true;
|
||||
bool requiresGenitals = actor.RequiredGenitals.Any(x => x == "Penis") || actor.IsFucking;
|
||||
|
||||
// Get clip percentage
|
||||
float clipPercent = clip.GetStageTickPercentage();
|
||||
if (Workspace.StageTick > Constants.minTick && Workspace.StageTick == clip.duration) clipPercent = 1f;
|
||||
|
||||
if (Workspace.GetCurrentAnimationStage().IsLooping == false)
|
||||
{ clipPercent = (float)Workspace.StageTick / clip.duration; }
|
||||
|
||||
PawnRaceDef pawnRaceDef = actor.GetPawnRaceDef();
|
||||
ActorBody actorBody = _actorBodies[actorID];
|
||||
// Get the actors race and body type
|
||||
PawnRaceDef pawnRaceDef = actor.GetPawnRaceDef();
|
||||
string bodyType = pawnRaceDef.isHumanoid ? actor.bodyType : "None";
|
||||
|
||||
Vector3 deltaPos = new Vector3(clip.BodyOffsetX.Evaluate(clipPercent), 0, clip.BodyOffsetZ.Evaluate(clipPercent));
|
||||
// Evalute the actor's basic offsets and facing
|
||||
ActorPosition actorPosition = actor.GetCurrentPosition();
|
||||
|
||||
float bodyAngle = clip.BodyAngle.Evaluate(clipPercent);
|
||||
bodyAngle += quiver ? UnityEngine.Random.value * 2f - 1f : 0f;
|
||||
|
||||
float headAngle = clip.HeadAngle.Evaluate(clipPercent);
|
||||
|
||||
int bodyFacing = (int)clip.BodyFacing.Evaluate(clipPercent);
|
||||
int headFacing = (int)clip.HeadFacing.Evaluate(clipPercent);
|
||||
|
||||
float headBob = clip.HeadBob.Evaluate(clipPercent);
|
||||
Vector3 headOffset = new Vector3(0, 0, headBob) + PawnUtility.BaseHeadOffsetAt(bodyType, bodyFacing);
|
||||
|
||||
Vector3 bodyPos = new Vector3(deltaPos.x, deltaPos.z, 0);
|
||||
Vector3 headPos = new Vector3(headOffset.x, headOffset.z, 0);
|
||||
float bodyPosX = actorPosition.bodyOffsetX;
|
||||
float bodyPosZ = actorPosition.bodyOffsetZ;
|
||||
float bodyAngle = actorPosition.bodyAngle + (quiver ? UnityEngine.Random.value * 2f - 1f : 0f);
|
||||
float headBob = actorPosition.headBob;
|
||||
float headAngle = actorPosition.headAngle;
|
||||
float genitalAngle = actorPosition.genitalAngle;
|
||||
|
||||
int bodyFacing = actorPosition.bodyFacing;
|
||||
int headFacing = actorPosition.headFacing;
|
||||
|
||||
// Convert values to world coordinates
|
||||
Vector3 bodyPos = new Vector3(bodyPosX, bodyPosZ, 0f);
|
||||
Vector3 headPos = new Vector3(0f, headBob, 0f) + PawnUtility.BaseHeadOffsetAt(bodyType, bodyFacing);
|
||||
Vector3 appendagePos = PawnUtility.GroinOffsetAt(bodyType, bodyFacing);
|
||||
float appendageRotation = clip.GenitalAngle.Evaluate(clipPercent);
|
||||
|
||||
actorBody.transform.position = bodyPos + actor.GetFinalTransformOffset();
|
||||
actorBody.transform.eulerAngles = new Vector3(0, 0, -bodyAngle);
|
||||
|
||||
actorBody.headRenderer.transform.localPosition = headPos;
|
||||
actorBody.headRenderer.transform.eulerAngles = new Vector3(0, 0, -headAngle);
|
||||
|
||||
actorBody.appendageRenderer.transform.localPosition = new Vector3(appendagePos.x, appendagePos.z, 0f);
|
||||
actorBody.appendageRenderer.transform.eulerAngles = new Vector3(0, 0, -appendageRotation);
|
||||
|
||||
actorBody.bodyRenderer.sprite = pawnRaceDef.GetBodyTypeGraphic((CardinalDirection)bodyFacing, bodyType);
|
||||
actorBody.headRenderer.sprite = pawnRaceDef.isHumanoid ? pawnRaceDef.GetHeadGraphic((CardinalDirection)headFacing) : null;
|
||||
actorBody.appendageRenderer.sprite = requiresGenitals && pawnRaceDef.isHumanoid && bodyFacing != 0 ? Resources.Load<Sprite>("Textures/Humanlike/Appendages/Appendage" + bodyFacing) : null;
|
||||
|
||||
actorBody.bodyRenderer.gameObject.SetActive(actorBody.bodyRenderer.sprite != null);
|
||||
actorBody.headRenderer.gameObject.SetActive(actorBody.headRenderer.sprite != null);
|
||||
actorBody.appendageRenderer.gameObject.SetActive(actorBody.appendageRenderer.sprite != null);
|
||||
|
||||
actorBody.bodyRenderer.sortingLayerName = clip.Layer;
|
||||
actorBody.headRenderer.sortingLayerName = clip.Layer;
|
||||
actorBody.headRenderer.sortingOrder = bodyFacing == 0 ? -1 : 1;
|
||||
actorBody.appendageRenderer.sortingLayerName = clip.Layer;
|
||||
|
||||
actorBody.bodyRenderer.flipX = bodyFacing == 3;
|
||||
actorBody.headRenderer.flipX = headFacing == 3;
|
||||
//actorBody.appendageRenderer.flipX = bodyFacing == 3;
|
||||
// Update actorbody
|
||||
ActorBody actorBody = actorBodiesList[actorID];
|
||||
ActorBodyPart actorBodypart;
|
||||
|
||||
actorBody.transform.localScale = new Vector3(pawnRaceDef.scale, pawnRaceDef.scale, pawnRaceDef.scale);
|
||||
|
||||
// ActorKeyframeCard update
|
||||
if (actorID != Workspace.ActorID) continue;
|
||||
if (ActorKeyframeCard.Instance.positionXField.isFocused == false) { ActorKeyframeCard.Instance.positionXField.text = bodyPos.x.ToString("0.000"); }
|
||||
if (ActorKeyframeCard.Instance.positionZField.isFocused == false) { ActorKeyframeCard.Instance.positionZField.text = bodyPos.y.ToString("0.000"); }
|
||||
if (ActorKeyframeCard.Instance.rotationField.isFocused == false) { ActorKeyframeCard.Instance.rotationField.text = bodyAngle.ToString("0.000"); }
|
||||
if (ActorKeyframeCard.Instance.headBobField.isFocused == false) { ActorKeyframeCard.Instance.headBobField.text = headBob.ToString("0.000"); }
|
||||
if (ActorKeyframeCard.Instance.headRotationField.isFocused == false) { ActorKeyframeCard.Instance.headRotationField.text = headAngle.ToString("0.000"); }
|
||||
if (ActorKeyframeCard.Instance.appendageRotationField.isFocused == false) { ActorKeyframeCard.Instance.appendageRotationField.text = appendageRotation.ToString("0.000"); }
|
||||
// Body
|
||||
actorBody.transform.position = bodyPos + actor.GetFinalTransformOffset();
|
||||
actorBody.transform.eulerAngles = new Vector3(0, 0, -bodyAngle);
|
||||
|
||||
if (actorID == Workspace.ActorID)
|
||||
{
|
||||
//handLeftControls.SetActive(clip.GetActorAddon("left hand").Render);
|
||||
//handRightControls.SetActive(clip.GetActorAddon("right hand").Render);
|
||||
//sexToyControls.SetActive(clip.GetActorAddon("dildo").Render);
|
||||
}
|
||||
actorBody.bodyRenderer.sortingLayerName = clip.Layer;
|
||||
actorBody.bodyRenderer.sprite = pawnRaceDef.GetBodyTypeGraphic((CardinalDirection)bodyFacing, bodyType);
|
||||
actorBody.bodyRenderer.flipX = bodyFacing == 3;
|
||||
|
||||
actorBody.bodyRenderer.gameObject.SetActive(actorBody.bodyRenderer.sprite != null);
|
||||
|
||||
// Head
|
||||
actorBodypart = actorBody.GetBodyPart("head");
|
||||
|
||||
actorBodypart.transform.localPosition = headPos;
|
||||
actorBodypart.transform.eulerAngles = new Vector3(0, 0, -headAngle);
|
||||
|
||||
actorBodypart.bodyPartRenderer.sortingLayerName = clip.Layer;
|
||||
actorBodypart.bodyPartRenderer.sortingOrder = bodyFacing == 0 ? -1 : 1;
|
||||
actorBodypart.bodyPartRenderer.sprite = pawnRaceDef.isHumanoid ? pawnRaceDef.GetHeadGraphic((CardinalDirection)headFacing) : null;
|
||||
actorBodypart.bodyPartRenderer.flipX = headFacing == 3;
|
||||
|
||||
actorBodypart.gameObject.SetActive(actorBodypart.bodyPartRenderer.sprite != null);
|
||||
|
||||
// Appendage
|
||||
actorBodypart = actorBody.GetBodyPart("appendage");
|
||||
|
||||
actorBodypart.transform.localPosition = new Vector3(appendagePos.x, appendagePos.z, 0f);
|
||||
actorBodypart.transform.eulerAngles = new Vector3(0, 0, -genitalAngle);
|
||||
|
||||
actorBodypart.bodyPartRenderer.sortingLayerName = clip.Layer;
|
||||
actorBodypart.bodyPartRenderer.sprite = requiresGenitals && pawnRaceDef.isHumanoid && bodyFacing != 0 ? Resources.Load<Sprite>("Textures/Humanlike/Appendages/Appendage" + bodyFacing) : null;
|
||||
//actorBody.appendageRenderer.flipX = bodyFacing == 3;
|
||||
|
||||
actorBodypart.gameObject.SetActive(actorBodypart.bodyPartRenderer.sprite != null);
|
||||
|
||||
// Add-ons
|
||||
foreach (ActorAddon addon in clip.Addons)
|
||||
{
|
||||
ActorBodyPart bodyPart = actorBody.GetComponentsInChildren<ActorBodyPart>()?.FirstOrDefault(x => x.addonName == addon.AddonName);
|
||||
if (bodyPart == null) continue;
|
||||
|
||||
Vector3 anchor;
|
||||
|
||||
actorBodypart = actorBody.GetBodyPart(addon.AddonName);
|
||||
|
||||
ActorBody anchoringActorBody = actorBodies.GetComponentsInChildren<ActorBody>()?.FirstOrDefault(x => x.actorID == addon.AnchoringActor);
|
||||
bodyPos = new Vector3(anchoringActorBody.transform.position.x, anchoringActorBody.transform.position.y, 0);
|
||||
pawnRaceDef = Workspace.animationDef.Actors[addon.AnchoringActor].GetPawnRaceDef();
|
||||
Actor anchoringActor = Workspace.animationDef.Actors[addon.AnchoringActor];
|
||||
bodyFacing = (int)Workspace.animationDef.AnimationStages[Workspace.StageID].AnimationClips[addon.AnchoringActor].BodyFacing.Evaluate(clipPercent);
|
||||
Vector3 anchor = PawnUtility.GetBodyPartAnchor(anchoringActorBody, addon.addonName);
|
||||
|
||||
switch (addon.AnchorName)
|
||||
{
|
||||
case "torso": anchor = bodyPos; break;
|
||||
case "head": anchor = new Vector3(anchoringActorBody.transform.Find("ActorHead").position.x, anchoringActorBody.transform.Find("ActorHead").position.y, 0); break;
|
||||
case "groin": anchor = bodyPos + Quaternion.AngleAxis(anchoringActorBody.transform.rotation.eulerAngles.z, Vector3.forward) * PawnUtility.GroinOffsetAt(anchoringActor.bodyType, bodyFacing).FlipAxes(); break;
|
||||
case "left breast": anchor = bodyPos + Quaternion.AngleAxis(anchoringActorBody.transform.rotation.eulerAngles.z, Vector3.forward) * PawnUtility.BreastLeftOffsetAt(anchoringActor.bodyType, bodyFacing).FlipAxes(); break;
|
||||
case "right breast": anchor = bodyPos + Quaternion.AngleAxis(anchoringActorBody.transform.rotation.eulerAngles.z, Vector3.forward) * PawnUtility.BreastRightOffsetAt(anchoringActor.bodyType, bodyFacing).FlipAxes(); break;
|
||||
default: anchor = new Vector3(); break;
|
||||
}
|
||||
actorBodypart.transform.position = anchor + new Vector3(addon.PosX.Evaluate(clipPercent), addon.PosZ.Evaluate(clipPercent), 0);
|
||||
actorBodypart.transform.eulerAngles = new Vector3(0, 0, -addon.Rotation.Evaluate(clipPercent));
|
||||
|
||||
bodyPart.transform.position = anchor + new Vector3(addon.PosX.Evaluate(clipPercent), addon.PosZ.Evaluate(clipPercent), 0);
|
||||
bodyPart.transform.eulerAngles = new Vector3(0, 0, -addon.Rotation.Evaluate(clipPercent));
|
||||
bodyPart.GetComponent<SpriteRenderer>().sortingLayerName = addon.Layer;
|
||||
actorBodypart.bodyPartRenderer.sortingLayerName = addon.Layer;
|
||||
//actorBodypart.bodyPartRenderer.sprite
|
||||
|
||||
actorBodypart.gameObject.SetActive(addon.Render);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
isDirty = true;
|
||||
Debug.Log("Initializing animation preview");
|
||||
|
||||
foreach (Transform child in transform)
|
||||
{ child.gameObject.SetActive(true); }
|
||||
|
||||
InitializeAnimationTimeline();
|
||||
StageCardManager.Instance.Initialize();
|
||||
|
||||
isDirty = false;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
isAnimating = false;
|
||||
timeSinceLastUpdate = 0;
|
||||
cycleIndex = 0;
|
||||
|
||||
MakeDirty();
|
||||
}
|
||||
|
||||
public void InitializeAnimationTimeline()
|
||||
{
|
||||
isTimelineDirty = true;
|
||||
|
||||
cyclesNormalField.text = Mathf.Max(Mathf.CeilToInt((float)Workspace.animationDef.AnimationStages[Workspace.StageID].PlayTimeTicks / Workspace.StageWindowSize), 1).ToString();
|
||||
cyclesFastField.text = Mathf.Max(Mathf.CeilToInt((float)Workspace.animationDef.AnimationStages[Workspace.StageID].PlayTimeTicksQuick / Workspace.StageWindowSize), 0).ToString();
|
||||
|
||||
Workspace.animationDef.AnimationStages[Workspace.StageID].IsLooping = int.Parse(cyclesNormalField.text) > 1 ? true : false;
|
||||
|
||||
int actorCount = Workspace.animationDef.Actors.Count;
|
||||
int childCount = animationTimelines.GetComponentsInChildren<AnimationTimeline>().Count();
|
||||
|
||||
|
@ -306,7 +203,7 @@ namespace RimWorldAnimationStudio
|
|||
{
|
||||
// Add new actors as required
|
||||
if (actorID >= childCount)
|
||||
{
|
||||
{
|
||||
Instantiate(animationTimelinePrefab, animationTimelines);
|
||||
Instantiate(actorBodyPrefab, actorBodies.transform);
|
||||
}
|
||||
|
@ -324,125 +221,21 @@ namespace RimWorldAnimationStudio
|
|||
|
||||
// Remove excess objects as required
|
||||
else
|
||||
{
|
||||
{
|
||||
Destroy(animationTimeline.transform.parent.gameObject);
|
||||
Destroy(actorBody.gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
animationClipLengthField.text = Workspace.StageWindowSize.ToString();
|
||||
stageTimelineSlider.maxValue = Workspace.StageWindowSize;
|
||||
|
||||
isTimelineDirty = false;
|
||||
|
||||
foreach (AnimationTimeline timeline in animationTimelines.GetComponentsInChildren<AnimationTimeline>())
|
||||
{ timeline.InitiateUpdateOfGhostFrames(); }
|
||||
}
|
||||
|
||||
public void ToggleAnimation()
|
||||
public void Reset()
|
||||
{
|
||||
isAnimating = !isAnimating;
|
||||
}
|
||||
|
||||
public void OnStageTimelineSliderChange()
|
||||
{
|
||||
if (Workspace.animationDef == null) return;
|
||||
|
||||
if (Workspace.StageTick != (int)stageTimelineSlider.value)
|
||||
{
|
||||
Workspace.StageTick = (int)stageTimelineSlider.value;
|
||||
animationClipTimeField.text = Workspace.StageTick.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
public void OnAnimationClipTimeFieldChange()
|
||||
{
|
||||
if (Workspace.animationDef == null) return;
|
||||
|
||||
int.TryParse(animationClipTimeField.text, out int newStageTick);
|
||||
Workspace.StageTick = Mathf.Clamp(newStageTick, Constants.minTick, Workspace.StageWindowSize);
|
||||
stageTimelineSlider.value = Workspace.StageTick;
|
||||
}
|
||||
|
||||
public void OnAnimationClipLengthFieldChange()
|
||||
{
|
||||
if (Workspace.animationDef == null) return;
|
||||
|
||||
int.TryParse(animationClipLengthField.text, out int newStageWindowSize);
|
||||
newStageWindowSize = Mathf.Clamp(newStageWindowSize, Constants.minAnimationClipLength, Constants.maxAnimationClipLength);
|
||||
|
||||
Debug.Log("Resizing animation clip length to " + newStageWindowSize.ToString() + " ticks.");
|
||||
|
||||
if (stretchKeyframesToggle.isOn)
|
||||
{ Workspace.GetCurrentAnimationStage().StretchStageWindow(newStageWindowSize); }
|
||||
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < Workspace.animationDef.AnimationStages[Workspace.StageID].AnimationClips.Count; i++)
|
||||
{
|
||||
PawnAnimationClip clip = Workspace.animationDef.AnimationStages[Workspace.StageID].AnimationClips[i];
|
||||
List<PawnKeyframe> keyframes = clip.Keyframes.Where(x => x.atTick > newStageWindowSize)?.ToList();
|
||||
|
||||
if (keyframes.NullOrEmpty())
|
||||
{ continue; }
|
||||
|
||||
foreach (PawnKeyframe keyframe in keyframes)
|
||||
{
|
||||
clip.RemovePawnKeyframe(i, keyframe.keyframeID);
|
||||
|
||||
if (Workspace.animationDef.AnimationStages[Workspace.StageID].AnimationClips[i].Keyframes.Count <= 2)
|
||||
{ break; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Workspace.GetCurrentAnimationStage().ResizeStageWindow(newStageWindowSize);
|
||||
Workspace.RecordEvent("Stage length");
|
||||
}
|
||||
|
||||
public void OnCycleNormalFieldChange()
|
||||
{
|
||||
if (Workspace.animationDef == null) return;
|
||||
|
||||
if (int.TryParse(cyclesNormalField.text, out int cycles))
|
||||
{
|
||||
cycles = cycles <= 0 ? 1 : cycles;
|
||||
cyclesNormalField.text = cycles.ToString();
|
||||
|
||||
Workspace.animationDef.AnimationStages[Workspace.StageID].PlayTimeTicks = cycles * Workspace.StageWindowSize;
|
||||
Workspace.animationDef.AnimationStages[Workspace.StageID].IsLooping = cycles > 1;
|
||||
|
||||
foreach(AnimationTimeline animationTimeline in animationTimelines.GetComponentsInChildren<AnimationTimeline>())
|
||||
{ animationTimeline.InitiateUpdateOfGhostFrames(); }
|
||||
}
|
||||
|
||||
Workspace.RecordEvent("Cycle count (normal)");
|
||||
}
|
||||
|
||||
public void OnCycleFastFieldChange()
|
||||
{
|
||||
if (Workspace.animationDef == null) return;
|
||||
|
||||
if (int.TryParse(cyclesFastField.text, out int fastCycles))
|
||||
{
|
||||
fastCycles = fastCycles < 0 ? 0 : fastCycles;
|
||||
|
||||
int.TryParse(cyclesNormalField.text, out int cycles);
|
||||
if (fastCycles > cycles) fastCycles = cycles;
|
||||
cyclesFastField.text = fastCycles.ToString();
|
||||
|
||||
Workspace.animationDef.AnimationStages[Workspace.StageID].PlayTimeTicksQuick = fastCycles * Workspace.StageWindowSize;
|
||||
}
|
||||
|
||||
Workspace.RecordEvent("Cycle count (fast)");
|
||||
}
|
||||
|
||||
public void OnPlayBackSpeedChange()
|
||||
{
|
||||
if (float.TryParse(playBackSpeedField.text, out playBackSpeed))
|
||||
{ playBackSpeed = Mathf.Clamp(playBackSpeed, 0.01f, 16f); }
|
||||
|
||||
playBackSpeedField.text = playBackSpeed.ToString();
|
||||
Workspace.isAnimating = false;
|
||||
timeSinceLastUpdate = 0;
|
||||
loopCount = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -73,7 +73,7 @@ namespace RimWorldAnimationStudio
|
|||
AnimationController.Instance.Reset();
|
||||
Workspace.Reset();
|
||||
|
||||
EventsManager.OnAnimationDefChanged();
|
||||
EventsManager.OnAnimationChanged();
|
||||
Workspace.RecordEvent("AnimationDef loaded");
|
||||
}
|
||||
|
||||
|
|
|
@ -204,7 +204,7 @@ namespace RimWorldAnimationStudio
|
|||
public void ToggleAnimationPreview()
|
||||
{
|
||||
if (Workspace.animationDef == null) return;
|
||||
AnimationController.Instance.ToggleAnimation();
|
||||
Workspace.isAnimating = !Workspace.isAnimating;
|
||||
}
|
||||
|
||||
public void AddKeyframe()
|
||||
|
@ -228,7 +228,9 @@ namespace RimWorldAnimationStudio
|
|||
public void DeleteKeyframes()
|
||||
{
|
||||
if (Workspace.animationDef == null) return;
|
||||
Workspace.GetCurrentPawnAnimationClip().RemovePawnKeyframe();
|
||||
|
||||
foreach (int keyframeID in Workspace.keyframeID)
|
||||
{ Workspace.GetAnimationClipThatOwnsKeyframe(keyframeID).RemovePawnKeyframe(keyframeID); }
|
||||
}
|
||||
|
||||
public void ActorMovementMode()
|
||||
|
@ -249,49 +251,65 @@ namespace RimWorldAnimationStudio
|
|||
public void AdjustActorUpward()
|
||||
{
|
||||
if (Workspace.animationDef == null) return;
|
||||
ActorKeyframeCard.Instance.AdjustActor(Vector2.up * largeStep);
|
||||
|
||||
PawnKeyframe keyframe = Workspace.GetCurrentPawnKeyframe(true);
|
||||
keyframe.AdjustActor(Vector2.up * largeStep);
|
||||
}
|
||||
|
||||
public void AdjustActorDownward()
|
||||
{
|
||||
if (Workspace.animationDef == null) return;
|
||||
ActorKeyframeCard.Instance.AdjustActor(Vector2.down * largeStep);
|
||||
|
||||
PawnKeyframe keyframe = Workspace.GetCurrentPawnKeyframe(true);
|
||||
keyframe.AdjustActor(Vector2.down * largeStep);
|
||||
}
|
||||
|
||||
public void AdjustActorLeftward()
|
||||
{
|
||||
if (Workspace.animationDef == null) return;
|
||||
ActorKeyframeCard.Instance.AdjustActor(Vector2.left * largeStep);
|
||||
|
||||
PawnKeyframe keyframe = Workspace.GetCurrentPawnKeyframe(true);
|
||||
keyframe.AdjustActor(Vector2.left * largeStep);
|
||||
}
|
||||
|
||||
public void AdjustActorRightward()
|
||||
{
|
||||
if (Workspace.animationDef == null) return;
|
||||
ActorKeyframeCard.Instance.AdjustActor(Vector2.right * largeStep);
|
||||
|
||||
PawnKeyframe keyframe = Workspace.GetCurrentPawnKeyframe(true);
|
||||
keyframe.AdjustActor(Vector2.right * largeStep);
|
||||
}
|
||||
|
||||
public void AdjustActorUpwardSmall()
|
||||
{
|
||||
if (Workspace.animationDef == null) return;
|
||||
ActorKeyframeCard.Instance.AdjustActor(Vector2.up * smallStep);
|
||||
|
||||
PawnKeyframe keyframe = Workspace.GetCurrentPawnKeyframe(true);
|
||||
keyframe.AdjustActor(Vector2.up * smallStep);
|
||||
}
|
||||
|
||||
public void AdjustActorDownwardSmall()
|
||||
{
|
||||
if (Workspace.animationDef == null) return;
|
||||
ActorKeyframeCard.Instance.AdjustActor(Vector2.down * smallStep);
|
||||
|
||||
PawnKeyframe keyframe = Workspace.GetCurrentPawnKeyframe(true);
|
||||
keyframe.AdjustActor(Vector2.down * smallStep);
|
||||
}
|
||||
|
||||
public void AdjustActorLeftwardSmall()
|
||||
{
|
||||
if (Workspace.animationDef == null) return;
|
||||
ActorKeyframeCard.Instance.AdjustActor(Vector2.left * smallStep);
|
||||
|
||||
PawnKeyframe keyframe = Workspace.GetCurrentPawnKeyframe(true);
|
||||
keyframe.AdjustActor(Vector2.left * smallStep);
|
||||
}
|
||||
|
||||
public void AdjustActorRightwardSmall()
|
||||
{
|
||||
if (Workspace.animationDef == null) return;
|
||||
ActorKeyframeCard.Instance.AdjustActor(Vector2.right * smallStep);
|
||||
|
||||
PawnKeyframe keyframe = Workspace.GetCurrentPawnKeyframe(true);
|
||||
keyframe.AdjustActor(Vector2.right * smallStep);
|
||||
}
|
||||
|
||||
public void CycleActorBodyPartSelecion()
|
||||
|
@ -407,7 +425,7 @@ namespace RimWorldAnimationStudio
|
|||
|
||||
public void StretchKeyframesToggle()
|
||||
{
|
||||
AnimationController.Instance.stretchKeyframesToggle.isOn = !AnimationController.Instance.stretchKeyframesToggle.isOn;
|
||||
Workspace.stretchKeyframes = !Workspace.stretchKeyframes;
|
||||
}
|
||||
|
||||
public void OpenProjectHome()
|
||||
|
@ -435,5 +453,26 @@ namespace RimWorldAnimationStudio
|
|||
|
||||
Workspace.animationDef.RemoveActor();
|
||||
}
|
||||
|
||||
public void AddStage()
|
||||
{
|
||||
if (Workspace.animationDef == null) return;
|
||||
|
||||
Workspace.animationDef.AddAnimationStage();
|
||||
}
|
||||
|
||||
public void CloneStage()
|
||||
{
|
||||
if (Workspace.animationDef == null) return;
|
||||
|
||||
Workspace.animationDef.CloneAnimationStage();
|
||||
}
|
||||
|
||||
public void RemoveStage()
|
||||
{
|
||||
if (Workspace.animationDef == null) return;
|
||||
|
||||
Workspace.animationDef.RemoveAnimationStage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,11 @@ namespace RimWorldAnimationStudio
|
|||
|
||||
public void Start()
|
||||
{
|
||||
EventsManager.onAnimationChanged.AddListener(delegate { Initialize(); });
|
||||
EventsManager.onStageIDChanged.AddListener(delegate { Initialize(); });
|
||||
EventsManager.onStageCountChanged.AddListener(delegate { Initialize(); });
|
||||
|
||||
Initialize();
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue