Multi-drag and stretching for keyframes

This commit is contained in:
AbstractConcept 2022-10-14 00:52:07 -05:00
parent f449a9b4e2
commit ab5a2a4c02
151 changed files with 195 additions and 85 deletions

View File

@ -242,6 +242,8 @@ MonoBehaviour:
maxGhosts: 50 maxGhosts: 50
actorID: 0 actorID: 0
keyframeID: 0 keyframeID: 0
linkedSlider: {fileID: 0}
linkedOffset: 0
--- !u!1 &8359461402257861397 --- !u!1 &8359461402257861397
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0

View File

@ -8316,7 +8316,7 @@ MonoBehaviour:
actorCard: {fileID: 3804747680621674853} actorCard: {fileID: 3804747680621674853}
animationTimelines: {fileID: 1100016168} animationTimelines: {fileID: 1100016168}
actorBodies: {fileID: 1828035561} actorBodies: {fileID: 1828035561}
stretchkeyframesToggle: {fileID: 462332576} stretchKeyframesToggle: {fileID: 462332576}
playBackSpeedField: {fileID: 1579799916} playBackSpeedField: {fileID: 1579799916}
playToggleButton: {fileID: 79733375} playToggleButton: {fileID: 79733375}
actorBodyPrefab: {fileID: -4411442180840688308, guid: dc4c8b005322f3b46a2f122a55f38db2, actorBodyPrefab: {fileID: -4411442180840688308, guid: dc4c8b005322f3b46a2f122a55f38db2,
@ -17458,7 +17458,7 @@ MonoBehaviour:
m_TargetGraphic: {fileID: 922060210} m_TargetGraphic: {fileID: 922060210}
m_HandleRect: {fileID: 922060209} m_HandleRect: {fileID: 922060209}
m_Direction: 2 m_Direction: 2
m_Value: 1 m_Value: 0
m_Size: 1 m_Size: 1
m_NumberOfSteps: 0 m_NumberOfSteps: 0
m_OnValueChanged: m_OnValueChanged:

View File

@ -34,15 +34,14 @@ namespace RimWorldAnimationStudio
HeadBob.Clear(); HeadBob.Clear();
GenitalAngle.Clear(); GenitalAngle.Clear();
int keyframePosition = 0;
int duration = 0; int duration = 0;
keyframes[keyframes.Count - 1].tickDuration = 1;
foreach (PawnKeyframe frame in keyframes) foreach (PawnKeyframe frame in keyframes)
{ duration += frame.tickDuration; } { duration += frame.tickDuration; }
int keyframePosition = 0;
keyframes[keyframes.Count - 1].tickDuration = 1;
for (int i = 0; i < keyframes.Count; i++) for (int i = 0; i < keyframes.Count; i++)
{ {
PawnKeyframe keyframe = keyframes[i]; PawnKeyframe keyframe = keyframes[i];
@ -82,7 +81,7 @@ namespace RimWorldAnimationStudio
quiver.Add(keyframePosition + keyframe.tickDuration - 1, false); quiver.Add(keyframePosition + keyframe.tickDuration - 1, false);
} }
keyframe.atTick = keyframePosition + 1; keyframe.atTick = keyframePosition + Constants.minTick;
keyframePosition += keyframe.tickDuration; keyframePosition += keyframe.tickDuration;
} }
} }

View File

@ -3,6 +3,7 @@ using System.Linq;
using System.Xml; using System.Xml;
using System.Xml.Serialization; using System.Xml.Serialization;
using UnityEngine; using UnityEngine;
using UnityEngine.UI;
namespace RimWorldAnimationStudio namespace RimWorldAnimationStudio
{ {
@ -45,5 +46,10 @@ namespace RimWorldAnimationStudio
public bool HasValidKeyframeID() public bool HasValidKeyframeID()
{ return keyframeID >= 100000 && keyframeID < 1000000; } { return keyframeID >= 100000 && keyframeID < 1000000; }
public KeyframeSlider GetKeyframeSlider()
{
return Selectable.allSelectablesArray.FirstOrDefault(x => x.GetComponent<KeyframeSlider>()?.keyframeID == keyframeID)?.GetComponent< KeyframeSlider>();
}
} }
} }

View File

@ -23,9 +23,15 @@ namespace RimWorldAnimationStudio
private PawnAnimationClip clip; private PawnAnimationClip clip;
private PawnKeyframe keyframe; private PawnKeyframe keyframe;
private float dragTimeStart = -1f;
public void Initialize(AnimationTimeline timeline, int actorID, int keyframeID) private float dragTimeStart = -1f;
private int dragTickStart = -1;
public KeyframeSlider linkedSlider;
public Keyframe pivotKeyframe;
public int linkedOffset;
public void Initialize(AnimationTimeline timeline, int actorID, int keyframeID)
{ {
this.timeline = timeline; this.timeline = timeline;
this.clip = Workspace.Instance.GetPawnAnimationClip(actorID); this.clip = Workspace.Instance.GetPawnAnimationClip(actorID);
@ -48,8 +54,6 @@ namespace RimWorldAnimationStudio
keyframe.atTick = (int)value; keyframe.atTick = (int)value;
clip.BuildSimpleCurves(); clip.BuildSimpleCurves();
//AnimationController.Instance.stageTick = keyframe.atTick.Value;
timeline.InitiateUpdateOfGhostFrames(); timeline.InitiateUpdateOfGhostFrames();
} }
@ -99,52 +103,76 @@ namespace RimWorldAnimationStudio
if (Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.LeftCommand)) if (Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.LeftCommand))
{ Workspace.keyframeID.Add(keyframeID); } { Workspace.keyframeID.Add(keyframeID); }
else else if (Workspace.keyframeID.NullOrEmpty() || Workspace.keyframeID.Contains(keyframeID) == false)
{ Workspace.keyframeID = new List<int> { keyframeID }; } { Workspace.keyframeID = new List<int> { keyframeID }; }
if (eventData.clickCount >= 2) if (eventData.clickCount >= 2)
{ AnimationController.Instance.stageTick = keyframe.atTick.Value; } { AnimationController.Instance.stageTick = keyframe.atTick.Value; }
//Workspace.Instance.RecordEvent("Keyframe selected");
} }
public void OnBeginDrag(PointerEventData eventData) public void OnBeginDrag(PointerEventData eventData)
{ {
//AnimationController.Instance.stageTick = keyframe.atTick.Value;
Workspace.actorID = actorID; Workspace.actorID = actorID;
Workspace.keyframeID = new List<int> { keyframeID };
dragTimeStart = Time.unscaledTime; dragTimeStart = Time.unscaledTime;
dragTickStart = keyframe.atTick.Value;
if (Workspace.keyframeID.NullOrEmpty() || Workspace.keyframeID.Contains(keyframeID) == false)
{ Workspace.keyframeID = new List<int> { keyframeID }; }
List<PawnKeyframe> selectedKeyframes = Workspace.Instance.GetPawnKeyframes(Workspace.keyframeID).Except(new List<PawnKeyframe>() { keyframe })?.ToList();
// Link other slected keyframes to the movement of this one
if (selectedKeyframes.NotNullOrEmpty())
{
foreach (PawnKeyframe selectedKeyframe in selectedKeyframes)
{
KeyframeSlider unlinkedSlider = selectedKeyframe.GetKeyframeSlider();
if (unlinkedSlider != null)
{
unlinkedSlider.linkedSlider = this;
unlinkedSlider.linkedOffset = unlinkedSlider.keyframe.atTick.Value - keyframe.atTick.Value;
}
}
pivotKeyframe = keyframe.atTick < selectedKeyframes[0].atTick ? selectedKeyframes.Last() : selectedKeyframes.First();
}
} }
public override void OnDrag(PointerEventData eventData) public override void OnDrag(PointerEventData eventData)
{ {
if (keyframe.atTick == 1) Workspace.actorID = actorID;
{ value = 1; return; }
// The first keyframe can't be moved
if (keyframe.atTick == Constants.minTick)
{ value = Constants.minTick; return; }
// Sticky drag
if (Time.unscaledTime - dragTimeStart < 0.05f) return; if (Time.unscaledTime - dragTimeStart < 0.05f) return;
interactable = true; interactable = true;
base.OnDrag(eventData); base.OnDrag(eventData);
// Snap to nearest keyframe (on another timeline)
int targetTick = Workspace.FindClosestKeyFrameAtTick(keyframe.atTick.Value, Mathf.CeilToInt(Workspace.StageWindowSize * 0.01f), actorID); int targetTick = Workspace.FindClosestKeyFrameAtTick(keyframe.atTick.Value, Mathf.CeilToInt(Workspace.StageWindowSize * 0.01f), actorID);
if (Input.GetKey(KeyCode.LeftShift) && Workspace.Instance.DoesPawnKeyframeExistAtTick(Workspace.stageID, actorID, targetTick) == false) if (Input.GetKey(KeyCode.LeftShift) && Workspace.Instance.DoesPawnKeyframeExistAtTick(Workspace.stageID, actorID, targetTick) == false)
{ value = (float)targetTick; } { value = (float)targetTick; }
// Prevent frames from being moved to tick 1 // Prevent other frames from being moved to the first keyframe
if (value == 1) if (value == Constants.minTick)
{ value = 2; } { value = Constants.minTick + 1; }
//AnimationController.Instance.stageTick = keyframe.atTick.Value;
Workspace.actorID = actorID;
} }
public void OnEndDrag(PointerEventData eventData) public void OnEndDrag(PointerEventData eventData)
{ {
if (keyframe.atTick == 1) if (keyframe.atTick == Constants.minTick)
{ value = 1; return; } { value = Constants.minTick; return; }
foreach (Selectable otherSlider in Selectable.allSelectablesArray)
{
if (otherSlider is KeyframeSlider)
{ Debug.Log("unlinked keyframes"); (otherSlider as KeyframeSlider).linkedSlider = null; }
}
interactable = false; interactable = false;
Workspace.Instance.RecordEvent("Keyframe move"); Workspace.Instance.RecordEvent("Keyframe move");
@ -154,25 +182,60 @@ namespace RimWorldAnimationStudio
{ {
base.Update(); base.Update();
// Update outdated values
if (Workspace.keyframeID.NullOrEmpty() || Workspace.keyframeID.Contains(keyframeID) == false)
{ linkedSlider = null; }
else if (AnimationController.Instance.stretchKeyframesToggle.isOn && linkedSlider != null && linkedSlider.IsPivotKeyframe(keyframe) == false)
{
//int minTick = linkedSlider.pivotKeyframe.atTick.Value + GetIndexAmongstSelectedKeyframes();
//value = Mathf.Clamp(Mathf.CeilToInt(linkedSlider.keyframe.atTick.Value + linkedOffset * linkedSlider.ScaledOffsetFromPivot()), minTick, Workspace.StageWindowSize);
value = Mathf.CeilToInt(linkedSlider.keyframe.atTick.Value + linkedOffset * linkedSlider.ScaledOffsetFromPivot());
}
else if (AnimationController.Instance.stretchKeyframesToggle.isOn == false && linkedSlider != null)
{ value = Mathf.Clamp(linkedSlider.keyframe.atTick.Value + linkedOffset, Constants.minTick + 1, Workspace.StageWindowSize); }
else if (keyframe.atTick.Value != value)
{ value = keyframe.atTick.Value; }
// Update key color
if (keyframe.atTick.HasValue && Workspace.keyframeID.Contains(keyframeID) && AnimationController.Instance.stageTick == keyframe.atTick.Value) if (keyframe.atTick.HasValue && Workspace.keyframeID.Contains(keyframeID) && AnimationController.Instance.stageTick == keyframe.atTick.Value)
{ handleImage.color = Constants.ColorPurple; } { handleImage.color = Constants.ColorPurple; }
else if (Workspace.keyframeID.Contains(keyframeID)) else if (Workspace.keyframeID.Contains(keyframeID))
{ handleImage.color = Constants.ColorCyan; } { handleImage.color = Constants.ColorCyan; }
else if (keyframe.atTick.HasValue && AnimationController.Instance.stageTick == keyframe.atTick.Value) else if (AnimationController.Instance.stageTick == keyframe.atTick.Value)
{ handleImage.color = Constants.ColorPink; } { handleImage.color = Constants.ColorPink; }
else else
{ handleImage.color = Constants.ColorGrey; } { handleImage.color = Constants.ColorGrey; }
// Show sound symbol
string soundDef = Workspace.Instance.GetPawnKeyframe(actorID, keyframeID)?.soundEffect; string soundDef = Workspace.Instance.GetPawnKeyframe(actorID, keyframeID)?.soundEffect;
soundIcon.SetActive(soundDef != null && soundDef != "" && soundDef != "None");
}
if (soundDef != null && soundDef != "" && soundDef != "None") public float ScaledOffsetFromPivot()
{ soundIcon.SetActive(true); } {
//if (IsPivotKeyframe(keyframe)) return 1f;
if (dragTickStart == pivotKeyframe.atTick.Value) return 0f;
else return (float)(keyframe.atTick.Value - pivotKeyframe.atTick.Value) / (dragTickStart - pivotKeyframe.atTick.Value);
{ soundIcon.SetActive(false); } }
public bool IsPivotKeyframe(Keyframe otherKeyframe)
{
return pivotKeyframe == otherKeyframe;
}
public int GetIndexAmongstSelectedKeyframes()
{
List<PawnKeyframe> selectedKeyframes = Workspace.Instance.GetPawnKeyframes(Workspace.keyframeID).OrderBy(x => x.atTick)?.ToList();
if (selectedKeyframes.NullOrEmpty() || selectedKeyframes.Contains(keyframe) == false) return -1;
return selectedKeyframes.IndexOf(keyframe);
} }
} }
} }

View File

@ -64,7 +64,7 @@ namespace RimWorldAnimationStudio
if (Workspace.stageID != transform.GetSiblingIndex()) if (Workspace.stageID != transform.GetSiblingIndex())
{ {
AnimationController.Instance.stageTick = 1; AnimationController.Instance.stageTick = Constants.minTick;
Workspace.Instance.RecordEvent("Stage selected"); Workspace.Instance.RecordEvent("Stage selected");
} }

View File

@ -13,7 +13,7 @@ namespace RimWorldAnimationStudio
{ {
[Header("Animation settings")] [Header("Animation settings")]
public bool isAnimating = false; public bool isAnimating = false;
public int stageTick = 1; public int stageTick = Constants.minTick;
[Header("Object references")] [Header("Object references")]
public Slider stageTimelineSlider; public Slider stageTimelineSlider;
@ -25,7 +25,7 @@ namespace RimWorldAnimationStudio
public ActorCard actorCard; public ActorCard actorCard;
public Transform animationTimelines; public Transform animationTimelines;
public Transform actorBodies; public Transform actorBodies;
public Toggle stretchkeyframesToggle; public Toggle stretchKeyframesToggle;
public InputField playBackSpeedField; public InputField playBackSpeedField;
public Button playToggleButton; public Button playToggleButton;
@ -34,7 +34,7 @@ namespace RimWorldAnimationStudio
public GameObject animationTimelinePrefab; public GameObject animationTimelinePrefab;
// Private timing variables // Private timing variables
private int lastStageTick = 1; private int lastStageTick = Constants.minTick;
private float timeSinceLastUpdate = 0; private float timeSinceLastUpdate = 0;
private int cycleIndex = 0; private int cycleIndex = 0;
private bool isDirty = true; private bool isDirty = true;
@ -57,7 +57,7 @@ namespace RimWorldAnimationStudio
{ Initialize(); } { Initialize(); }
// Update tick if animating // Update tick if animating
stageTick = Mathf.Clamp(stageTick, 1, Workspace.StageWindowSize); stageTick = Mathf.Clamp(stageTick, Constants.minTick, Workspace.StageWindowSize);
if (isAnimating) if (isAnimating)
{ {
@ -72,12 +72,12 @@ namespace RimWorldAnimationStudio
if (stageTick > Workspace.StageWindowSize) if (stageTick > Workspace.StageWindowSize)
{ {
if (stageLoopDropdown.value == 1) if (stageLoopDropdown.value == 1)
{ stageTick = 1; } { stageTick = Constants.minTick; }
else if (stageLoopDropdown.value >= 2) else if (stageLoopDropdown.value >= 2)
{ {
++cycleIndex; ++cycleIndex;
stageTick = 1; stageTick = Constants.minTick;
if ((stageLoopDropdown.value == 2 && cycleIndex >= int.Parse(cyclesNormalField.text)) || if ((stageLoopDropdown.value == 2 && cycleIndex >= int.Parse(cyclesNormalField.text)) ||
(stageLoopDropdown.value == 3 && cycleIndex >= int.Parse(cyclesFastField.text))) (stageLoopDropdown.value == 3 && cycleIndex >= int.Parse(cyclesFastField.text)))
@ -148,7 +148,7 @@ namespace RimWorldAnimationStudio
bool requiresGenitals = actor.requiredGenitals.Any(x => x == "Penis") || Workspace.animationDef.actors[actorID].isFucking; bool requiresGenitals = actor.requiredGenitals.Any(x => x == "Penis") || Workspace.animationDef.actors[actorID].isFucking;
float clipPercent = (float)(stageTick % clip.duration) / clip.duration; float clipPercent = (float)(stageTick % clip.duration) / clip.duration;
if (stageTick == clip.duration) clipPercent = 1f; if (stageTick > Constants.minTick && stageTick == clip.duration) clipPercent = 1f;
if (Workspace.animationDef.animationStages[Workspace.stageID].isLooping == false) if (Workspace.animationDef.animationStages[Workspace.stageID].isLooping == false)
{ clipPercent = (float)stageTick / clip.duration; } { clipPercent = (float)stageTick / clip.duration; }
@ -401,7 +401,7 @@ namespace RimWorldAnimationStudio
if (tickToPasteAt < 1) continue; if (tickToPasteAt < 1) continue;
if (tickToPasteAt > Workspace.StageWindowSize) if (tickToPasteAt > Workspace.StageWindowSize)
{ {
if (stretchkeyframesToggle.isOn) if (stretchKeyframesToggle.isOn)
{ ResizeStageWindowSize(tickToPasteAt); } { ResizeStageWindowSize(tickToPasteAt); }
else continue; else continue;
@ -487,7 +487,7 @@ namespace RimWorldAnimationStudio
if (keyframe == null || clip == null) return; if (keyframe == null || clip == null) return;
if (keyframe.atTick == 1 && force == false) 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; } { 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 (clip.keyframes.Count <= 2 && force == false)
@ -527,7 +527,7 @@ namespace RimWorldAnimationStudio
if (Workspace.animationDef == null) return; if (Workspace.animationDef == null) return;
int.TryParse(animationClipTimeField.text, out int newStageTick); int.TryParse(animationClipTimeField.text, out int newStageTick);
stageTick = Mathf.Clamp(newStageTick, 1, Workspace.StageWindowSize); stageTick = Mathf.Clamp(newStageTick, Constants.minTick, Workspace.StageWindowSize);
stageTimelineSlider.value = stageTick; stageTimelineSlider.value = stageTick;
} }
@ -540,8 +540,11 @@ namespace RimWorldAnimationStudio
Debug.Log("Resizing animation clip length to " + newStageWindowSize.ToString() + " ticks."); Debug.Log("Resizing animation clip length to " + newStageWindowSize.ToString() + " ticks.");
if (stretchkeyframesToggle.isOn) if (stretchKeyframesToggle.isOn)
{ StretchKeyframes(newStageWindowSize); } {
List<PawnKeyframe> keyframes = Workspace.animationDef.animationStages[Workspace.stageID].animationClips.SelectMany(x => x.keyframes)?.ToList();
StretchKeyframes(keyframes, Workspace.StageWindowSize, newStageWindowSize);
}
else else
{ {
@ -566,7 +569,7 @@ namespace RimWorldAnimationStudio
ResizeStageWindowSize(newStageWindowSize); ResizeStageWindowSize(newStageWindowSize);
} }
public void StretchKeyframes(int newStageWindowSize) /*public void StretchKeyframes(int newStageWindowSize)
{ {
float scale = (float)newStageWindowSize / Workspace.StageWindowSize; float scale = (float)newStageWindowSize / Workspace.StageWindowSize;
@ -580,6 +583,39 @@ namespace RimWorldAnimationStudio
clip.BuildSimpleCurves(); clip.BuildSimpleCurves();
} }
}*/
public void StretchKeyframes(List<PawnKeyframe> keyframesToStretch, int v1, int v2)
{
int v0 = keyframesToStretch.Min(x => x.atTick.Value);
if (v1 == v0)
{ OffsetKeyframes(keyframesToStretch, v1, v2); return; }
float scaleFactor = (float)(v2 - v0) / (v1 - v0);
foreach (PawnKeyframe keyframe in keyframesToStretch)
{
keyframe.atTick = Mathf.RoundToInt(scaleFactor * (keyframe.atTick.Value - v0) + v0);
}
foreach(PawnAnimationClip clip in Workspace.animationDef.animationStages[Workspace.stageID].animationClips)
{ clip.BuildSimpleCurves(); }
}
public void OffsetKeyframes(List<PawnKeyframe> keyframesToOffset, int v1, int v2)
{
float offset = v2 - v1;
foreach (PawnKeyframe keyframe in keyframesToOffset)
{
keyframe.atTick = Mathf.RoundToInt(keyframe.atTick.Value + offset);
Debug.Log(keyframe.atTick);
Workspace.Instance.GetAnimationClipThatOwnsKeyframe(keyframe.keyframeID, out int clipID).BuildSimpleCurves();
}
foreach (PawnAnimationClip clip in Workspace.animationDef.animationStages[Workspace.stageID].animationClips)
{ clip.BuildSimpleCurves(); }
} }
public void ResizeStageWindowSize(int newStageWindowSize) public void ResizeStageWindowSize(int newStageWindowSize)

View File

@ -341,19 +341,19 @@ namespace RimWorldAnimationStudio
public void ToPreviousTick() public void ToPreviousTick()
{ {
if (Workspace.animationDef == null) return; if (Workspace.animationDef == null) return;
AnimationController.Instance.stageTick = Mathf.Clamp(AnimationController.Instance.stageTick - 1, 1, Workspace.StageWindowSize); AnimationController.Instance.stageTick = Mathf.Clamp(AnimationController.Instance.stageTick - 1, Constants.minTick, Workspace.StageWindowSize);
} }
public void ToNextTick() public void ToNextTick()
{ {
if (Workspace.animationDef == null) return; if (Workspace.animationDef == null) return;
AnimationController.Instance.stageTick = Mathf.Clamp(AnimationController.Instance.stageTick + 1, 1, Workspace.StageWindowSize); AnimationController.Instance.stageTick = Mathf.Clamp(AnimationController.Instance.stageTick + 1, Constants.minTick, Workspace.StageWindowSize);
} }
public void ToFirstTick() public void ToFirstTick()
{ {
if (Workspace.animationDef == null) return; if (Workspace.animationDef == null) return;
AnimationController.Instance.stageTick = 1; AnimationController.Instance.stageTick = Constants.minTick;
} }
public void ToLastTick() public void ToLastTick()

View File

@ -8,6 +8,7 @@ namespace RimWorldAnimationStudio
public static class Constants public static class Constants
{ {
public static int defaultAnimationClipLength = 600; public static int defaultAnimationClipLength = 600;
public static int minTick = 1;
public static int minAnimationClipLength = 2; public static int minAnimationClipLength = 2;
public static int maxAnimationClipLength = 9999; public static int maxAnimationClipLength = 9999;

View File

@ -37,6 +37,9 @@ namespace RimWorldAnimationStudio
if (animationDef.animationStages[stageID].stageWindowSize < 0) if (animationDef.animationStages[stageID].stageWindowSize < 0)
{ animationDef.animationStages[stageID].stageWindowSize = animationDef.animationStages[stageID].animationClips.Select(x => x.duration).Max(); } { animationDef.animationStages[stageID].stageWindowSize = animationDef.animationStages[stageID].animationClips.Select(x => x.duration).Max(); }
Debug.Log(animationDef.animationStages[stageID].stageWindowSize);
return animationDef.animationStages[stageID].stageWindowSize; return animationDef.animationStages[stageID].stageWindowSize;
} }
} }

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.

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