using System.Collections; using System.Collections.Generic; using System.Linq; using UnityEngine; using UnityEngine.EventSystems; namespace RimWorldAnimationStudio { public class ActorBodyPart : MonoBehaviour, IPointerClickHandler, IDragHandler, IEndDragHandler { public SpriteRenderer bodyPartRenderer; public ActorBody parent; public bool isHead = false; public string addonName; public bool isSelected = false; private Vector3 delta = new Vector3(); public void Update() { if ((Workspace.actorID == parent.actorID && Workspace.selectedBodyPart == null) || Workspace.selectedBodyPart == this) { bodyPartRenderer.color = Constants.ColorGreen; } else { bodyPartRenderer.color = Constants.ColorWhite; } } public void OnPointerClick(PointerEventData eventData) { if (eventData.pointerCurrentRaycast.gameObject.GetComponent() == null) { return; } Activate(); } public void OnDrag(PointerEventData eventData) { Activate(); PawnKeyframe keyframe = Workspace.Instance.GetCurrentPawnKeyframe(true); if (keyframe == null) { Debug.LogWarning("Cannot alter actor - no keyframe data available"); return; } Vector3 mousePosition = Camera.main.ScreenToWorldPoint(Input.mousePosition); if (delta == Vector3.zero) { delta = mousePosition - transform.position; } if (addonName != null && addonName != "") { AddonKeyframe addonKeyframe = keyframe.GetAddonKeyframe(addonName); ActorAddon addon = Workspace.Instance.GetCurrentPawnAnimationClip().GetActorAddon(addonName); if (Workspace.actorManipulationMode == ActorManipulationMode.Pan) { Vector3 anchor; ActorBody anchoringActorBody = AnimationController.Instance.actorBodies.GetComponentsInChildren()?.FirstOrDefault(x => x.actorID == addon.anchoringActor); Vector3 bodyPos = new Vector3(anchoringActorBody.transform.position.x, anchoringActorBody.transform.position.y, 0); AlienRaceDef alienRaceDef = Workspace.animationDef.actors[addon.anchoringActor].GetAlienRaceDef(); Actor anchoringActor = Workspace.animationDef.actors[addon.anchoringActor]; int bodyFacing = (int)Workspace.animationDef.animationStages[Workspace.stageID].animationClips[addon.anchoringActor].BodyFacing.Evaluate((float)AnimationController.Instance.stageTick / Workspace.StageWindowSize); 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; } transform.position = new Vector3(mousePosition.x, mousePosition.y, 0f); addonKeyframe.posX = transform.position.x - anchor.x; addonKeyframe.posZ = transform.position.y - anchor.y; ActorKeyframeCard.Instance.transform.GetComponentsInChildren()?.FirstOrDefault(x => x.addonName == addonName)?.OnKeyframeValueChanged(); } else if (Workspace.actorManipulationMode == ActorManipulationMode.Rotate) { float angle = -Vector2.SignedAngle(Vector2.down, (Vector2)mousePosition - (Vector2)transform.position); addonKeyframe.rotation = angle; } else if (Workspace.actorManipulationMode == ActorManipulationMode.Face) { //float angle = Vector2.SignedAngle(Vector2.up, (Vector2)mousePosition - (Vector2)transform.position); //int facing = -Mathf.RoundToInt(angle / 90f); //facing = facing < 0 ? facing + 4 : facing; //keyframe.headFacing = facing; } } else if (isHead) { if (Workspace.actorManipulationMode == ActorManipulationMode.Pan) { // It's stupid but it works Vector3 localPosA = transform.localPosition; transform.position = mousePosition - delta; Vector3 localPosB = transform.localPosition; transform.localPosition = localPosA; keyframe.headBob += localPosB.y - localPosA.y; } else if (Workspace.actorManipulationMode == ActorManipulationMode.Rotate) { float angle = -Vector2.SignedAngle(Vector2.down, (Vector2)mousePosition - (Vector2)transform.position); keyframe.headAngle = angle; } else if (Workspace.actorManipulationMode == ActorManipulationMode.Face) { float angle = Vector2.SignedAngle(Vector2.up, (Vector2)mousePosition - (Vector2)transform.position); int facing = -Mathf.RoundToInt(angle / 90f); facing = facing < 0 ? facing + 4 : facing; keyframe.headFacing = facing; } } else { if (Workspace.actorManipulationMode == ActorManipulationMode.Rotate) { float angle = -Vector2.SignedAngle(Vector2.up, (Vector2)mousePosition - (Vector2)transform.position); keyframe.genitalAngle = angle; Workspace.animationDef.actors[Workspace.actorID].controlGenitalAngle = Workspace.animationDef.animationStages.Any(x => x.animationClips[Workspace.actorID].keyframes.Any(y => y.genitalAngle != 0)); } } PawnAnimationClip clip = Workspace.Instance.GetPawnAnimationClip(parent.actorID); clip.BuildSimpleCurves(); } public void OnEndDrag(PointerEventData eventData) { Workspace.Instance.RecordEvent("Actor position / orientation"); delta = Vector3.zero; } public void Activate() { Workspace.actorID = parent.actorID; Workspace.selectedBodyPart = this; } } }