Solo Node & KeyFrames
diff --git a/Source/Actor.cpp b/Source/Actor.cpp
index 4d142ec..b609d21 100644
--- a/Source/Actor.cpp
+++ b/Source/Actor.cpp
@@ -3,6 +3,7 @@
 #include "ActorRootBone.hpp"
 #include "ActorIKTarget.hpp"
 #include "ActorEvent.hpp"
+#include "ActorNodeSolo.hpp"
 #include "CustomProperty.hpp"
 #include "ActorCollider.hpp"
 #include "BinaryReader.hpp"
@@ -174,7 +175,7 @@
 		throw UnsupportedVersionException("Unsupported file version", 0, 12);
 	}
 	// And of supported version...
-	if (version != 12)
+	if (version != 13)
 	{
 		throw UnsupportedVersionException("Unsupported file version", version, 12);
 	}
@@ -411,6 +412,9 @@
 			case BlockType::ColliderLine:
 				component = ActorColliderLine::read(this, componentBlock);
 				break;
+			case BlockType::ActorNodeSolo:
+				component = ActorNodeSolo::read(this, componentBlock);
+				break;
 			default:
 				// Not handled/expected block.
 				break;
diff --git a/Source/Actor.hpp b/Source/Actor.hpp
index 5a6906c..e5876c3 100644
--- a/Source/Actor.hpp
+++ b/Source/Actor.hpp
@@ -38,10 +38,11 @@
 		ColliderPolygon = 20, // TODO
 		ColliderLine = 21, // TODO
 		ActorImageSequence = 22, // TODO
-		ActorStaticMesh = 23,
+		ActorNodeSolo = 23,
 		NestedActorNode = 24,
 		NestedActorAssets = 25,
-		NestedActorAsset = 26
+		NestedActorAsset = 26,
+		ActorStaticMesh = 27
 	};
 
 	class Actor
diff --git a/Source/ActorComponent.hpp b/Source/ActorComponent.hpp
index 5a66b7a..8dafe7e 100644
--- a/Source/ActorComponent.hpp
+++ b/Source/ActorComponent.hpp
@@ -33,8 +33,9 @@
 		ColliderCircle = 19, // TODO
 		ColliderPolygon = 20, // TODO
 		ColliderLine = 21, // TODO
-		ActorStaticMesh = 23,
-		NestedActorNode = 24
+		ActorNodeSolo = 23,
+		NestedActorNode = 24,
+		ActorStaticMesh = 27
 	};
 
 
diff --git a/Source/ActorNode.cpp b/Source/ActorNode.cpp
index 5743576..19ccdcb 100644
--- a/Source/ActorNode.cpp
+++ b/Source/ActorNode.cpp
@@ -27,6 +27,8 @@
 		m_SuppressMarkDirty(false),
 		m_OverrideWorldTransform(false),
 		m_OverrideRotation(false),
+		m_IsCollapsedVisibility(false),
+		m_RenderCollapsed(false),
 		m_OverrideRotationValue(0.0f)
 {
 
@@ -197,6 +199,26 @@
 	return m_RenderOpacity;
 }
 
+bool ActorNode::collapsedVisibility() const
+{
+	return m_IsCollapsedVisibility;
+}
+
+void ActorNode::collapsedVisibility(bool v)
+{
+	if(m_IsCollapsedVisibility != v)
+	{
+		m_IsCollapsedVisibility = v;
+		markDirty();
+		markWorldDirty();
+	}
+}
+
+bool ActorNode::renderCollapsed() const
+{
+	return m_RenderCollapsed;
+}
+
 void ActorNode::markDirty()
 {
 	if(m_IsDirty)
@@ -325,6 +347,13 @@
 	if(m_Parent != nullptr)
 	{
 		m_Parent->updateTransforms();
+
+		bool isRenderCollapsed = (m_IsCollapsedVisibility || m_Parent->renderCollapsed());
+		if(m_RenderCollapsed != isRenderCollapsed)
+		{
+			m_RenderCollapsed = isRenderCollapsed;
+		}
+
 		m_RenderOpacity *= m_Parent->renderOpacity();
 		if(!m_OverrideWorldTransform)
 		{
@@ -402,6 +431,7 @@
 	node->m_Rotation = reader->readFloat();
 	reader->read(node->m_Scale);
 	node->m_Opacity = reader->readFloat();
+	node->m_IsCollapsedVisibility = (reader->readByte() == 1);
 
 	return node;
 }
\ No newline at end of file
diff --git a/Source/ActorNode.hpp b/Source/ActorNode.hpp
index 224b9d1..6bc4d92 100644
--- a/Source/ActorNode.hpp
+++ b/Source/ActorNode.hpp
@@ -31,6 +31,8 @@
 			bool m_SuppressMarkDirty;
 			bool m_OverrideWorldTransform;
 			bool m_OverrideRotation;
+			bool m_IsCollapsedVisibility;
+			bool m_RenderCollapsed;
 			float m_OverrideRotationValue;
 
 		protected:
@@ -63,6 +65,9 @@
 			float opacity() const;
 			void opacity(float v);
 			float renderOpacity() const;
+			bool collapsedVisibility() const;
+			void collapsedVisibility(bool v);
+			bool renderCollapsed() const;
 			void markDirty();
 			void markWorldDirty();
 			void addDependent(ActorNode* node);
diff --git a/Source/ActorNodeSolo.cpp b/Source/ActorNodeSolo.cpp
new file mode 100644
index 0000000..78f30fa
--- /dev/null
+++ b/Source/ActorNodeSolo.cpp
@@ -0,0 +1,58 @@
+#include "ActorNodeSolo.hpp"
+#include "BlockReader.hpp"
+
+using namespace nima;
+
+ActorNodeSolo::ActorNodeSolo() : 
+	ActorNode(ComponentType::ActorNodeSolo),
+	m_ActiveChildIndex(0)
+{
+
+}
+
+int ActorNodeSolo::activeChildIndex() const
+{
+	return m_ActiveChildIndex;
+}
+
+void ActorNodeSolo::activeChildIndex(int index)
+{
+	if(m_ActiveChildIndex != index)
+	{
+		m_ActiveChildIndex = index;
+		for(int i = 0; i < m_Children.size(); i++)
+		{
+			auto an = m_Children[i];
+			bool cv = (i != (m_ActiveChildIndex-1));
+			an->collapsedVisibility(cv);
+		}
+	}
+}
+
+ActorComponent* ActorNodeSolo::makeInstance(Actor* resetActor)
+{
+	ActorNodeSolo* soloInstance = new ActorNodeSolo();
+	soloInstance->copy(this, resetActor);
+
+	return soloInstance;
+}
+
+void ActorNodeSolo::copy(ActorNodeSolo* node, Actor* resetActor)
+{
+	Base::copy(node, resetActor);
+	m_ActiveChildIndex = node->m_ActiveChildIndex;
+}
+
+ActorNodeSolo* ActorNodeSolo::read(Actor* actor, BlockReader* reader, ActorNodeSolo* node)
+{
+	if(node == nullptr)
+	{
+		node = new ActorNodeSolo();
+	}
+
+	Base::read(actor, reader, node);
+
+	node->m_ActiveChildIndex = (int)reader->readFloat();
+
+	return node;
+}
\ No newline at end of file
diff --git a/Source/ActorNodeSolo.hpp b/Source/ActorNodeSolo.hpp
new file mode 100644
index 0000000..9365534
--- /dev/null
+++ b/Source/ActorNodeSolo.hpp
@@ -0,0 +1,28 @@
+#ifndef _NIMA_ACTORNODESOLO_HPP_
+#define _NIMA_ACTORNODESOLO_HPP_
+
+#include <string>
+#include "ActorNode.hpp"
+
+namespace nima
+{
+	class ActorNodeSolo : public ActorNode
+	{
+		typedef ActorNode Base;
+
+		private:
+			int m_ActiveChildIndex;
+
+		public:
+			ActorNodeSolo();
+			int activeChildIndex() const;
+			void activeChildIndex(int index);
+
+			ActorComponent* makeInstance(Actor* resetActor) override;
+			void copy(ActorNodeSolo* node, Actor* resetActor);
+
+			static ActorNodeSolo* read(Actor* actor, BlockReader* reader, ActorNodeSolo* node = NULL);
+	};
+}
+
+#endif
\ No newline at end of file
diff --git a/Source/Animation/KeyFrames/KeyFrameActiveChild.cpp b/Source/Animation/KeyFrames/KeyFrameActiveChild.cpp
new file mode 100644
index 0000000..8199fbd
--- /dev/null
+++ b/Source/Animation/KeyFrames/KeyFrameActiveChild.cpp
@@ -0,0 +1,33 @@
+#include "KeyFrameActiveChild.hpp"
+#include "../../BlockReader.hpp"
+#include "../../ActorNodeSolo.hpp"
+
+using namespace nima;
+
+bool KeyFrameActiveChild::read(BlockReader* reader, ActorComponent* component)
+{
+	if(!Base::read(reader, component))
+	{
+		return false;
+	}
+
+	m_Value = reader->readFloat();
+	return true;
+}
+
+void KeyFrameActiveChild::setNext(KeyFrame* frame)
+{
+	// Blank, no interpolation here
+}
+
+void KeyFrameActiveChild::apply(ActorComponent* component, float mix)
+{
+	// printf("APPLY KeyFrameActiveChild %d\n", m_Value);
+	ActorNodeSolo* node = reinterpret_cast<ActorNodeSolo*>(component);
+	node->activeChildIndex(m_Value);
+}
+
+void KeyFrameActiveChild::applyInterpolation(ActorComponent* component, float time, KeyFrame* toFrame, float mix)
+{
+	apply(component, mix);
+}
\ No newline at end of file
diff --git a/Source/Animation/KeyFrames/KeyFrameActiveChild.hpp b/Source/Animation/KeyFrames/KeyFrameActiveChild.hpp
new file mode 100644
index 0000000..a18f6c5
--- /dev/null
+++ b/Source/Animation/KeyFrames/KeyFrameActiveChild.hpp
@@ -0,0 +1,29 @@
+#ifndef _NIMA_KEYFRAMEACTIVECHILD_HPP_
+#define _NIMA_KEYFRAMEACTIVECHILD_HPP_
+
+#include "KeyFrame.hpp"
+
+namespace nima
+{
+	class ActorComponent;
+
+	class KeyFrameActiveChild : public KeyFrame
+	{
+		typedef KeyFrame Base;
+		
+		private:
+			unsigned m_Value;
+
+		protected:
+			void setValue(ActorComponent* component, float value, float mix);
+
+		public:
+			bool read(BlockReader* reader, ActorComponent* component) override;
+			void setNext(KeyFrame* frame) override;
+			void apply(ActorComponent* component, float mix) override;
+			void applyInterpolation(ActorComponent* component, float time, KeyFrame* toFrame, float mix) override;
+
+	};
+}
+
+#endif
\ No newline at end of file
diff --git a/Source/Animation/PropertyAnimation.cpp b/Source/Animation/PropertyAnimation.cpp
index cc4d575..2b3b540 100644
--- a/Source/Animation/PropertyAnimation.cpp
+++ b/Source/Animation/PropertyAnimation.cpp
@@ -14,6 +14,7 @@
 #include "KeyFrames/KeyFrameTrigger.hpp"
 #include "KeyFrames/KeyFrameCustomProperty.hpp"
 #include "KeyFrames/KeyFrameIsCollisionEnabled.hpp"
+#include "KeyFrames/KeyFrameActiveChild.hpp"
 #include <cassert> 
 
 using namespace nima;
@@ -115,6 +116,9 @@
 			case PropertyType::IsCollisionEnabled:
 				frame = new KeyFrameIsCollisionEnabled();
 				break;
+			case PropertyType::ActiveChildIndex:
+				frame = new KeyFrameActiveChild();
+				break;				
 			default:
 				// This will only happen if the code isn't handling a property type it should handle.
 				// Check the PropertyType enum and make sure Max is in the right place (and that you're not missing a case).
diff --git a/Source/Animation/PropertyAnimation.hpp b/Source/Animation/PropertyAnimation.hpp
index ba13c4b..5c1ac67 100644
--- a/Source/Animation/PropertyAnimation.hpp
+++ b/Source/Animation/PropertyAnimation.hpp
@@ -27,6 +27,7 @@
 		StringProperty = 14,
 		BooleanProperty = 15,
 		IsCollisionEnabled = 16,
+		ActiveChildIndex = 18,
 		Max
 	};