Code refactor

This commit is contained in:
AbstractConcept 2022-10-28 00:28:51 -05:00
parent 757badf4f6
commit a55ba7b95b
232 changed files with 1282 additions and 936 deletions

View file

@ -173,9 +173,7 @@ MonoBehaviour:
m_EditorClassIdentifier:
bodyPartRenderer: {fileID: 3345967395353432914}
parent: {fileID: -4411442180840688308}
isHead: 0
addonName: right hand
isSelected: 0
bodyPart: right hand
--- !u!1 &2846713953308910856
GameObject:
m_ObjectHideFlags: 0
@ -340,9 +338,7 @@ MonoBehaviour:
m_EditorClassIdentifier:
bodyPartRenderer: {fileID: 4070361490379091543}
parent: {fileID: -4411442180840688308}
isHead: 0
addonName: left hand
isSelected: 0
bodyPart: left hand
--- !u!1 &3158459618386162366
GameObject:
m_ObjectHideFlags: 0
@ -658,9 +654,7 @@ MonoBehaviour:
m_EditorClassIdentifier:
bodyPartRenderer: {fileID: 7367385255154626542}
parent: {fileID: -4411442180840688308}
isHead: 0
addonName: dildo
isSelected: 0
bodyPart: dildo
--- !u!1 &7929422519883802246
GameObject:
m_ObjectHideFlags: 0
@ -818,9 +812,7 @@ MonoBehaviour:
m_EditorClassIdentifier:
bodyPartRenderer: {fileID: 7929422519883802244}
parent: {fileID: -4411442180840688308}
isHead: 1
addonName:
isSelected: 0
bodyPart: head
--- !u!1 &7929422520673851210
GameObject:
m_ObjectHideFlags: 0
@ -871,10 +863,7 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
actorID: 0
isSelected: 0
bodyRenderer: {fileID: 5996161745621340017}
headRenderer: {fileID: 7929422519883802244}
appendageRenderer: {fileID: 4251726083449519904}
--- !u!1 &9122292209377678227
GameObject:
m_ObjectHideFlags: 0
@ -1048,6 +1037,4 @@ MonoBehaviour:
m_EditorClassIdentifier:
bodyPartRenderer: {fileID: 4251726083449519904}
parent: {fileID: -4411442180840688308}
isHead: 0
addonName:
isSelected: 0
bodyPart: appendage

View file

@ -77,7 +77,7 @@ MonoBehaviour:
m_HorizontalOverflow: 0
m_VerticalOverflow: 0
m_LineSpacing: 1
m_Text: New Stage
m_Text: Empty
--- !u!1 &533195464737222177
GameObject:
m_ObjectHideFlags: 0
@ -207,18 +207,7 @@ MonoBehaviour:
m_CharacterLimit: 0
m_OnEndEdit:
m_PersistentCalls:
m_Calls:
- m_Target: {fileID: 2278168916950142456}
m_MethodName: OnNameChange
m_Mode: 1
m_Arguments:
m_ObjectArgument: {fileID: 0}
m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
m_IntArgument: 0
m_FloatArgument: 0
m_StringArgument:
m_BoolArgument: 0
m_CallState: 2
m_Calls: []
m_OnValueChanged:
m_PersistentCalls:
m_Calls: []

View file

@ -133,7 +133,6 @@ GameObject:
- component: {fileID: 11575770}
- component: {fileID: 11575769}
- component: {fileID: 11575768}
- component: {fileID: 11575767}
m_Layer: 5
m_Name: SelectRaceDropdown
m_TagString: Untagged
@ -163,21 +162,6 @@ RectTransform:
m_AnchoredPosition: {x: 10, y: -150}
m_SizeDelta: {x: 120, y: 30}
m_Pivot: {x: 0, y: 1}
--- !u!114 &11575767
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 11575765}
m_Enabled: 0
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 0ba5b69d448f9434ca7d74d4022f3dcd, type: 3}
m_Name:
m_EditorClassIdentifier:
dropdown: {fileID: 0}
label: {fileID: 0}
hashcode: -1
--- !u!114 &11575768
MonoBehaviour:
m_ObjectHideFlags: 0
@ -454,6 +438,7 @@ GameObject:
- component: {fileID: 40289126}
- component: {fileID: 40289125}
- component: {fileID: 40289124}
- component: {fileID: 40289128}
m_Layer: 5
m_Name: posOffsetXField
m_TagString: Untagged
@ -606,6 +591,18 @@ CanvasRenderer:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 40289122}
m_CullTransparentMesh: 0
--- !u!114 &40289128
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 40289122}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 92068b39ed172084296a595f5a09e54b, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!1 &40775274
GameObject:
m_ObjectHideFlags: 0
@ -3563,6 +3560,7 @@ GameObject:
- component: {fileID: 254347859}
- component: {fileID: 254347858}
- component: {fileID: 254347862}
- component: {fileID: 254347863}
m_Layer: 5
m_Name: headBobField
m_TagString: Untagged
@ -3622,18 +3620,7 @@ MonoBehaviour:
m_CharacterLimit: 0
m_OnEndEdit:
m_PersistentCalls:
m_Calls:
- m_Target: {fileID: 629081417}
m_MethodName: OnValueChanged
m_Mode: 1
m_Arguments:
m_ObjectArgument: {fileID: 0}
m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
m_IntArgument: 0
m_FloatArgument: 0
m_StringArgument:
m_BoolArgument: 0
m_CallState: 2
m_Calls: []
m_OnValueChanged:
m_PersistentCalls:
m_Calls: []
@ -3715,6 +3702,18 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
valiationType: 2
--- !u!114 &254347863
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 254347857}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 92068b39ed172084296a595f5a09e54b, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!1 &257134980
GameObject:
m_ObjectHideFlags: 0
@ -7825,6 +7824,7 @@ GameObject:
- component: {fileID: 444811204}
- component: {fileID: 444811203}
- component: {fileID: 444811202}
- component: {fileID: 444811206}
m_Layer: 5
m_Name: rotationField
m_TagString: Untagged
@ -7977,6 +7977,18 @@ CanvasRenderer:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 444811200}
m_CullTransparentMesh: 0
--- !u!114 &444811206
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 444811200}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 92068b39ed172084296a595f5a09e54b, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!1 &448745871
GameObject:
m_ObjectHideFlags: 0
@ -8253,8 +8265,9 @@ GameObject:
serializedVersion: 6
m_Component:
- component: {fileID: 468781281}
- component: {fileID: 468781282}
m_Layer: 5
m_Name: StageCycleCard
m_Name: StageLoopsCard
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
@ -8281,6 +8294,20 @@ RectTransform:
m_AnchoredPosition: {x: 155, y: -315}
m_SizeDelta: {x: 310, y: 70}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &468781282
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 468781280}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 38691dc973d99734f8f0f2a240df73fe, type: 3}
m_Name:
m_EditorClassIdentifier:
stageLoopsNormalField: {fileID: 74082975}
stageLoopsQuickField: {fileID: 1463915054}
--- !u!1 &476324336
GameObject:
m_ObjectHideFlags: 0
@ -9638,23 +9665,9 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
isAnimating: 0
stageTimelineSlider: {fileID: 1289465655}
stageLoopDropdown: {fileID: 429161118}
cyclesNormalField: {fileID: 74082975}
cyclesFastField: {fileID: 1463915054}
animationClipTimeField: {fileID: 760297267}
animationClipLengthField: {fileID: 1676585155}
actorCard: {fileID: 0}
animationTimelines: {fileID: 1100016168}
actorBodies: {fileID: 1828035561}
stretchKeyframesToggle: {fileID: 462332576}
playBackSpeedField: {fileID: 1579799916}
playToggleButton: {fileID: 79733375}
stageLengthText: {fileID: 1137451986}
animationLengthText: {fileID: 1293297801}
handLeftControls: {fileID: 374385281}
handRightControls: {fileID: 613856053}
sexToyControls: {fileID: 2069775739}
stageLoopDropdown: {fileID: 429161118}
actorBodyPrefab: {fileID: -4411442180840688308, guid: dc4c8b005322f3b46a2f122a55f38db2,
type: 3}
animationTimelinePrefab: {fileID: 3541467645058788217, guid: eac2d5e7275f9064facfeb818ee30308,
@ -10201,8 +10214,9 @@ GameObject:
- component: {fileID: 539052777}
- component: {fileID: 539052779}
- component: {fileID: 539052781}
- component: {fileID: 539052778}
m_Layer: 5
m_Name: AnimControlPanel
m_Name: AnimControlCard
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
@ -10236,6 +10250,25 @@ RectTransform:
m_AnchoredPosition: {x: 10, y: -22.5}
m_SizeDelta: {x: 1375.8606, y: 45}
m_Pivot: {x: 0, y: 0.5}
--- !u!114 &539052778
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 539052776}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 6b414452bfd6c9b4bb99542a51d77468, type: 3}
m_Name:
m_EditorClassIdentifier:
stageLoopDropdown: {fileID: 429161118}
animationClipTimeField: {fileID: 760297267}
animationClipLengthField: {fileID: 1676585155}
stretchKeyframesToggle: {fileID: 462332576}
playBackSpeedField: {fileID: 1579799916}
playToggleButton: {fileID: 79733375}
stageTimelineSlider: {fileID: 1289465655}
--- !u!222 &539052779
CanvasRenderer:
m_ObjectHideFlags: 0
@ -10916,8 +10949,8 @@ MonoBehaviour:
m_OnClick:
m_PersistentCalls:
m_Calls:
- m_Target: {fileID: 542629604}
m_MethodName: OnNewStage
- m_Target: {fileID: 1335076905}
m_MethodName: AddStage
m_Mode: 1
m_Arguments:
m_ObjectArgument: {fileID: 0}
@ -12096,6 +12129,7 @@ GameObject:
- component: {fileID: 619777500}
- component: {fileID: 619777499}
- component: {fileID: 619777498}
- component: {fileID: 619777502}
m_Layer: 5
m_Name: posOffsetZField
m_TagString: Untagged
@ -12237,6 +12271,18 @@ CanvasRenderer:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 619777496}
m_CullTransparentMesh: 0
--- !u!114 &619777502
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 619777496}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 92068b39ed172084296a595f5a09e54b, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!1 &620055138
GameObject:
m_ObjectHideFlags: 0
@ -12823,9 +12869,9 @@ RectTransform:
m_Father: {fileID: 935483303140078260}
m_RootOrder: 1
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0, y: 0}
m_AnchorMin: {x: 0, y: 1}
m_AnchorMax: {x: 0, y: 1}
m_AnchoredPosition: {x: 155, y: -166.98029}
m_SizeDelta: {x: 310, y: 65.97644}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!1 &658284331
@ -14056,6 +14102,7 @@ GameObject:
- component: {fileID: 725162533}
- component: {fileID: 725162532}
- component: {fileID: 725162535}
- component: {fileID: 725162536}
m_Layer: 5
m_Name: rotationField
m_TagString: Untagged
@ -14135,18 +14182,7 @@ MonoBehaviour:
m_CharacterLimit: 0
m_OnEndEdit:
m_PersistentCalls:
m_Calls:
- m_Target: {fileID: 629081417}
m_MethodName: OnValueChanged
m_Mode: 1
m_Arguments:
m_ObjectArgument: {fileID: 0}
m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
m_IntArgument: 0
m_FloatArgument: 0
m_StringArgument:
m_BoolArgument: 0
m_CallState: 2
m_Calls: []
m_OnValueChanged:
m_PersistentCalls:
m_Calls: []
@ -14208,6 +14244,18 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
valiationType: 2
--- !u!114 &725162536
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 725162530}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 92068b39ed172084296a595f5a09e54b, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!1 &726027038
GameObject:
m_ObjectHideFlags: 0
@ -14651,6 +14699,7 @@ GameObject:
- component: {fileID: 760297268}
- component: {fileID: 760297267}
- component: {fileID: 760297270}
- component: {fileID: 760297271}
m_Layer: 5
m_Name: AnimationClipTimeField
m_TagString: Untagged
@ -14803,6 +14852,18 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
valiationType: 1
--- !u!114 &760297271
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 760297265}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 92068b39ed172084296a595f5a09e54b, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!1 &763620509
GameObject:
m_ObjectHideFlags: 0
@ -16809,6 +16870,7 @@ GameObject:
- component: {fileID: 891720216}
- component: {fileID: 891720215}
- component: {fileID: 891720218}
- component: {fileID: 891720219}
m_Layer: 5
m_Name: posOffsetXField
m_TagString: Untagged
@ -16888,18 +16950,7 @@ MonoBehaviour:
m_CharacterLimit: 0
m_OnEndEdit:
m_PersistentCalls:
m_Calls:
- m_Target: {fileID: 629081417}
m_MethodName: OnValueChanged
m_Mode: 1
m_Arguments:
m_ObjectArgument: {fileID: 0}
m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
m_IntArgument: 0
m_FloatArgument: 0
m_StringArgument:
m_BoolArgument: 0
m_CallState: 2
m_Calls: []
m_OnValueChanged:
m_PersistentCalls:
m_Calls: []
@ -16961,6 +17012,18 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
valiationType: 2
--- !u!114 &891720219
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 891720213}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 92068b39ed172084296a595f5a09e54b, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!1 &898059650
GameObject:
m_ObjectHideFlags: 0
@ -17256,6 +17319,7 @@ GameObject:
- component: {fileID: 906179602}
- component: {fileID: 906179601}
- component: {fileID: 906179600}
- component: {fileID: 906179604}
m_Layer: 5
m_Name: rotationField
m_TagString: Untagged
@ -17408,6 +17472,18 @@ CanvasRenderer:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 906179598}
m_CullTransparentMesh: 0
--- !u!114 &906179604
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 906179598}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 92068b39ed172084296a595f5a09e54b, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!1 &911162557
GameObject:
m_ObjectHideFlags: 0
@ -17648,7 +17724,7 @@ RectTransform:
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 0.99997056}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 20, y: 20}
m_Pivot: {x: 0.5, y: 0.5}
@ -21067,6 +21143,7 @@ GameObject:
- component: {fileID: 1152532962}
- component: {fileID: 1152532961}
- component: {fileID: 1152532960}
- component: {fileID: 1152532964}
m_Layer: 5
m_Name: posOffsetXField
m_TagString: Untagged
@ -21219,6 +21296,18 @@ CanvasRenderer:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1152532958}
m_CullTransparentMesh: 0
--- !u!114 &1152532964
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1152532958}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 92068b39ed172084296a595f5a09e54b, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!1 &1153227822
GameObject:
m_ObjectHideFlags: 0
@ -21301,7 +21390,7 @@ MonoBehaviour:
m_HandleRect: {fileID: 922060209}
m_Direction: 2
m_Value: 0
m_Size: 0.99997056
m_Size: 1
m_NumberOfSteps: 0
m_OnValueChanged:
m_PersistentCalls:
@ -21667,8 +21756,8 @@ MonoBehaviour:
m_OnClick:
m_PersistentCalls:
m_Calls:
- m_Target: {fileID: 542629604}
m_MethodName: OnRemoveStage
- m_Target: {fileID: 1335076905}
m_MethodName: RemoveStage
m_Mode: 1
m_Arguments:
m_ObjectArgument: {fileID: 0}
@ -22802,9 +22891,9 @@ RectTransform:
m_Father: {fileID: 935483303140078260}
m_RootOrder: 2
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0, y: 0}
m_AnchorMin: {x: 0, y: 1}
m_AnchorMax: {x: 0, y: 1}
m_AnchoredPosition: {x: 155, y: -337.8237}
m_SizeDelta: {x: 310, y: 275.7104}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &1216651061
@ -23154,12 +23243,12 @@ PrefabInstance:
type: 3}
propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[1].m_Target
value:
objectReference: {fileID: 1567848590}
objectReference: {fileID: 0}
- target: {fileID: 7715503544528335667, guid: 8b89f6c9e5f696c4997760829c45a505,
type: 3}
propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[2].m_Target
value:
objectReference: {fileID: 11575767}
objectReference: {fileID: 0}
- target: {fileID: 7715503544528335667, guid: 8b89f6c9e5f696c4997760829c45a505,
type: 3}
propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[1].m_CallState
@ -25222,7 +25311,7 @@ GameObject:
- component: {fileID: 1335076900}
- component: {fileID: 1335076905}
m_Layer: 5
m_Name: Workspace
m_Name: WorkspaceAndGUI
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
@ -29764,8 +29853,8 @@ MonoBehaviour:
m_OnClick:
m_PersistentCalls:
m_Calls:
- m_Target: {fileID: 542629604}
m_MethodName: OnCloneStage
- m_Target: {fileID: 1335076905}
m_MethodName: CloneStage
m_Mode: 1
m_Arguments:
m_ObjectArgument: {fileID: 0}
@ -29825,6 +29914,7 @@ GameObject:
- component: {fileID: 1518099309}
- component: {fileID: 1518099308}
- component: {fileID: 1518099311}
- component: {fileID: 1518099312}
m_Layer: 5
m_Name: posOffsetZField
m_TagString: Untagged
@ -29904,18 +29994,7 @@ MonoBehaviour:
m_CharacterLimit: 0
m_OnEndEdit:
m_PersistentCalls:
m_Calls:
- m_Target: {fileID: 629081417}
m_MethodName: OnValueChanged
m_Mode: 1
m_Arguments:
m_ObjectArgument: {fileID: 0}
m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
m_IntArgument: 0
m_FloatArgument: 0
m_StringArgument:
m_BoolArgument: 0
m_CallState: 2
m_Calls: []
m_OnValueChanged:
m_PersistentCalls:
m_Calls: []
@ -29977,6 +30056,18 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
valiationType: 2
--- !u!114 &1518099312
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1518099306}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 92068b39ed172084296a595f5a09e54b, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!1 &1522728394
GameObject:
m_ObjectHideFlags: 0
@ -30299,6 +30390,7 @@ GameObject:
- component: {fileID: 1560400021}
- component: {fileID: 1560400020}
- component: {fileID: 1560400019}
- component: {fileID: 1560400023}
m_Layer: 5
m_Name: posOffsetZField
m_TagString: Untagged
@ -30451,6 +30543,18 @@ CanvasRenderer:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1560400017}
m_CullTransparentMesh: 0
--- !u!114 &1560400023
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1560400017}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 92068b39ed172084296a595f5a09e54b, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!1 &1561986055
GameObject:
m_ObjectHideFlags: 0
@ -30697,7 +30801,6 @@ GameObject:
- component: {fileID: 1567848593}
- component: {fileID: 1567848592}
- component: {fileID: 1567848591}
- component: {fileID: 1567848590}
m_Layer: 5
m_Name: RaceSelectDropdown
m_TagString: Untagged
@ -30727,21 +30830,6 @@ RectTransform:
m_AnchoredPosition: {x: 178, y: 0}
m_SizeDelta: {x: 160, y: 30}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &1567848590
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1567848588}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 0ba5b69d448f9434ca7d74d4022f3dcd, type: 3}
m_Name:
m_EditorClassIdentifier:
dropdown: {fileID: 0}
label: {fileID: 0}
hashcode: -1
--- !u!114 &1567848591
MonoBehaviour:
m_ObjectHideFlags: 0
@ -31888,6 +31976,7 @@ GameObject:
- component: {fileID: 1668270819}
- component: {fileID: 1668270818}
- component: {fileID: 1668270821}
- component: {fileID: 1668270822}
m_Layer: 5
m_Name: appendageRotationField
m_TagString: Untagged
@ -32040,6 +32129,18 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
valiationType: 2
--- !u!114 &1668270822
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1668270816}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 92068b39ed172084296a595f5a09e54b, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!1 &1670013372
GameObject:
m_ObjectHideFlags: 0
@ -32245,6 +32346,7 @@ GameObject:
- component: {fileID: 1676585156}
- component: {fileID: 1676585155}
- component: {fileID: 1676585158}
- component: {fileID: 1676585159}
m_Layer: 5
m_Name: AnimationClipLengthField
m_TagString: Untagged
@ -32397,6 +32499,18 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
valiationType: 1
--- !u!114 &1676585159
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1676585153}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 92068b39ed172084296a595f5a09e54b, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!1 &1685703671
GameObject:
m_ObjectHideFlags: 0
@ -33698,6 +33812,7 @@ GameObject:
- component: {fileID: 1767445798}
- component: {fileID: 1767445797}
- component: {fileID: 1767445801}
- component: {fileID: 1767445802}
m_Layer: 5
m_Name: headRotationField
m_TagString: Untagged
@ -33757,18 +33872,7 @@ MonoBehaviour:
m_CharacterLimit: 0
m_OnEndEdit:
m_PersistentCalls:
m_Calls:
- m_Target: {fileID: 629081417}
m_MethodName: OnValueChanged
m_Mode: 1
m_Arguments:
m_ObjectArgument: {fileID: 0}
m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
m_IntArgument: 0
m_FloatArgument: 0
m_StringArgument:
m_BoolArgument: 0
m_CallState: 2
m_Calls: []
m_OnValueChanged:
m_PersistentCalls:
m_Calls: []
@ -33850,6 +33954,18 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
valiationType: 2
--- !u!114 &1767445802
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1767445796}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 92068b39ed172084296a595f5a09e54b, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!1 &1776904761
GameObject:
m_ObjectHideFlags: 0
@ -36271,6 +36387,7 @@ GameObject:
- component: {fileID: 1899457113}
- component: {fileID: 1899457112}
- component: {fileID: 1899457111}
- component: {fileID: 1899457115}
m_Layer: 5
m_Name: rotationField
m_TagString: Untagged
@ -36412,6 +36529,18 @@ CanvasRenderer:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1899457109}
m_CullTransparentMesh: 0
--- !u!114 &1899457115
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1899457109}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 92068b39ed172084296a595f5a09e54b, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!1 &1900570404
GameObject:
m_ObjectHideFlags: 0
@ -36981,6 +37110,7 @@ GameObject:
- component: {fileID: 1925610721}
- component: {fileID: 1925610720}
- component: {fileID: 1925610719}
- component: {fileID: 1925610723}
m_Layer: 5
m_Name: posOffsetZField
m_TagString: Untagged
@ -37133,6 +37263,18 @@ CanvasRenderer:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1925610717}
m_CullTransparentMesh: 0
--- !u!114 &1925610723
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1925610717}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 92068b39ed172084296a595f5a09e54b, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!1 &1928565389
GameObject:
m_ObjectHideFlags: 0
@ -39224,6 +39366,7 @@ GameObject:
- component: {fileID: 2114146443}
- component: {fileID: 2114146442}
- component: {fileID: 2114146441}
- component: {fileID: 2114146445}
m_Layer: 5
m_Name: posOffsetXField
m_TagString: Untagged
@ -39365,6 +39508,18 @@ CanvasRenderer:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2114146439}
m_CullTransparentMesh: 0
--- !u!114 &2114146445
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2114146439}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 92068b39ed172084296a595f5a09e54b, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!1 &2114503331
GameObject:
m_ObjectHideFlags: 0
@ -39679,9 +39834,9 @@ RectTransform:
m_Father: {fileID: 935483303140078260}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0, y: 0}
m_AnchorMin: {x: 0, y: 1}
m_AnchorMax: {x: 0, y: 1}
m_AnchoredPosition: {x: 155, y: -66.99603}
m_SizeDelta: {x: 310, y: 133.99207}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &2130812670
@ -40435,7 +40590,7 @@ GameObject:
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
m_IsActive: 0
--- !u!222 &935483303140078262
CanvasRenderer:
m_ObjectHideFlags: 0
@ -42532,7 +42687,7 @@ MonoBehaviour:
m_StringArgument:
m_BoolArgument: 0
m_CallState: 2
- m_Target: {fileID: 1567848590}
- m_Target: {fileID: 0}
m_MethodName: UpdateDropdown
m_Mode: 1
m_Arguments:
@ -42543,7 +42698,7 @@ MonoBehaviour:
m_StringArgument:
m_BoolArgument: 0
m_CallState: 2
- m_Target: {fileID: 11575767}
- m_Target: {fileID: 0}
m_MethodName: UpdateDropdown
m_Mode: 1
m_Arguments:

View file

@ -36,60 +36,60 @@ namespace RimWorldAnimationStudio
[XmlIgnore] public List<string> DefNames
{
get { return defNames.NullOrEmpty() ? defNames = new List<string>() : defNames; }
set { defNames = value.NotNullOrEmpty() ? value : null; EventsManager.OnActorChanged(this); }
set { defNames = value.NotNullOrEmpty() ? value : null; }
}
[XmlIgnore] public List<string> BodyDefTypes
{
get { return bodyDefTypes.NullOrEmpty() ? bodyDefTypes = new List<string>() : bodyDefTypes; }
set { bodyDefTypes = value.NotNullOrEmpty() ? value : null; EventsManager.OnActorChanged(this); }
set { bodyDefTypes = value.NotNullOrEmpty() ? value : null; }
}
[XmlIgnore] public List<string> RequiredGenitals
{
get { return requiredGenitals.NullOrEmpty() ? requiredGenitals = new List<string>() : requiredGenitals; }
set { requiredGenitals = value.NotNullOrEmpty() ? value : null; EventsManager.OnActorChanged(this); }
set { requiredGenitals = value.NotNullOrEmpty() ? value : null; }
}
[XmlIgnore] public List<PawnRaceOffset> RaceOffsets {
get { return raceOffsets.NullOrEmpty() ? raceOffsets = new List<PawnRaceOffset>() : raceOffsets; }
set { raceOffsets = value.NotNullOrEmpty() ? value : null; EventsManager.OnActorChanged(this); }
set { raceOffsets = value.NotNullOrEmpty() ? value : null; }
}
[XmlIgnore] public List<string> Tags
{
get { return tags.NullOrEmpty() ? tags = new List<string>() : tags; }
set { tags = value.NotNullOrEmpty() ? value : null; EventsManager.OnActorChanged(this); }
set { tags = value.NotNullOrEmpty() ? value : null; }
}
[XmlIgnore] public BodyTypeOffset BodyTypeOffset
{
get { return bodyTypeOffset == null ? bodyTypeOffset = new BodyTypeOffset() : bodyTypeOffset; }
set { bodyTypeOffset = value; EventsManager.OnActorChanged(this); }
set { bodyTypeOffset = value; }
}
[XmlIgnore] public bool Initiator
{
get { return initiator == true; }
set { if (value) { initiator = true; } else initiator = null; EventsManager.OnActorChanged(this); }
set { if (value) { initiator = true; } else initiator = null; }
}
[XmlIgnore] public bool ControlGenitalAngle
{
get { return controlGenitalAngle == true; }
set { if (value) { controlGenitalAngle = true; } else controlGenitalAngle = null; EventsManager.OnActorChanged(this); }
set { if (value) { controlGenitalAngle = true; } else controlGenitalAngle = null; }
}
[XmlIgnore] public bool IsFucking
{
get { return isFucking == true; }
set { if (value) { isFucking = true; } else isFucking = null; EventsManager.OnActorChanged(this); }
set { if (value) { isFucking = true; } else isFucking = null; }
}
[XmlIgnore] public bool IsFucked
{
get { return isFucked == true; }
set { if (value) { isFucked = true; } else isFucked = null; EventsManager.OnActorChanged(this); }
set { if (value) { isFucked = true; } else isFucked = null; }
}
// Local data
@ -163,6 +163,16 @@ namespace RimWorldAnimationStudio
return Workspace.animationDef.Actors.IndexOf(this);
}
public ActorPosition GetCurrentPosition()
{
return GetPositionAtTick(Workspace.StageTick);
}
public ActorPosition GetPositionAtTick(int atTick)
{
return new ActorPosition(GetActorID(), atTick);
}
// Pre-save / post-load
public void OnPreSave()
{

View file

@ -28,31 +28,31 @@ namespace RimWorldAnimationStudio
[XmlIgnore] public int AnchoringActor
{
get { return anchoringActor.HasValue ? anchoringActor.Value : 0; }
set { anchoringActor = value; EventsManager.OnActorAddonChanged(this); }
set { anchoringActor = value; }
}
[XmlIgnore] public string AnchorName
{
get { return anchorName; }
set { anchorName = value; EventsManager.OnActorAddonChanged(this); }
set { anchorName = value; }
}
[XmlIgnore] public string Layer
{
get { return layer; }
set { layer = value; EventsManager.OnActorAddonChanged(this); }
set { layer = value; }
}
[XmlIgnore] public float Scale
{
get { return scale.HasValue ? scale.Value : 0f; }
set { scale = value; EventsManager.OnActorAddonChanged(this); }
set { scale = value; }
}
[XmlIgnore] public bool Render
{
get { return render == true; }
set { render = value; EventsManager.OnActorAddonChanged(this); }
set { render = value; }
}
// Simple curves

View file

@ -23,19 +23,19 @@ namespace RimWorldAnimationStudio
[XmlIgnore] public float PosX
{
get { return posX.HasValue ? posX.Value : 0f; }
set { posX = value; EventsManager.OnAddonKeyframeChanged(this); }
set { posX = value; }
}
[XmlIgnore] public float PosZ
{
get { return posZ.HasValue ? posZ.Value : 0f; }
set { posZ = value; EventsManager.OnAddonKeyframeChanged(this); }
set { posZ = value; }
}
[XmlIgnore] public float Rotation
{
get { return rotation.HasValue ? rotation.Value : 0f; }
set { rotation = value; EventsManager.OnAddonKeyframeChanged(this); }
set { rotation = value; }
}
// Constructors

View file

@ -28,37 +28,37 @@ namespace RimWorldAnimationStudio
[XmlIgnore] public string DefName
{
get { return defName != null && defName != "" ? defName : "newAnimation"; }
set { defName = value; EventsManager.OnAnimationDefChanged(); }
set { defName = value; }
}
[XmlIgnore] public string Label
{
get { return label != null && label != "" ? label : "newAnimation"; }
set { label = value; EventsManager.OnAnimationDefChanged(); }
set { label = value; }
}
[XmlIgnore] public List<string> SexTypes
{
get { return sexTypes.NullOrEmpty() ? sexTypes = new List<string>() : sexTypes; }
set { sexTypes = value.NotNullOrEmpty() ? value : null; EventsManager.OnAnimationDefChanged(); }
set { sexTypes = value.NotNullOrEmpty() ? value : null; }
}
[XmlIgnore] public List<string> InteractionDefTypes
{
get { return interactionDefTypes.NullOrEmpty() ? interactionDefTypes = new List<string>() : interactionDefTypes; }
set { interactionDefTypes = value.NotNullOrEmpty() ? value : null; EventsManager.OnAnimationDefChanged(); }
set { interactionDefTypes = value.NotNullOrEmpty() ? value : null; }
}
[XmlIgnore] public List<Actor> Actors
{
get { return actors.NullOrEmpty() ? actors = new List<Actor>() : actors; }
set { actors = value.NotNullOrEmpty() ? value : null; EventsManager.OnAnimationDefChanged(); }
set { actors = value.NotNullOrEmpty() ? value : null; }
}
[XmlIgnore] public List<AnimationStage> AnimationStages
{
get { if (animationStages.NullOrEmpty()){ animationStages = new List<AnimationStage>(); } return animationStages; }
set { animationStages = value.NotNullOrEmpty() ? value : null; EventsManager.OnAnimationDefChanged(); }
set { animationStages = value.NotNullOrEmpty() ? value : null; }
}
// Local data
@ -83,12 +83,13 @@ namespace RimWorldAnimationStudio
Actor actor = new Actor();
Actors.Add(actor);
foreach (AnimationStage stage in Workspace.animationDef.AnimationStages)
{ stage.AddAnimationClip(Workspace.animationDef.Actors.Count - 1); }
Initialize();
Workspace.ActorID = Workspace.animationDef.Actors.Count - 1;
foreach (AnimationStage stage in Workspace.animationDef.AnimationStages)
{ stage.AddAnimationClip(Workspace.ActorID); }
EventsManager.OnActorCountChanged();
EventsManager.OnActorCountChanged();
Workspace.RecordEvent("Actor addition");
}
@ -119,7 +120,9 @@ namespace RimWorldAnimationStudio
{ stage.AddAnimationClip(actor.GetActorID()); }
Initialize();
Workspace.StageID = Workspace.animationDef.AnimationStages.Count - 1;
EventsManager.OnStageCountChanged();
Workspace.RecordEvent("Stage addition");
}
@ -127,9 +130,11 @@ namespace RimWorldAnimationStudio
{
AnimationStage stage = Workspace.GetCurrentAnimationStage().Copy();
stage.StageName += " (Clone)";
stage.Initialize();
Workspace.animationDef.AnimationStages.Insert(Workspace.StageID + 1, stage);
Initialize();
EventsManager.OnStageCountChanged();
Workspace.RecordEvent("Stage clone");
}
@ -154,8 +159,9 @@ namespace RimWorldAnimationStudio
}
AnimationStages.RemoveAt(Workspace.StageID);
Workspace.StageID--;
EventsManager.OnStageCountChanged();
Workspace.RecordEvent("Stage deletion");
}

View file

@ -10,11 +10,11 @@ namespace RimWorldAnimationStudio
public class AnimationStage
{
// Data to/from animationDef
[SerializeField] private string stageName;
[SerializeField] private int? playTimeTicks;
[SerializeField] private int? playTimeTicksQuick;
[SerializeField] private bool? isLooping;
[SerializeField, XmlArray("animationClips"), XmlArrayItem("li")] public List<PawnAnimationClip> animationClips;
public string stageName;
public int? playTimeTicks;
public int? playTimeTicksQuick;
public bool? isLooping;
[XmlArray("animationClips"), XmlArrayItem("li")] public List<PawnAnimationClip> animationClips;
// Data serialization control
public bool ShouldSerializeanimationClips() { return animationClips.NotNullOrEmpty(); }
@ -22,32 +22,44 @@ namespace RimWorldAnimationStudio
// Data helper functions
[XmlIgnore] public string StageName
{
get { return stageName != null && stageName != "" ? stageName : "NewStage"; }
set { stageName = value; EventsManager.OnAnimationStageChanged(this); }
get { return string.IsNullOrEmpty(stageName) ? stageName = "NewStage" : stageName; }
set { stageName = value; }
}
[XmlIgnore] public int PlayTimeTicks
{
get { return playTimeTicks.HasValue ? playTimeTicks.Value : 0; }
set { playTimeTicks = value; EventsManager.OnAnimationStageChanged(this); }
set { playTimeTicks = value; }
}
[XmlIgnore] public int PlayTimeTicksQuick
{
get { return playTimeTicksQuick.HasValue ? playTimeTicksQuick.Value : 0; }
set { playTimeTicksQuick = value; EventsManager.OnAnimationStageChanged(this); }
set { playTimeTicksQuick = value; }
}
[XmlIgnore] public bool IsLooping
{
get { return isLooping == true; }
set { isLooping = value; EventsManager.OnAnimationStageChanged(this); }
set { isLooping = value; }
}
[XmlIgnore] public List<PawnAnimationClip> AnimationClips
{
get { return animationClips.NullOrEmpty() ? animationClips = new List<PawnAnimationClip>() : animationClips; }
set { animationClips = value.NotNullOrEmpty() ? value : null; EventsManager.OnAnimationStageChanged(this); }
set { animationClips = value.NotNullOrEmpty() ? value : null; }
}
[XmlIgnore] public int StageLoopsNormal
{
get { return Mathf.CeilToInt(PlayTimeTicks / Workspace.StageWindowSize); }
set { value = Math.Max(1, value); PlayTimeTicks = value * Workspace.StageWindowSize; IsLooping = value > 1; }
}
[XmlIgnore] public int StageLoopsQuick
{
get { return Mathf.CeilToInt(PlayTimeTicksQuick / Workspace.StageWindowSize); }
set { value = Math.Max(0, Math.Min(value, StageLoopsNormal)); PlayTimeTicksQuick = value * Workspace.StageWindowSize; IsLooping = value > 1; }
}
// Local data
@ -63,8 +75,6 @@ namespace RimWorldAnimationStudio
if (clip.duration > PlayTimeTicks)
{ PlayTimeTicks = clip.duration; }
}
PlayTimeTicksQuick = PlayTimeTicks;
}
public int GetStageID()
@ -78,7 +88,7 @@ namespace RimWorldAnimationStudio
{
float scale = (float)newStageWindowSize / Workspace.StageWindowSize;
foreach (PawnAnimationClip clip in Workspace.animationDef.AnimationStages[Workspace.StageID].AnimationClips)
foreach (PawnAnimationClip clip in AnimationClips)
{
foreach (PawnKeyframe keyframe in clip.Keyframes)
{
@ -93,8 +103,8 @@ namespace RimWorldAnimationStudio
public void ResizeStageWindow(int newStageWindowSize)
{
Workspace.GetCurrentAnimationStage().stageWindowSize = newStageWindowSize;
Workspace.GetCurrentAnimationStage().PlayTimeTicks = newStageWindowSize * Workspace.stageLoopsNormal;
Workspace.GetCurrentAnimationStage().PlayTimeTicksQuick = newStageWindowSize * Workspace.stageLoopsQuick;
Workspace.GetCurrentAnimationStage().PlayTimeTicks = newStageWindowSize * StageLoopsNormal;
Workspace.GetCurrentAnimationStage().PlayTimeTicksQuick = newStageWindowSize * StageLoopsQuick;
}
public void AddAnimationClip(int actorID = -1)
@ -134,7 +144,7 @@ namespace RimWorldAnimationStudio
clip.Keyframes.Add(keyframeB);
}
clip.BuildSimpleCurves();
animationClips.Add(clip);
}
// Pre-save / post-load

View file

@ -31,20 +31,20 @@ namespace RimWorldAnimationStudio
[XmlIgnore] public List<ActorAddon> Addons
{
get { return addons.NullOrEmpty() ? addons = new List<ActorAddon>() : addons; }
set { addons = value.NotNullOrEmpty() ? value : null; EventsManager.OnPawnAnimationClipChanged(this); }
set { addons = value.NotNullOrEmpty() ? value : null; }
}
[XmlIgnore] public List<PawnKeyframe> Keyframes
{
get { return keyframes.NullOrEmpty() ? keyframes = new List<PawnKeyframe>() : keyframes; }
set { keyframes = value.NotNullOrEmpty() ? value : null; EventsManager.OnPawnAnimationClipChanged(this); }
set { keyframes = value.NotNullOrEmpty() ? value : null; }
}
[XmlIgnore]
public List<string> Tags
{
get { return tags.NullOrEmpty() ? tags = new List<string>() : tags; }
set { tags = value.NotNullOrEmpty() ? value : null; EventsManager.OnPawnAnimationClipChanged(this); }
set { tags = value.NotNullOrEmpty() ? value : null; }
}
// Local data
@ -235,7 +235,7 @@ namespace RimWorldAnimationStudio
foreach (PawnKeyframe keyframe in keyframesToClone)
{
PawnAnimationClip clip = Workspace.GetAnimationClipThatOwnsKeyframe(keyframe.keyframeID, out int clipID);
PawnAnimationClip clip = Workspace.GetAnimationClipThatOwnsKeyframe(keyframe.keyframeID);
if (clip == null)
{ Debug.LogWarning("Cannot clone pawn keyframe - no clip owns this keyframe"); continue; }
@ -244,7 +244,7 @@ namespace RimWorldAnimationStudio
{ Debug.LogWarning("Cannot clone pawn keyframe - a keyframe already exists at this tick"); return; }
PawnKeyframe cloneFrame = keyframe.Copy();
cloneFrame.GenerateKeyframeID(clipID);
cloneFrame.GenerateKeyframeID(clip.GetOwningActorID());
cloneFrame.atTick = Workspace.StageTick;
PawnKeyframe nextKeyframe = clip.Keyframes.FirstOrDefault(x => x.atTick > Workspace.StageTick);
@ -301,8 +301,8 @@ namespace RimWorldAnimationStudio
if (Workspace.DoesPawnKeyframeExistAtTick(Workspace.StageID, targetActorID, tickToPasteAt))
{
PawnKeyframe oldKeyframe = Workspace.animationDef.AnimationStages[Workspace.StageID].AnimationClips[targetActorID].Keyframes.First(x => x.atTick == tickToPasteAt);
RemovePawnKeyframe(targetActorID, oldKeyframe.keyframeID, true);
PawnKeyframe oldKeyframe = Workspace.GetPawnAnimationClip(targetActorID).Keyframes.First(x => x.atTick == tickToPasteAt);
Workspace.GetAnimationClipThatOwnsKeyframe(oldKeyframe.keyframeID).RemovePawnKeyframe(oldKeyframe.keyframeID, true);
}
PawnKeyframe clonedKeyframe = copiedKeyframe.Copy();
@ -330,34 +330,28 @@ namespace RimWorldAnimationStudio
Workspace.RecordEvent("Keyframe pasted");
}
public void RemovePawnKeyframe()
public void RemovePawnKeyframe(int keyframeID, bool force = false)
{
foreach (int keyframeID in Workspace.keyframeID)
{
if (Workspace.GetAnimationClipThatOwnsKeyframe(keyframeID, out int clipID) != null)
{ RemovePawnKeyframe(clipID, keyframeID); }
}
}
public void RemovePawnKeyframe(int actorID, int keyframeID, bool force = false)
{
PawnKeyframe keyframe = Workspace.GetPawnKeyframe(actorID, keyframeID);
PawnAnimationClip clip = Workspace.animationDef.AnimationStages[Workspace.StageID].AnimationClips[actorID];
if (keyframe == null || clip == null) return;
PawnKeyframe keyframe = Workspace.GetPawnKeyframe(keyframeID);
if (keyframe == null || IsOwnerOfKeyframe(keyframeID) == false) return;
if (keyframe.atTick == Constants.minTick && force == false)
{ Debug.LogWarning("Cannot delete key frame - the first key frame of an animation clip cannot be deleted"); return; }
if (clip.Keyframes.Count <= 2 && force == false)
if (Keyframes.Count <= 2 && force == false)
{ Debug.LogWarning("Cannot delete key frame - an animation clip must have two or more keyframes"); return; }
clip.Keyframes.Remove(keyframe);
clip.BuildSimpleCurves();
Keyframes.Remove(keyframe);
BuildSimpleCurves();
Workspace.RecordEvent("Keyframe deletion");
}
public bool IsOwnerOfKeyframe(int keyframeID)
{
return Keyframes.Any(x => x.keyframeID == keyframeID);
}
public float GetStageTickPercentage()
{
return (float)(Workspace.StageTick % duration) / duration;

View file

@ -40,79 +40,79 @@ namespace RimWorldAnimationStudio
[XmlIgnore] public float BodyAngle
{
get { return bodyAngle.HasValue ? bodyAngle.Value : 0f; }
set { bodyAngle = value; EventsManager.OnPawnKeyframeChanged(this); }
set { bodyAngle = value; }
}
[XmlIgnore] public float HeadAngle
{
get { return headAngle.HasValue ? headAngle.Value : (float)(headAngle = 0f); }
set { headAngle = value; EventsManager.OnPawnKeyframeChanged(this); }
set { headAngle = value; }
}
[XmlIgnore] public float HeadBob
{
get { return headBob.HasValue ? headBob.Value : (float)(headBob = 0f); }
set { headBob = value; EventsManager.OnPawnKeyframeChanged(this); }
set { headBob = value; }
}
[XmlIgnore] public float BodyOffsetX
{
get { return bodyOffsetX.HasValue ? bodyOffsetX.Value : (float)(bodyOffsetX = 0f); }
set { bodyOffsetX = value; EventsManager.OnPawnKeyframeChanged(this); }
set { bodyOffsetX = value; }
}
[XmlIgnore] public float BodyOffsetZ
{
get { return bodyOffsetZ.HasValue ? bodyOffsetZ.Value : (float)(bodyOffsetZ = 0f); }
set { bodyOffsetZ = value; EventsManager.OnPawnKeyframeChanged(this); }
set { bodyOffsetZ = value; }
}
[XmlIgnore] public int HeadFacing
{
get { return headFacing.HasValue ? headFacing.Value : (int)(headFacing = 2); }
set { headFacing = value; EventsManager.OnPawnKeyframeChanged(this); }
set { headFacing = value; }
}
[XmlIgnore] public int BodyFacing
{
get { return bodyFacing.HasValue ? bodyFacing.Value : (int)(bodyFacing = 2); }
set { bodyFacing = value; EventsManager.OnPawnKeyframeChanged(this); }
set { bodyFacing = value; }
}
[XmlIgnore] public float GenitalAngle
{
get { return genitalAngle.HasValue ? genitalAngle.Value : (float)(genitalAngle = 0f); }
set { genitalAngle = value; EventsManager.OnPawnKeyframeChanged(this); }
set { genitalAngle = value; }
}
[XmlIgnore] public bool Quiver
{
get { return quiver == true; }
set { quiver = value; EventsManager.OnPawnKeyframeChanged(this); }
set { quiver = value; }
}
[XmlIgnore] public int TickDuration
{
get { return tickDuration.HasValue ? tickDuration.Value : (int)(tickDuration = 0); }
set { tickDuration = value; EventsManager.OnPawnKeyframeChanged(this); }
set { tickDuration = value; }
}
[XmlIgnore] public string SoundEffect
{
get { return soundEffect; }
set { soundEffect = value; EventsManager.OnPawnKeyframeChanged(this); }
set { soundEffect = value; }
}
[XmlIgnore] public List<string> Tags
{
get { return tags.NullOrEmpty() ? tags = new List<string>() : tags; }
set { tags = value.NotNullOrEmpty() ? value : null; EventsManager.OnPawnKeyframeChanged(this); }
set { tags = value.NotNullOrEmpty() ? value : null; }
}
[XmlIgnore] public List<AddonKeyframe> AddonKeyframes
{
get { return addonKeyframes.NullOrEmpty() ? addonKeyframes = new List<AddonKeyframe>() : addonKeyframes; }
set { addonKeyframes = value.NotNullOrEmpty()? value : null; EventsManager.OnPawnKeyframeChanged(this); }
set { addonKeyframes = value.NotNullOrEmpty()? value : null; }
}
// Local data
@ -148,6 +148,63 @@ namespace RimWorldAnimationStudio
return AddonKeyframes.FirstOrDefault(x => x.AddonName == addonName);
}
public void AdjustActor(Vector2 deltaOffset)
{
float deltaAngle = -deltaOffset.x * 33.3333f + deltaOffset.y * 33.3333f;
int facing = deltaOffset.x < 0 ? 3 : deltaOffset.y < 0 ? 2 : deltaOffset.x > 0 ? 1 : 0;
switch (Workspace.actorManipulationMode)
{
case ActorManipulationMode.Pan: MoveActor(deltaOffset); break;
case ActorManipulationMode.Rotate: RotateActor(deltaAngle); break;
case ActorManipulationMode.Face: FaceActor(facing); break;
}
}
public void MoveActor(Vector2 deltaOffset)
{
if (Workspace.selectedBodyPart == null)
{
BodyOffsetX += deltaOffset.x;
BodyOffsetZ += deltaOffset.y;
}
else if (Workspace.selectedBodyPart.bodyPart.ToLower() == "head")
{ HeadBob += deltaOffset.y; }
Workspace.GetCurrentPawnAnimationClip().BuildSimpleCurves();
Workspace.RecordEvent("Actor position / orientation");
}
public void RotateActor(float deltaAngle)
{
if (Workspace.selectedBodyPart == null)
{ BodyAngle += deltaAngle; }
else if (Workspace.selectedBodyPart.bodyPart.ToLower() == "head")
{ HeadAngle += deltaAngle; }
else if (Workspace.selectedBodyPart.bodyPart.ToLower() == "appendage")
{ GenitalAngle -= deltaAngle; }
Workspace.GetCurrentPawnAnimationClip().BuildSimpleCurves();
Workspace.RecordEvent("Actor position / orientation");
}
public void FaceActor(int facing)
{
PawnKeyframe keyframe = Workspace.GetCurrentPawnKeyframe(true);
if (Workspace.selectedBodyPart == null)
{ keyframe.BodyFacing = facing; }
else if (Workspace.selectedBodyPart.bodyPart.ToLower() == "head")
{ keyframe.HeadFacing = facing; }
Workspace.GetCurrentPawnAnimationClip().BuildSimpleCurves();
Workspace.RecordEvent("Actor position / orientation");
}
// Pre-save / post-load
public void OnPreSave()
{
@ -157,7 +214,7 @@ namespace RimWorldAnimationStudio
foreach (AddonKeyframe addonKeyframe in AddonKeyframes)
{
ActorAddon addon = Workspace.GetAnimationClipThatOwnsKeyframe(keyframeID, out int clipID).GetActorAddon(addonKeyframe.AddonName);
ActorAddon addon = Workspace.GetAnimationClipThatOwnsKeyframe(keyframeID).GetActorAddon(addonKeyframe.AddonName);
if (addon.Render)
{ addonKeyframes.Add(addonKeyframe.Copy()); }

View file

@ -0,0 +1,44 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
namespace RimWorldAnimationStudio
{
public class ActorPosition
{
public float bodyOffsetX;
public float bodyOffsetZ;
public float bodyAngle;
public float headBob;
public float headAngle;
public float genitalAngle;
public int bodyFacing;
public int headFacing;
public ActorPosition(int actorID, int atTick)
{
Actor actor = Workspace.GetActor(actorID);
PawnAnimationClip clip = Workspace.GetPawnAnimationClip(actorID);
float clipPercent = atTick / Workspace.StageWindowSize;
if (atTick > Constants.minTick && atTick == clip.duration) clipPercent = 1f;
if (Workspace.GetCurrentAnimationStage().IsLooping == false)
{ clipPercent = (float)atTick / clip.duration; }
bodyOffsetX = clip.BodyOffsetX.Evaluate(clipPercent);
bodyOffsetZ = clip.BodyOffsetZ.Evaluate(clipPercent);
bodyAngle = clip.BodyAngle.Evaluate(clipPercent);
headBob = clip.HeadBob.Evaluate(clipPercent);
headAngle = clip.HeadAngle.Evaluate(clipPercent);
genitalAngle = clip.GenitalAngle.Evaluate(clipPercent);
bodyFacing = (int)clip.BodyFacing.Evaluate(clipPercent);
headFacing = (int)clip.HeadFacing.Evaluate(clipPercent);
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e2a9b0bb71978ea49909b3e1814303a5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -24,6 +24,7 @@ namespace RimWorldAnimationStudio
// Colors used
public static Color ColorWhite = new Color(1f, 1f, 1f);
public static Color ColorGreen = new Color(0f, 1f, 0f);
public static Color ColorLightGreen = new Color(0.75f, 1f, 0.75f);
public static Color ColorGoldYellow = new Color(1f, 0.85f, 0f);
public static Color ColorDarkGold = new Color(0.75f, 0.64f, 0f);
public static Color ColorLightGrey = new Color(0.9f, 0.9f, 0.9f);

View file

@ -9,34 +9,40 @@ namespace RimWorldAnimationStudio
public class ActorBody : MonoBehaviour, IPointerClickHandler, IDragHandler, IEndDragHandler
{
public int actorID;
public bool isSelected = false;
public SpriteRenderer bodyRenderer;
public SpriteRenderer headRenderer;
public SpriteRenderer appendageRenderer;
private Vector3 delta = new Vector3();
private Vector3 dragDelta = new Vector3();
public bool actorBodyPartSelected { get { return GetComponentsInChildren<ActorBodyPart>().Any(x => x.isSelected); } }
public void Initialize(int actorID)
private void Start()
{
this.actorID = actorID;
EventsManager.onActorBodyPartSelected.AddListener(delegate(ActorBodyPart bodyPart) { OnActorBodyPartSelected(bodyPart); });
EventsManager.onActorBodySelected.AddListener(delegate(ActorBody actorBody) { OnActorBodySelected(actorBody); });
}
public void Update()
public void OnActorBodySelected(ActorBody actorBody)
{
if (Workspace.ActorID == actorID && Workspace.selectedBodyPart == null)
if (actorBody == this)
{ bodyRenderer.color = Constants.ColorGreen; }
else
{ bodyRenderer.color = Constants.ColorWhite; }
}
foreach (ActorAddon addon in Workspace.GetCurrentAnimationStage().AnimationClips[actorID].Addons)
{
ActorBodyPart bodyPart = GetComponentsInChildren<ActorBodyPart>(true).FirstOrDefault(x => x.addonName == addon.AddonName);
bodyPart?.gameObject?.SetActive(addon.Render);
}
public void OnActorBodyPartSelected(ActorBodyPart bodyPart)
{
if (bodyPart.parent == this)
{ bodyRenderer.color = Constants.ColorLightGreen; }
else
{ bodyRenderer.color = Constants.ColorWhite; }
}
public void Initialize(int actorID)
{
this.actorID = actorID;
if (actorID == Workspace.ActorID)
{ Activate(); }
}
public void OnPointerClick(PointerEventData eventData)
@ -52,19 +58,15 @@ namespace RimWorldAnimationStudio
Activate();
PawnKeyframe keyframe = Workspace.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 (dragDelta == Vector3.zero)
{ dragDelta = mousePosition - transform.position; }
if (Workspace.actorManipulationMode == ActorManipulationMode.Pan)
{
keyframe.BodyOffsetX = mousePosition.x - delta.x - Workspace.animationDef.Actors[actorID].GetFinalTransformOffset().x;
keyframe.BodyOffsetZ = mousePosition.y - delta.y - Workspace.animationDef.Actors[actorID].GetFinalTransformOffset().y;
keyframe.BodyOffsetX = mousePosition.x - dragDelta.x - Workspace.GetActor(actorID).GetFinalTransformOffset().x;
keyframe.BodyOffsetZ = mousePosition.y - dragDelta.y - Workspace.GetActor(actorID).GetFinalTransformOffset().y;
}
else if (Workspace.actorManipulationMode == ActorManipulationMode.Rotate)
@ -84,18 +86,27 @@ namespace RimWorldAnimationStudio
PawnAnimationClip clip = Workspace.GetPawnAnimationClip(actorID);
clip.BuildSimpleCurves();
EventsManager.OnPawnKeyframeChanged(keyframe);
}
public void OnEndDrag(PointerEventData eventData)
{
Workspace.RecordEvent("Actor position / orientation");
delta = Vector3.zero;
dragDelta = Vector3.zero;
}
public ActorBodyPart GetBodyPart(string bodyPart)
{
return GetComponentsInChildren<ActorBodyPart>(true)?.FirstOrDefault(x => x.bodyPart.ToLower() == bodyPart);
}
public void Activate()
{
Workspace.ActorID = actorID;
Workspace.selectedBodyPart = null;
EventsManager.OnActorBodySelected(this);
}
}
}

View file

@ -10,22 +10,39 @@ namespace RimWorldAnimationStudio
{
public SpriteRenderer bodyPartRenderer;
public ActorBody parent;
public bool isHead = false;
public string addonName;
public bool isSelected = false;
public string bodyPart;
private Vector3 delta = new Vector3();
private Vector3 dragDelta = new Vector3();
public void Start()
{
//Workspace.onActorChanged.AddListener(delegate { });
EventsManager.onActorBodyPartSelected.AddListener(delegate (ActorBodyPart bodyPart) { OnActorBodyPartSelected(bodyPart); });
EventsManager.onActorBodySelected.AddListener(delegate (ActorBody actorBody) { OnActorBodySelected(actorBody); });
}
public void Update()
public void OnActorAddonChange(ActorAddon actorAddon)
{
if ((Workspace.ActorID == parent.actorID && Workspace.selectedBodyPart == null) || Workspace.selectedBodyPart == this)
if (actorAddon.AddonName == bodyPart)
{ gameObject?.SetActive(actorAddon.Render); }
}
public void OnActorBodySelected(ActorBody actorBody)
{
if (actorBody == parent)
{ bodyPartRenderer.color = Constants.ColorLightGreen; }
else
{ bodyPartRenderer.color = Constants.ColorWhite; }
}
public void OnActorBodyPartSelected(ActorBodyPart bodyPart)
{
if (bodyPart == this)
{ bodyPartRenderer.color = Constants.ColorGreen; }
else if (bodyPart.parent == parent)
{ bodyPartRenderer.color = Constants.ColorLightGreen; }
else
{ bodyPartRenderer.color = Constants.ColorWhite; }
}
@ -43,71 +60,18 @@ namespace RimWorldAnimationStudio
Activate();
PawnKeyframe keyframe = Workspace.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 (dragDelta == Vector3.zero)
{ dragDelta = mousePosition - transform.position; }
if (addonName != null && addonName != "")
{
AddonKeyframe addonKeyframe = keyframe.GetAddonKeyframe(addonName);
ActorAddon addon = Workspace.GetCurrentPawnAnimationClip().GetActorAddon(addonName);
if (Workspace.actorManipulationMode == ActorManipulationMode.Pan)
{
Vector3 anchor;
ActorBody anchoringActorBody = AnimationController.Instance.actorBodies.GetComponentsInChildren<ActorBody>()?.FirstOrDefault(x => x.actorID == addon.AnchoringActor);
Vector3 bodyPos = new Vector3(anchoringActorBody.transform.position.x, anchoringActorBody.transform.position.y, 0);
PawnRaceDef pawnRaceDef = Workspace.animationDef.Actors[addon.AnchoringActor].GetPawnRaceDef();
Actor anchoringActor = Workspace.animationDef.Actors[addon.AnchoringActor];
int bodyFacing = (int)Workspace.GetCurrentAnimationStage().AnimationClips[addon.AnchoringActor].BodyFacing.Evaluate((float)Workspace.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<ActorAddonCard>()?.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 (bodyPart.ToLower() == "head")
{
if (Workspace.actorManipulationMode == ActorManipulationMode.Pan)
{
// It's stupid but it works
// It's stupid, but it works
Vector3 localPosA = transform.localPosition;
transform.position = mousePosition - delta;
transform.position = mousePosition - dragDelta;
Vector3 localPosB = transform.localPosition;
transform.localPosition = localPosA;
@ -130,31 +94,55 @@ namespace RimWorldAnimationStudio
}
}
else
else if (bodyPart.ToLower() == "appendage")
{
if (Workspace.actorManipulationMode == ActorManipulationMode.Rotate)
{
float angle = -Vector2.SignedAngle(Vector2.up, (Vector2)mousePosition - (Vector2)transform.position);
keyframe.GenitalAngle = angle;
}
}
Workspace.GetCurrentActor().ControlGenitalAngle = Workspace.animationDef.AnimationStages.Any(x => x.AnimationClips[Workspace.ActorID].Keyframes.Any(y => y.GenitalAngle != 0));
else
{
AddonKeyframe addonKeyframe = keyframe.GetAddonKeyframe(bodyPart);
ActorAddon addon = Workspace.GetCurrentPawnAnimationClip().GetActorAddon(bodyPart);
if (Workspace.actorManipulationMode == ActorManipulationMode.Pan)
{
ActorBody anchoringActorBody = AnimationController.Instance.actorBodies.GetComponentsInChildren<ActorBody>()?.FirstOrDefault(x => x.actorID == addon.AnchoringActor);
Vector3 anchor = PawnUtility.GetBodyPartAnchor(anchoringActorBody, addon.addonName);
transform.position = new Vector3(mousePosition.x, mousePosition.y, 0f);
addonKeyframe.PosX = transform.position.x - anchor.x;
addonKeyframe.PosZ = transform.position.y - anchor.y;
}
else if (Workspace.actorManipulationMode == ActorManipulationMode.Rotate)
{
float angle = -Vector2.SignedAngle(Vector2.down, (Vector2)mousePosition - (Vector2)transform.position);
addonKeyframe.Rotation = angle;
}
}
PawnAnimationClip clip = Workspace.GetPawnAnimationClip(parent.actorID);
clip.BuildSimpleCurves();
EventsManager.OnPawnKeyframeChanged(keyframe);
}
public void OnEndDrag(PointerEventData eventData)
{
Workspace.RecordEvent("Actor position / orientation");
delta = Vector3.zero;
dragDelta = Vector3.zero;
}
public void Activate()
{
Workspace.ActorID = parent.actorID;
Workspace.selectedBodyPart = this;
EventsManager.OnActorBodyPartSelected(this);
}
}
}

View file

@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.UI;
namespace RimWorldAnimationStudio
{
public class AnimationLengthDisplay : MonoBehaviour
{
public Text stageLengthNormalText;
public Text animationLengthNormalText;
public Text stageLengthQuickText;
public Text animationLengthQuickText;
public void Start()
{
}
public void UpdateGUI()
{
stageLengthNormalText.text = "Stage length (normal): " + Workspace.GetCurrentAnimationStage().PlayTimeTicks + " (" + Workspace.GetCurrentAnimationStage().PlayTimeTicks / 60f + " s)";
animationLengthNormalText.text = "Animation length (normal): " + Workspace.animationDef.animationTimeTicks + " (" + Workspace.animationDef.animationTimeTicks / 60f + " s)";
stageLengthQuickText.text = "Stage length (quickie): " + Workspace.GetCurrentAnimationStage().PlayTimeTicksQuick + " (" + Workspace.GetCurrentAnimationStage().PlayTimeTicksQuick / 60f + " s)";
animationLengthQuickText.text = "Animation length (quickie): " + Workspace.animationDef.animationTimeTicksQuick + " (" + Workspace.animationDef.animationTimeTicksQuick / 60f + " s)";
LayoutRebuilder.ForceRebuildLayoutImmediate(stageLengthQuickText.GetComponent<RectTransform>());
LayoutRebuilder.ForceRebuildLayoutImmediate(animationLengthQuickText.GetComponent<RectTransform>());
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 060e49b40b1097e46b662059e4e29cdf
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -75,7 +75,7 @@ namespace RimWorldAnimationStudio
public void InitiateUpdateOfGhostFrames()
{
if (AnimationController.Instance.IsTimelineDirty()) return;
//if (AnimationController.Instance.IsTimelineDirty()) return;
BroadcastMessage("UpdateGhostFrames");
}
@ -86,7 +86,7 @@ namespace RimWorldAnimationStudio
int? siblingCount = anchorTransform.parent.GetComponentsInChildren<AnimationTimeline>()?.ToList()?.Count();
if (siblingIndex != null && siblingCount != null && MoveAnimationTimeline(siblingIndex.Value, delta))
{ AnimationController.Instance.InitializeAnimationTimeline(); }
{ AnimationController.Instance.Initialize(); }
}
public bool MoveAnimationTimeline(int startIndex, int delta)

View file

@ -8,7 +8,7 @@ using UnityEngine.UI;
namespace RimWorldAnimationStudio
{
public class ActorAddonCard : MonoBehaviour
public class ActorAddonKeyframeCard : MonoBehaviour
{
public string addonName;
public InputField xOffsetField;
@ -17,30 +17,33 @@ namespace RimWorldAnimationStudio
public void Start()
{
xOffsetField.onEndEdit.AddListener(delegate { OnFieldValueChanged(); });
zOffsetField.onEndEdit.AddListener(delegate { OnFieldValueChanged(); });
rotationField.onEndEdit.AddListener(delegate { OnFieldValueChanged(); });
EventsManager.onAnimationChanged.AddListener(delegate { UpdateGUI(); });
EventsManager.onStageIDChanged.AddListener(delegate { UpdateGUI(); });
EventsManager.onActorIDChanged.AddListener(delegate { UpdateGUI(); });
EventsManager.onStageTickChanged.AddListener(delegate { Debug.Log("stagetick"); UpdateGUI(); });
AnimationController.Instance.animationClipTimeField.onValueChanged.AddListener(delegate { OnKeyframeValueChanged(); });
xOffsetField.onEndEdit.AddListener(delegate { OnValueChanged(); });
zOffsetField.onEndEdit.AddListener(delegate { OnValueChanged(); });
rotationField.onEndEdit.AddListener(delegate { OnValueChanged(); });
UpdateGUI();
}
public void OnFieldValueChanged()
public void OnValueChanged()
{
if (Workspace.animationDef == null) return;
PawnAnimationClip clip = Workspace.GetCurrentPawnAnimationClip();
PawnKeyframe keyframe = Workspace.GetCurrentPawnKeyframe(true);
keyframe.GetAddonKeyframe(addonName).PosX = float.Parse(xOffsetField.text);
keyframe.GetAddonKeyframe(addonName).PosZ = float.Parse(zOffsetField.text);
keyframe.GetAddonKeyframe(addonName).Rotation = float.Parse(rotationField.text);
clip.BuildSimpleCurves();
Workspace.GetCurrentPawnAnimationClip().BuildSimpleCurves();
Workspace.RecordEvent("Actor addon position / orientation");
}
public void OnKeyframeValueChanged()
public void UpdateGUI()
{
if (Workspace.animationDef == null) return;
PawnAnimationClip clip = Workspace.GetCurrentPawnAnimationClip();
xOffsetField.SetTextWithoutNotify(clip.GetActorAddon(addonName).PosX.Evaluate((float)Workspace.StageTick / Workspace.StageWindowSize).ToString());

View file

@ -28,7 +28,7 @@ namespace RimWorldAnimationStudio
public void Start()
{
// General events
EventsManager.onAnimationDefChanged.AddListener(delegate { UpdateGUI(); });
EventsManager.onAnimationChanged.AddListener(delegate { UpdateGUI(); });
EventsManager.onActorIDChanged.AddListener(delegate { UpdateGUI(); });
EventsManager.onDefNamesChanged.AddListener(delegate { UpdateRaceDropdown(); });
@ -69,6 +69,8 @@ namespace RimWorldAnimationStudio
actor.SetPawnRaceOffset(new Vector2(x, z));
Workspace.RecordEvent("Actor offset");
UpdateGUI();
}
public void OnDropdownChanged()
@ -107,8 +109,8 @@ namespace RimWorldAnimationStudio
string bodyType = actor.bodyType;
bodyTypeDropdown.SetValueWithoutNotify(bodyTypeDropdown.options.FindIndex(x => x.text == bodyType));
bodyOffsetXField.SetTextWithoutNotify(string.Format("{0:0.000}", actor.BodyTypeOffset.GetOffset(bodyType).x.ToString()));
bodyOffsetZField.SetTextWithoutNotify(string.Format("{0:0.000}", actor.BodyTypeOffset.GetOffset(bodyType).z.ToString()));
bodyOffsetXField.SetTextWithoutNotify(string.Format("{0:0.000}", actor.BodyTypeOffset.GetOffset(bodyType).x));
bodyOffsetZField.SetTextWithoutNotify(string.Format("{0:0.000}", actor.BodyTypeOffset.GetOffset(bodyType).z));
bodyTypeDropdown.interactable = actor.GetPawnRaceDef().isHumanoid;
bodyOffsetXField.interactable = actor.GetPawnRaceDef().isHumanoid;
@ -117,8 +119,8 @@ namespace RimWorldAnimationStudio
string race = actor.GetPawnRaceDef().defName;
raceDropdown.SetValueWithoutNotify(raceDropdown.options.FindIndex(x => x.text == race));
raceOffsetXField.SetTextWithoutNotify(string.Format("{0:0.000}", actor.GetPawnRaceOffset().x.ToString()));
raceOffsetZField.SetTextWithoutNotify(string.Format("{0:0.000}", actor.GetPawnRaceOffset().z.ToString()));
raceOffsetXField.SetTextWithoutNotify(string.Format("{0:0.000}", actor.GetPawnRaceOffset().x));
raceOffsetZField.SetTextWithoutNotify(string.Format("{0:0.000}", actor.GetPawnRaceOffset().z));
}
}
}

View file

@ -15,17 +15,25 @@ namespace RimWorldAnimationStudio
public InputField headRotationField;
public InputField appendageRotationField;
public void Update()
{
if (Workspace.animationDef == null)
{ return; }
private Actor actor { get { return Workspace.GetCurrentActor(); } }
positionXField.interactable = AnimationController.Instance.isAnimating == false;
positionZField.interactable = AnimationController.Instance.isAnimating == false;
rotationField.interactable = AnimationController.Instance.isAnimating == false;
headBobField.interactable = AnimationController.Instance.isAnimating == false;
headRotationField.interactable = AnimationController.Instance.isAnimating == false;
appendageRotationField.interactable = AnimationController.Instance.isAnimating == false;
private void Start()
{
EventsManager.onAnimationChanged.AddListener(delegate { UpdateGUI(); });
EventsManager.onStageIDChanged.AddListener(delegate { UpdateGUI(); });
EventsManager.onActorIDChanged.AddListener(delegate { UpdateGUI(); });
EventsManager.onStageTickChanged.AddListener(delegate { UpdateGUI(); });
EventsManager.onKeyframeCountChanged.AddListener(delegate { UpdateGUI(); });
EventsManager.onPawnKeyframeChanged.AddListener(delegate { UpdateGUI(); });
positionXField.onEndEdit.AddListener(delegate { OnValueChanged(); });
positionZField.onEndEdit.AddListener(delegate { OnValueChanged(); });
rotationField.onEndEdit.AddListener(delegate { OnValueChanged(); });
headBobField.onEndEdit.AddListener(delegate { OnValueChanged(); });
headRotationField.onEndEdit.AddListener(delegate { OnValueChanged(); });
appendageRotationField.onEndEdit.AddListener(delegate { OnValueChanged(); });
UpdateGUI();
}
public void OnValueChanged()
@ -39,70 +47,21 @@ namespace RimWorldAnimationStudio
keyframe.HeadAngle = float.Parse(headRotationField.text);
keyframe.GenitalAngle = float.Parse(appendageRotationField.text);
Workspace.animationDef.Actors[Workspace.ActorID].ControlGenitalAngle = keyframe.GenitalAngle != 0;
Workspace.GetPawnAnimationClip(Workspace.ActorID).BuildSimpleCurves();
Workspace.RecordEvent("Actor position / orientation");
}
public void AdjustActor(Vector2 deltaOffset)
{
float deltaAngle = -deltaOffset.x * 33.3333f + deltaOffset.y * 33.3333f;
int facing = deltaOffset.x < 0 ? 3 : deltaOffset.y < 0 ? 2 : deltaOffset.x > 0 ? 1 : 0;
switch (Workspace.actorManipulationMode)
{
case ActorManipulationMode.Pan: MoveActor(deltaOffset); break;
case ActorManipulationMode.Rotate: RotateActor(deltaAngle); break;
case ActorManipulationMode.Face: FaceActor(facing); break;
}
}
public void MoveActor(Vector2 deltaOffset)
{
PawnKeyframe keyframe = Workspace.GetCurrentPawnKeyframe(true);
if (Workspace.selectedBodyPart == null)
{
keyframe.BodyOffsetX += deltaOffset.x;
keyframe.BodyOffsetZ += deltaOffset.y;
}
else if (Workspace.selectedBodyPart.isHead)
{ keyframe.HeadBob += deltaOffset.y; }
Workspace.GetCurrentPawnAnimationClip().BuildSimpleCurves();
Workspace.RecordEvent("Actor position / orientation");
}
public void RotateActor(float deltaAngle)
public void UpdateGUI()
{
PawnKeyframe keyframe = Workspace.GetCurrentPawnKeyframe(true);
ActorPosition actorPosition = actor.GetCurrentPosition();
if (Workspace.selectedBodyPart == null)
{ keyframe.BodyAngle += deltaAngle; }
else if (Workspace.selectedBodyPart.isHead)
{ keyframe.HeadAngle += deltaAngle; }
else
{ keyframe.GenitalAngle -= deltaAngle; }
Workspace.GetCurrentPawnAnimationClip().BuildSimpleCurves();
Workspace.RecordEvent("Actor position / orientation");
}
public void FaceActor(int facing)
{
PawnKeyframe keyframe = Workspace.GetCurrentPawnKeyframe(true);
if (Workspace.selectedBodyPart == null)
{ keyframe.BodyFacing = facing; }
else if (Workspace.selectedBodyPart.isHead)
{ keyframe.HeadFacing = facing; }
Workspace.GetCurrentPawnAnimationClip().BuildSimpleCurves();
Workspace.RecordEvent("Actor position / orientation");
positionXField.SetTextWithoutNotify(string.Format("{0:0.000}", actorPosition.bodyOffsetX));
positionZField.SetTextWithoutNotify(string.Format("{0:0.000}", actorPosition.bodyOffsetZ));
rotationField.SetTextWithoutNotify(string.Format("{0:0.000}", actorPosition.bodyAngle));
headBobField.SetTextWithoutNotify(string.Format("{0:0.000}", actorPosition.headBob));
headRotationField.SetTextWithoutNotify(string.Format("{0:0.000}", actorPosition.headAngle));
appendageRotationField.SetTextWithoutNotify(string.Format("{0:0.000}", actorPosition.genitalAngle));
}
}
}

View file

@ -0,0 +1,103 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.UI;
namespace RimWorldAnimationStudio
{
public class AnimationControlCard : MonoBehaviour
{
public Dropdown stageLoopDropdown;
public InputField animationClipTimeField;
public InputField animationClipLengthField;
public Toggle stretchKeyframesToggle;
public InputField playBackSpeedField;
public Button playToggleButton;
public Slider stageTimelineSlider;
private void Start()
{
EventsManager.onStageTickChanged.AddListener(delegate
{
animationClipTimeField.SetTextWithoutNotify(Workspace.StageTick.ToString());
stageTimelineSlider.SetValueWithoutNotify(Workspace.StageTick);
});
EventsManager.onAnimationToggled.AddListener(delegate
{
playToggleButton.image.color = Workspace.isAnimating ? Constants.ColorGoldYellow : Constants.ColorWhite;
});
animationClipLengthField.text = Workspace.StageWindowSize.ToString();
stageTimelineSlider.maxValue = Workspace.StageWindowSize;
}
public void ToggleAnimation(bool forceOff = false)
{
Workspace.isAnimating = !Workspace.isAnimating;
if (forceOff) Workspace.isAnimating = false;
}
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
{
foreach (PawnAnimationClip clip in Workspace.GetCurrentAnimationStage().AnimationClips)
{
List<PawnKeyframe> keyframes = clip.Keyframes.Where(x => x.atTick > newStageWindowSize)?.ToList();
if (keyframes.NullOrEmpty())
{ continue; }
foreach (PawnKeyframe keyframe in keyframes)
{
if (clip.Keyframes.Count <= 2)
{ break; }
clip.RemovePawnKeyframe(keyframe.keyframeID);
}
}
}
Workspace.GetCurrentAnimationStage().ResizeStageWindow(newStageWindowSize);
Workspace.RecordEvent("Stage length");
}
public void OnPlayBackSpeedChange()
{
Workspace.PlayBackSpeed = float.Parse(playBackSpeedField.text);
playBackSpeedField.SetTextWithoutNotify(Workspace.PlayBackSpeed.ToString());
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6b414452bfd6c9b4bb99542a51d77468
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -15,7 +15,7 @@ namespace RimWorldAnimationStudio
public void Start()
{
EventsManager.onAnimationDefChanged.AddListener(delegate { UpdateInputFields(); });
EventsManager.onAnimationChanged.AddListener(delegate { UpdateInputFields(); });
defNameField.onEndEdit.AddListener(delegate {
Workspace.animationDef.DefName = defNameField.text;

View file

@ -12,6 +12,30 @@ namespace RimWorldAnimationStudio
public InputField stageNameField;
public Image banner;
private int stageID { get { return transform.GetSiblingIndex(); } }
public void Start()
{
EventsManager.onStageIDChanged.AddListener(delegate { Initialize(stageName.text); });
stageNameField.onEndEdit.AddListener(delegate { OnNameChange(); });
}
public void Initialize(string stageName)
{
this.stageName.text = stageName;
if (Workspace.StageID == transform.GetSiblingIndex())
{
banner.gameObject.SetActive(true);
}
else
{
banner.gameObject.SetActive(false);
stageNameField.gameObject.SetActive(false);
}
}
public void OnNameChange()
{
stageName.text = stageNameField.text;
@ -23,27 +47,7 @@ namespace RimWorldAnimationStudio
public void OnMoveStage(int delta)
{
int siblingCount = transform.parent.childCount;
int index = Mathf.Clamp(transform.GetSiblingIndex() + delta, 0, siblingCount - 1);
transform.SetSiblingIndex(index);
}
public void Initialize(string stageName)
{
this.stageName.text = stageName;
}
public void Update()
{
if (Workspace.StageID == transform.GetSiblingIndex())
{ banner.gameObject.SetActive(true); }
else
{
banner.gameObject.SetActive(false);
stageNameField.gameObject.SetActive(false);
}
Workspace.animationDef.MoveAnimationStage(stageID, delta);
}
public void OnPointerClick(PointerEventData eventData)

View file

@ -0,0 +1,58 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.UI;
namespace RimWorldAnimationStudio
{
public class StageLoopsCard : MonoBehaviour
{
public InputField stageLoopsNormalField;
public InputField stageLoopsQuickField;
public void Start()
{
EventsManager.onAnimationChanged.AddListener(delegate { UpdateInputFields(); });
EventsManager.onStageIDChanged.AddListener(delegate { UpdateInputFields(); });
EventsManager.onAnimationStageChanged.AddListener(delegate { UpdateInputFields(); });
stageLoopsNormalField.onEndEdit.AddListener(delegate { OnStageLoopsNormalFieldChange(); });
stageLoopsQuickField.onEndEdit.AddListener(delegate { OnStageLoopsFastFieldChange(); });
UpdateInputFields();
}
public void OnStageLoopsNormalFieldChange()
{
if (Workspace.animationDef == null) return;
Workspace.GetCurrentAnimationStage().StageLoopsNormal = int.Parse(stageLoopsNormalField.text);
EventsManager.OnAnimationStageChanged(Workspace.GetCurrentAnimationStage());
Workspace.RecordEvent("Cycle count (normal)");
UpdateInputFields();
}
public void OnStageLoopsFastFieldChange()
{
if (Workspace.animationDef == null) return;
Workspace.GetCurrentAnimationStage().StageLoopsQuick = int.Parse(stageLoopsQuickField.text);
EventsManager.OnAnimationStageChanged(Workspace.GetCurrentAnimationStage());
Workspace.RecordEvent("Cycle count (fast)");
UpdateInputFields();
}
public void UpdateInputFields()
{
stageLoopsNormalField.SetTextWithoutNotify(Workspace.GetCurrentAnimationStage().StageLoopsNormal.ToString());
stageLoopsQuickField.SetTextWithoutNotify(Workspace.GetCurrentAnimationStage().StageLoopsQuick.ToString());
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 38691dc973d99734f8f0f2a240df73fe
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -35,12 +35,12 @@ namespace RimWorldAnimationStudio
{
this.timeline = timeline;
this.clip = Workspace.GetPawnAnimationClip(actorID);
this.keyframe = Workspace.GetPawnKeyframe(actorID, keyframeID);
this.keyframe = Workspace.GetPawnKeyframe(keyframeID);
this.actorID = actorID;
this.keyframeID = keyframeID;
PawnKeyframe keyframe = Workspace.GetPawnKeyframe(actorID, keyframeID);
PawnKeyframe keyframe = Workspace.GetPawnKeyframe(keyframeID);
maxValue = Workspace.StageWindowSize;
value = keyframe.atTick.Value;
@ -132,7 +132,7 @@ namespace RimWorldAnimationStudio
if (unlinkedSlider != null)
{
if (AnimationController.Instance.stretchKeyframesToggle.isOn && unlinkedSlider.keyframe.atTick == pivotKeyframe.atTick) continue;
if (Workspace.stretchKeyframes && unlinkedSlider.keyframe.atTick == pivotKeyframe.atTick) continue;
unlinkedSlider.linkedSlider = this;
unlinkedSlider.linkedOffset = unlinkedSlider.keyframe.atTick.Value - keyframe.atTick.Value;
@ -176,7 +176,7 @@ namespace RimWorldAnimationStudio
foreach (PawnKeyframe _keyframe in keyframesToCheck)
{
if (_keyframe != keyframe)
{ Workspace.GetCurrentPawnAnimationClip().RemovePawnKeyframe(actorID, _keyframe.keyframeID); }
{ Workspace.GetAnimationClipThatOwnsKeyframe(_keyframe.keyframeID).RemovePawnKeyframe(_keyframe.keyframeID); }
}
}
@ -196,7 +196,7 @@ namespace RimWorldAnimationStudio
foreach (PawnKeyframe _keyframe in keyframesToCheck)
{
if (_keyframe.keyframeID != linkedKeyframe.keyframeID)
{ Workspace.GetCurrentPawnAnimationClip().RemovePawnKeyframe(actorID, _keyframe.keyframeID); Debug.Log("delete"); }
{ Workspace.GetAnimationClipThatOwnsKeyframe(_keyframe.keyframeID).RemovePawnKeyframe(_keyframe.keyframeID); }
}
}
}
@ -219,10 +219,10 @@ namespace RimWorldAnimationStudio
if (Workspace.keyframeID.NullOrEmpty() || Workspace.keyframeID.Contains(keyframeID) == false)
{ linkedSlider = null; }
else if (AnimationController.Instance.stretchKeyframesToggle.isOn && linkedSlider != null)
else if (Workspace.stretchKeyframes && linkedSlider != null)
{ value = Mathf.CeilToInt(linkedSlider.keyframe.atTick.Value + linkedOffset * linkedSlider.ScaledOffsetFromPivot()); }
else if (AnimationController.Instance.stretchKeyframesToggle.isOn == false && linkedSlider != null)
else if (Workspace.stretchKeyframes == false && linkedSlider != null)
{ value = Mathf.Clamp(linkedSlider.keyframe.atTick.Value + linkedOffset, Constants.minTick + 1, Workspace.StageWindowSize); }
else if (keyframe.atTick.Value != value)
@ -242,7 +242,7 @@ namespace RimWorldAnimationStudio
{ handleImage.color = Constants.ColorGrey; }
// Show sound symbol
string soundDef = Workspace.GetPawnKeyframe(actorID, keyframeID)?.SoundEffect;
string soundDef = Workspace.GetPawnKeyframe(keyframeID)?.SoundEffect;
soundIcon.SetActive(soundDef != null && soundDef != "" && soundDef != "None");
}

View file

@ -16,21 +16,10 @@ namespace RimWorldAnimationStudio
private List<int> divisions = new List<int>();
private float minDiff = -1f;
private RectTransform rect;
private int lastStageWindowSize = -1;
public void Start()
{
rect = GetComponent<RectTransform>();
}
public void Update()
{
if (lastStageWindowSize != Workspace.StageWindowSize)
{
UpdateLinearScale();
lastStageWindowSize = Workspace.StageWindowSize;
}
EventsManager.onStageWindowSizeChanged.AddListener(delegate { UpdateLinearScale(); });
}
public void UpdateLinearScale()

View file

@ -0,0 +1,22 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
namespace RimWorldAnimationStudio
{
public class InactiveDuringAnimationPreview : MonoBehaviour
{
private InputField inputfield;
private void Start()
{
inputfield = GetComponent<InputField>();
}
private void Update()
{
inputfield.interactable = AnimationController.Instance.isAnimating == false;
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 92068b39ed172084296a595f5a09e54b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -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;
}
}
}

View file

@ -73,7 +73,7 @@ namespace RimWorldAnimationStudio
AnimationController.Instance.Reset();
Workspace.Reset();
EventsManager.OnAnimationDefChanged();
EventsManager.OnAnimationChanged();
Workspace.RecordEvent("AnimationDef loaded");
}

View file

@ -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();
}
}
}

View file

@ -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()

View file

@ -24,10 +24,10 @@ namespace RimWorldAnimationStudio
switch (rotation)
{
case 0: return new Vector3(0f, 0f, headOffset.y);
case 1: return new Vector3(headOffset.x, 0f, headOffset.y);
case 2: return new Vector3(0f, 0f, headOffset.y);
case 3: return new Vector3(-headOffset.x, 0f, headOffset.y);
case 0: return new Vector3(0f, headOffset.y, 0);
case 1: return new Vector3(headOffset.x, headOffset.y, 0);
case 2: return new Vector3(0f, headOffset.y, 0f);
case 3: return new Vector3(-headOffset.x, headOffset.y, 0f);
default: return Vector3.zero;
}
}
@ -161,5 +161,23 @@ namespace RimWorldAnimationStudio
}
}
}
public static Vector3 GetBodyPartAnchor(ActorBody anchoringActorBody, string anchorName)
{
Actor anchoringActor = Workspace.GetActor(anchoringActorBody.actorID);
Vector3 anchoringActorBodyPos = anchoringActorBody.transform.position;
Quaternion anchoringActorBodyQuad = Quaternion.AngleAxis(anchoringActorBody.transform.rotation.eulerAngles.z, Vector3.forward);
int anchoringActorFacing = anchoringActor.GetCurrentPosition().bodyFacing;
switch (anchorName)
{
case "torso": return anchoringActorBodyPos;
case "head": return anchoringActorBody.GetComponentsInChildren<ActorBodyPart>().FirstOrDefault(x => x.bodyPart.ToLower() == "head").transform.position;
case "groin": return anchoringActorBodyPos + anchoringActorBodyQuad * PawnUtility.GroinOffsetAt(anchoringActor.bodyType, anchoringActorFacing).FlipAxes();
case "left breast": return anchoringActorBodyPos + anchoringActorBodyQuad * PawnUtility.BreastLeftOffsetAt(anchoringActor.bodyType, anchoringActorFacing).FlipAxes();
case "right breast": return anchoringActorBodyPos + anchoringActorBodyQuad * PawnUtility.BreastRightOffsetAt(anchoringActor.bodyType, anchoringActorFacing).FlipAxes();
default: return new Vector3();
}
}
}
}

View file

@ -18,8 +18,12 @@ namespace RimWorldAnimationStudio
public class PawnKeyframeEvent : UnityEvent<PawnKeyframe> { }
public class ActorAddonEvent : UnityEvent<ActorAddon> { }
public class AddonKeyframeEvent : UnityEvent<AddonKeyframe> { }
public class ActorBodyEvent : UnityEvent<ActorBody> { }
public class ActorBodyPartEvent : UnityEvent<ActorBodyPart> { }
// Event list
public static UnityEvent onAnimationToggled = new UnityEvent();
public static UnityEvent onAnimationChanged = new UnityEvent();
public static UnityEvent onAnimationDefChanged = new UnityEvent();
public static WorkspaceIntEvent onActorIDChanged = new WorkspaceIntEvent();
public static WorkspaceIntEvent onStageIDChanged = new WorkspaceIntEvent();
@ -29,13 +33,18 @@ namespace RimWorldAnimationStudio
public static WorkspaceIntEvent onKeyframeCountChanged = new WorkspaceIntEvent();
public static ActorEvent onActorChanged = new ActorEvent();
public static AnimationStageEvent onAnimationStageChanged = new AnimationStageEvent();
public static AnimationStageEvent onStageWindowSizeChanged = new AnimationStageEvent();
public static PawnAnimationClipEvent onPawnAnimationClipChanged = new PawnAnimationClipEvent();
public static PawnKeyframeEvent onPawnKeyframeChanged = new PawnKeyframeEvent();
public static ActorAddonEvent onActorAddonChanged = new ActorAddonEvent();
public static AddonKeyframeEvent onAddonKeyframeChanged = new AddonKeyframeEvent();
public static UnityEvent onDefNamesChanged = new UnityEvent();
public static ActorBodyEvent onActorBodySelected = new ActorBodyEvent();
public static ActorBodyPartEvent onActorBodyPartSelected = new ActorBodyPartEvent();
// Event invoking
public static void OnAnimationToggled() { onAnimationToggled.Invoke(); }
public static void OnAnimationChanged() { onAnimationChanged.Invoke(); }
public static void OnAnimationDefChanged() { onAnimationDefChanged.Invoke(); }
public static void OnActorIDChanged() { onActorIDChanged.Invoke(Workspace.ActorID); }
public static void OnStageIDChanged() { onStageIDChanged.Invoke(Workspace.ActorID); }
@ -45,10 +54,13 @@ namespace RimWorldAnimationStudio
public static void OnKeyframeCountChanged(PawnAnimationClip clip) { onKeyframeCountChanged.Invoke(clip.Keyframes.Count); }
public static void OnActorChanged(Actor actor) { onActorChanged.Invoke(actor); }
public static void OnAnimationStageChanged(AnimationStage stage) { onAnimationStageChanged.Invoke(stage); }
public static void OnStageWindowSizeChanged(AnimationStage stage) { onStageWindowSizeChanged.Invoke(stage); }
public static void OnPawnAnimationClipChanged(PawnAnimationClip clip) { onPawnAnimationClipChanged.Invoke(clip); }
public static void OnPawnKeyframeChanged(PawnKeyframe keyframe) { onPawnKeyframeChanged.Invoke(keyframe); }
public static void OnActorAddonChanged(ActorAddon actorAddon) { onActorAddonChanged.Invoke(actorAddon); }
public static void OnAddonKeyframeChanged(AddonKeyframe addonKeyframe) { onAddonKeyframeChanged.Invoke(addonKeyframe); }
public static void OnDefNamesChanged() { onDefNamesChanged.Invoke(); }
public static void OnActorBodySelected(ActorBody actorBody) { onActorBodySelected.Invoke(actorBody); }
public static void OnActorBodyPartSelected(ActorBodyPart bodyPart) { onActorBodyPartSelected.Invoke(bodyPart); }
}
}

View file

@ -22,11 +22,7 @@ namespace RimWorldAnimationStudio
bool triggerEvent = stageID != value;
stageID = value;
if (triggerEvent)
{
StageTick = Constants.minTick;
EventsManager.OnStageIDChanged();
}
if (triggerEvent) { StageTick = Constants.minTick; EventsManager.OnStageIDChanged(); }
}
}
@ -78,12 +74,15 @@ namespace RimWorldAnimationStudio
// Current save path
public static string animationSavePath;
// Stage loop counts and stretching
public static int stageLoopsNormal = 1;
public static int stageLoopsQuick = 1;
// Stage controls
private static float playBackSpeed = 1f;
public static bool isAnimating;
public static bool stretchKeyframes;
// Stage controls set / get
public static float PlayBackSpeed { get { return playBackSpeed; } set { Mathf.Clamp(Workspace.playBackSpeed, 0.01f, 10f); } }
// Animation indices
private static int stageID = 0;
private static int actorID = 0;
@ -96,17 +95,17 @@ namespace RimWorldAnimationStudio
public static Actor GetCurrentActor()
{
return animationDef?.Actors[ActorID];
return GetActor(ActorID);
}
public static AnimationStage GetCurrentAnimationStage()
{
return animationDef?.AnimationStages[StageID];
return GetAnimationStage(StageID);
}
public static PawnAnimationClip GetCurrentPawnAnimationClip()
{
return animationDef?.AnimationStages[StageID]?.AnimationClips[ActorID];
return GetPawnAnimationClip(ActorID);
}
public static PawnKeyframe GetCurrentPawnKeyframe(bool makeKeyframe = false)
@ -122,28 +121,47 @@ namespace RimWorldAnimationStudio
public static Actor GetActor(int actorID)
{
return animationDef?.Actors[actorID];
return animationDef?.Actors.ElementAtOrDefault(actorID);
}
public static AnimationStage GetAnimationStage(int stageID)
{
return animationDef?.AnimationStages[stageID];
return animationDef?.AnimationStages.ElementAtOrDefault(stageID);
}
public static PawnAnimationClip GetPawnAnimationClip(int actorID)
{
return animationDef?.AnimationStages[StageID]?.AnimationClips[actorID];
return GetCurrentAnimationStage()?.AnimationClips.ElementAtOrDefault(actorID);
}
public static PawnKeyframe GetPawnKeyframe(int actorID, int keyframeID)
public static PawnKeyframe GetPawnKeyframe(int keyframeID)
{
if (StageID < 0) return null;
if (actorID < 0) return null;
foreach (AnimationStage stage in animationDef?.AnimationStages)
{
foreach (PawnAnimationClip clip in stage.animationClips)
{
PawnKeyframe keyframe = clip.Keyframes.FirstOrDefault(x => x.keyframeID == keyframeID);
if (StageID >= animationDef.AnimationStages.Count) return null;
if (actorID >= animationDef.AnimationStages[StageID].AnimationClips.Count) return null;
if (keyframe != null) return keyframe;
}
}
return animationDef.AnimationStages[StageID].AnimationClips[actorID].Keyframes.FirstOrDefault(x => x.keyframeID == keyframeID);
return null;
}
public static PawnAnimationClip GetAnimationClipThatOwnsKeyframe(int keyframeID)
{
foreach (AnimationStage stage in animationDef?.AnimationStages)
{
foreach (PawnAnimationClip clip in stage.animationClips)
{
PawnKeyframe keyframe = clip.Keyframes.FirstOrDefault(x => x.keyframeID == keyframeID);
if (keyframe != null) return clip;
}
}
return null;
}
public static List<PawnKeyframe> GetAllPawnKeyframesAtTick(int actorID, int atTick)
@ -167,24 +185,6 @@ namespace RimWorldAnimationStudio
return pawnKeyframes;
}
public static PawnAnimationClip GetAnimationClipThatOwnsKeyframe(int keyframeID, out int clipID)
{
clipID = -1;
for (int i = 0; i < animationDef.AnimationStages[StageID].AnimationClips.Count; i++)
{
PawnAnimationClip clip = animationDef.AnimationStages[StageID].AnimationClips[i];
if (clip.Keyframes.Any(x => x.keyframeID == keyframeID))
{
clipID = i;
return clip;
}
}
return null;
}
public static bool DoesPawnKeyframeExistAtTick(int stageID, int actorID, int atTick)
{
return animationDef.AnimationStages[stageID].AnimationClips[actorID].Keyframes.Any(x => x.atTick == atTick);
@ -195,11 +195,9 @@ namespace RimWorldAnimationStudio
PawnKeyframe pawnKeyframe = null;
PawnAnimationClip clip = GetPawnAnimationClip(actorID);
int stageTick = Workspace.StageTick;
foreach (PawnKeyframe keyframe in clip.Keyframes)
{
if (keyframe.atTick > stageTick)
if (keyframe.atTick > StageTick)
{ pawnKeyframe = keyframe; break; }
}
@ -211,11 +209,9 @@ namespace RimWorldAnimationStudio
PawnKeyframe pawnKeyframe = null;
PawnAnimationClip clip = GetPawnAnimationClip(actorID);
int stageTick = Workspace.StageTick;
foreach (PawnKeyframe keyframe in clip.Keyframes)
{
if (keyframe.atTick < stageTick)
if (keyframe.atTick < StageTick)
{ pawnKeyframe = keyframe; }
}
@ -227,11 +223,9 @@ namespace RimWorldAnimationStudio
PawnKeyframe pawnKeyframe = null;
PawnAnimationClip clip = GetPawnAnimationClip(actorID);
int stageTick = Workspace.StageTick;
foreach (PawnKeyframe keyframe in clip.Keyframes)
{
if (keyframe.atTick <= stageTick)
if (keyframe.atTick <= StageTick)
{ pawnKeyframe = keyframe; }
}
@ -310,7 +304,6 @@ namespace RimWorldAnimationStudio
animationDef = record.animationDef.Copy();
StageID = record.stageID;
AnimationController.Instance.MakeTimelineDirty();
StageCardManager.Instance.Initialize();
}
@ -327,7 +320,7 @@ namespace RimWorldAnimationStudio
RestoreToHistoricRecord(recordToRead);
Debug.Log("Undoing : " + recordToStore.eventDesc);
EventsManager.OnAnimationDefChanged();
EventsManager.OnAnimationChanged();
}
public static void Redo()
@ -342,7 +335,7 @@ namespace RimWorldAnimationStudio
RestoreToHistoricRecord(recordToReadAndStore);
Debug.Log("Redoing : " + recordToReadAndStore.eventDesc);
EventsManager.OnAnimationDefChanged();
EventsManager.OnAnimationChanged();
}
public static void ClearHistory()