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

@ -75,6 +75,7 @@
<Compile Include="Assets\Scripts\AnimationComponents\PawnKeyframe.cs" />
<Compile Include="Assets\Scripts\AnimationComponents\PawnRaceDef.cs" />
<Compile Include="Assets\Scripts\AnimationComponents\PawnRaceOffset.cs" />
<Compile Include="Assets\Scripts\Data\ActorPosition.cs" />
<Compile Include="Assets\Scripts\Data\Constants.cs" />
<Compile Include="Assets\Scripts\Data\DefaultTags.cs" />
<Compile Include="Assets\Scripts\Data\Enums.cs" />
@ -87,12 +88,15 @@
<Compile Include="Assets\Scripts\GUI\Actors\ActorBody.cs" />
<Compile Include="Assets\Scripts\GUI\Actors\ActorBodyPart.cs" />
<Compile Include="Assets\Scripts\GUI\AddSoundDefButton.cs" />
<Compile Include="Assets\Scripts\GUI\AnimationLengthDisplay.cs" />
<Compile Include="Assets\Scripts\GUI\AnimationTimeline.cs" />
<Compile Include="Assets\Scripts\GUI\Cards\ActorAddonCard.cs" />
<Compile Include="Assets\Scripts\GUI\Cards\ActorAddonKeyframeCard.cs" />
<Compile Include="Assets\Scripts\GUI\Cards\ActorCard.cs" />
<Compile Include="Assets\Scripts\GUI\Cards\ActorKeyframeCard.cs" />
<Compile Include="Assets\Scripts\GUI\Cards\AnimationControlCard.cs" />
<Compile Include="Assets\Scripts\GUI\Cards\AnimationDefCard.cs" />
<Compile Include="Assets\Scripts\GUI\Cards\StageCard.cs" />
<Compile Include="Assets\Scripts\GUI\Cards\StageLoopsCard.cs" />
<Compile Include="Assets\Scripts\GUI\DialogBoxes\ConsoleMessagesDialog.cs" />
<Compile Include="Assets\Scripts\GUI\DialogBoxes\DialogBox.cs" />
<Compile Include="Assets\Scripts\GUI\DialogBoxes\RaceSettingsDialog.cs" />
@ -109,15 +113,16 @@
<Compile Include="Assets\Scripts\GUI\KeybindLabel.cs" />
<Compile Include="Assets\Scripts\GUI\KeyframeSlider.cs" />
<Compile Include="Assets\Scripts\GUI\LinearScale.cs" />
<Compile Include="Assets\Scripts\GUI\Props\SexProp.cs" />
<Compile Include="Assets\Scripts\GUI\Props\SexPropManager.cs" />
<Compile Include="Assets\Scripts\GUI\QuiverToggle.cs" />
<Compile Include="Assets\Scripts\GUI\SelectActorLayerButton.cs" />
<Compile Include="Assets\Scripts\GUI\SelfContained\ActorManipulator.cs" />
<Compile Include="Assets\Scripts\GUI\SelfContained\ButtonWithKeyCode.cs" />
<Compile Include="Assets\Scripts\GUI\SelfContained\Chaser.cs" />
<Compile Include="Assets\Scripts\GUI\SelfContained\InactiveDuringAnimationPreview.cs" />
<Compile Include="Assets\Scripts\GUI\SelfContained\RequiresAnimationDef.cs" />
<Compile Include="Assets\Scripts\GUI\SelfContained\SnapToKeyframe.cs" />
<Compile Include="Assets\Scripts\GUI\SexProps\SexProp.cs" />
<Compile Include="Assets\Scripts\GUI\SexProps\SexPropManager.cs" />
<Compile Include="Assets\Scripts\GUI\Tooltips\Tooltip.cs" />
<Compile Include="Assets\Scripts\GUI\Tooltips\TooltipMessage.cs" />
<Compile Include="Assets\Scripts\Graphics\MultiDirectionalGraphic.cs" />

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

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More