Adding ActorComponent, ActorEvent, and triggerEvents methods.
diff --git a/Source/Actor.cpp b/Source/Actor.cpp
index 04a0b1d..f991e9e 100644
--- a/Source/Actor.cpp
+++ b/Source/Actor.cpp
@@ -2,6 +2,7 @@
 #include "ActorBone.hpp"
 #include "ActorRootBone.hpp"
 #include "ActorIKTarget.hpp"
+#include "ActorEvent.hpp"
 #include "BinaryReader.hpp"
 #include "BlockReader.hpp"
 #include "Exceptions/OverflowException.hpp"
@@ -254,6 +255,9 @@
 				m_SolverNodeCount++;
 				component = ActorIKTarget::read(this, componentBlock);
 				break;
+			case BlockType::ActorEvent:
+				component = ActorEvent::read(this, componentBlock);
+				break;
 			default:
 				// Not handled/expected block.
 				break;
diff --git a/Source/Actor.hpp b/Source/Actor.hpp
index d3b3e34..2d9f8e0 100644
--- a/Source/Actor.hpp
+++ b/Source/Actor.hpp
@@ -22,7 +22,8 @@
 		Animations = 8,
 		Atlases = 9,
 		Atlas = 10,
-		ActorIKTarget = 11
+		ActorIKTarget = 11,
+		ActorEvent = 12
 	};
 
 	class Actor
diff --git a/Source/ActorComponent.cpp b/Source/ActorComponent.cpp
index 4cac363..4a79b8c 100644
--- a/Source/ActorComponent.cpp
+++ b/Source/ActorComponent.cpp
@@ -5,6 +5,11 @@
 #include <cassert>
 using namespace nima;
 
+ActorComponent::ActorComponent(ComponentType type) : ActorComponent(nullptr, type)
+{
+
+}
+
 ActorComponent::ActorComponent(Actor* actor, ComponentType type) : 
 			m_Type(type),
 			m_Parent(nullptr),
diff --git a/Source/ActorComponent.hpp b/Source/ActorComponent.hpp
index 132a12e..5786995 100644
--- a/Source/ActorComponent.hpp
+++ b/Source/ActorComponent.hpp
@@ -18,7 +18,8 @@
 		ActorBone = 3,
 		ActorRootBone = 4,
 		ActorImage = 5,
-		ActorIKTarget = 11
+		ActorIKTarget = 11,
+		ActorEvent = 12
 	};
 
 
@@ -35,6 +36,7 @@
 			unsigned short m_Idx;
 			
 		protected:
+			ActorComponent(ComponentType type);
 			ActorComponent(Actor* actor, ComponentType type);
 
 		public:
diff --git a/Source/ActorEvent.cpp b/Source/ActorEvent.cpp
new file mode 100644
index 0000000..b93f1a6
--- /dev/null
+++ b/Source/ActorEvent.cpp
@@ -0,0 +1,33 @@
+#include "ActorEvent.hpp"
+#include "BlockReader.hpp"
+using namespace nima;
+
+ActorEvent::ActorEvent() : ActorComponent(ComponentType::ActorEvent)
+{
+
+}
+
+ActorComponent* ActorEvent::makeInstance(Actor* resetActor)
+{
+	ActorEvent* eventInstance = new ActorEvent();
+	eventInstance->copy(this, resetActor);
+	return eventInstance;
+
+}
+
+void ActorEvent::copy(ActorComponent* node, Actor* resetActor)
+{	
+	Base::copy(node, resetActor);
+}
+
+ActorEvent* ActorEvent::read(Actor* actor, BlockReader* reader, ActorEvent* component)
+{
+	if(component == nullptr)
+	{
+		component = new ActorEvent();
+	}
+
+	Base::read(actor, reader, component);
+
+	return component;
+}
\ No newline at end of file
diff --git a/Source/ActorEvent.hpp b/Source/ActorEvent.hpp
new file mode 100644
index 0000000..cf7f568
--- /dev/null
+++ b/Source/ActorEvent.hpp
@@ -0,0 +1,20 @@
+#ifndef _NIMA_ACTOREVENT_HPP_
+#define _NIMA_ACTOREVENT_HPP_
+
+#include <string>
+#include "ActorComponent.hpp"
+
+namespace nima
+{
+	class ActorEvent : public ActorComponent
+	{
+		typedef ActorComponent Base;
+		public:
+			ActorEvent();
+			ActorComponent* makeInstance(Actor* resetActor) override;
+			void copy(ActorComponent* node, Actor* resetActor);
+
+			static ActorEvent* read(Actor* actor, BlockReader* reader, ActorEvent* component = NULL);
+	};
+}
+#endif
\ No newline at end of file
diff --git a/Source/ActorNode.hpp b/Source/ActorNode.hpp
index 26dcaf0..b738aca 100644
--- a/Source/ActorNode.hpp
+++ b/Source/ActorNode.hpp
@@ -1,7 +1,6 @@
 #ifndef _NIMA_ACTORNODE_HPP_
 #define _NIMA_ACTORNODE_HPP_
 
-#include <string>
 #include <vector>
 #include <nima/Mat2D.hpp>
 #include <nima/Vec2D.hpp>
diff --git a/Source/Animation/ActorAnimation.cpp b/Source/Animation/ActorAnimation.cpp
index 0184657..c2774a4 100644
--- a/Source/Animation/ActorAnimation.cpp
+++ b/Source/Animation/ActorAnimation.cpp
@@ -1,4 +1,5 @@
 #include "ActorAnimation.hpp"
+#include "../ActorComponent.hpp"
 #include "../BlockReader.hpp"
 
 using namespace nima;
@@ -41,6 +42,14 @@
 	}
 }
 
+void ActorAnimation::triggerEvents(ActorComponent** components, float fromTime, float toTime, std::vector<ActorAnimationEvent>& events)
+{
+	for(auto keyedComponent : m_TriggerComponents)
+	{
+		keyedComponent->triggerEvents(components, fromTime, toTime, events);
+	}
+}
+
 void ActorAnimation::read(BlockReader* reader, ActorComponent** components)
 {
 	m_Name = reader->readString();
@@ -53,6 +62,14 @@
 
 	for(int i = 0; i < m_AnimatedComponentsCount; i++)
 	{
-		m_AnimatedComponents[i].read(reader, components);
+		ComponentAnimation& animatedComponent = m_AnimatedComponents[i];
+		animatedComponent.read(reader, components);
+
+		// Put actor events in a separate list...
+		ActorComponent* component = components[animatedComponent.componentIndex()];
+		if(component != nullptr && component->type() == ComponentType::ActorEvent)
+		{
+			m_TriggerComponents.push_back(&animatedComponent);
+		}
 	}
 }
\ No newline at end of file
diff --git a/Source/Animation/ActorAnimation.hpp b/Source/Animation/ActorAnimation.hpp
index e75e7a3..d83149e 100644
--- a/Source/Animation/ActorAnimation.hpp
+++ b/Source/Animation/ActorAnimation.hpp
@@ -2,13 +2,30 @@
 #define _NIMA_ACTORANIMATION_HPP_
 
 #include <string>
+#include <vector>
 #include "ComponentAnimation.hpp"
 
 namespace nima
 {
 	class BlockReader;
 	class ActorNode;
-	
+	class ActorEvent;
+
+	struct ActorAnimationEvent
+	{
+		ActorEvent* actorEvent;
+		float keyFrameTime;
+		float elapsedTime;
+
+		ActorAnimationEvent(ActorEvent* av, float time, float elapsed) :
+			actorEvent(av),
+			keyFrameTime(time),
+			elapsedTime(elapsed)
+		{
+
+		}
+	};
+
 	class ActorAnimation
 	{
 		private:
@@ -19,7 +36,10 @@
 			ComponentAnimation* m_AnimatedComponents;
 			int m_AnimatedComponentsCount;
 
+			std::vector<ComponentAnimation*> m_TriggerComponents;
+
 		public:
+
 			ActorAnimation();
 			~ActorAnimation();
 			const std::string& name() const;
@@ -30,6 +50,8 @@
 
 			void apply(float time, Actor* actor, float mix);
 
+			void triggerEvents(ActorComponent** components, float fromTime, float toTime, std::vector<ActorAnimationEvent>& events);
+
 	};
 }
 #endif
\ No newline at end of file
diff --git a/Source/Animation/ComponentAnimation.cpp b/Source/Animation/ComponentAnimation.cpp
index d8e4d83..551a811 100644
--- a/Source/Animation/ComponentAnimation.cpp
+++ b/Source/Animation/ComponentAnimation.cpp
@@ -1,10 +1,13 @@
 #include "ComponentAnimation.hpp"
+#include "ActorAnimation.hpp"
+#include "KeyFrames/KeyFrame.hpp"
 #include "../Actor.hpp"
 #include "../BlockReader.hpp"
 
 using namespace nima;
 
 ComponentAnimation::ComponentAnimation() :
+	m_ComponentIndex(0),
 	m_Properties(NULL),
 	m_PropertiesCount(0)
 {
@@ -30,6 +33,95 @@
 	}
 }
 
+void ComponentAnimation::triggerEvents(ActorComponent** components, float fromTime, float toTime, std::vector<ActorAnimationEvent>& events)
+{
+	for(int i = 0; i < m_PropertiesCount; i++)
+	{
+		PropertyAnimation& property = m_Properties[i];
+		switch(property.type())
+		{
+			case PropertyType::Trigger:
+			{
+				int keyFramesCount = property.keyFramesCount();
+				if(keyFramesCount == 0)
+				{
+					continue;
+				}
+				int idx = 0;
+				// Binary find the keyframe index.
+				{
+					int mid = 0;
+					float element = 0.0f;
+					int start = 0;
+					int end = keyFramesCount-1;
+
+					while (start <= end) 
+					{
+				    	mid = ((start + end) >> 1);
+						element = property.keyFrame(mid)->time();
+						if (element < toTime) 
+						{
+							start = mid + 1;
+						} 
+						else if (element > toTime) 
+						{
+							end = mid - 1;
+						} 
+						else 
+						{
+							start = mid;
+							break;
+						}
+					}
+
+					idx = start;
+				}
+
+				if(idx == 0)
+				{
+					if(property.keyFrame(0)->time() == toTime)
+					{
+						ActorEvent* actorEvent = reinterpret_cast<ActorEvent*>(components[m_ComponentIndex]);
+						events.emplace_back(ActorAnimationEvent(actorEvent, toTime, 0.0f));
+						//ActorComponent component = components[keyedComponent.ComponentIndex];
+						//triggerEvents.Add(new AnimationEventArgs(component.Name, component, property.PropertyType, toTime, 0.0f));
+					}
+				}
+				else
+				{
+					for(int k = idx-1; k >= 0; k--)
+					{
+						float frameTime = property.keyFrame(k)->time();
+
+						if(frameTime > fromTime)
+						{
+							ActorEvent* actorEvent = reinterpret_cast<ActorEvent*>(components[m_ComponentIndex]);
+							events.emplace_back(ActorAnimationEvent(actorEvent, frameTime, toTime-frameTime));
+
+							//ActorComponent component = components[keyedComponent.ComponentIndex];
+							//triggerEvents.Add(new AnimationEventArgs(component.Name, component, property.PropertyType, frameTime, toTime-frameTime));
+							/*triggered.push({
+								name:component._Name,
+								component:component,
+								propertyType:property._Type,
+								keyFrameTime:frame._Time,
+								elapsed:toTime-frame._Time
+							});*/
+						}
+						else
+						{
+							break;
+						}
+					}
+				}
+				break;
+			}
+			default:
+				break;
+		}	
+	}
+}
+
 void ComponentAnimation::read(BlockReader* reader, ActorComponent** components)
 {
 	m_ComponentIndex = reader->readUnsignedShort();
diff --git a/Source/Animation/ComponentAnimation.hpp b/Source/Animation/ComponentAnimation.hpp
index b5794ee..a7b819e 100644
--- a/Source/Animation/ComponentAnimation.hpp
+++ b/Source/Animation/ComponentAnimation.hpp
@@ -2,6 +2,7 @@
 #define _NIMA_COMPONENTANIMATION_HPP_
 
 #include <string>
+#include <vector>
 #include "PropertyAnimation.hpp"
 
 namespace nima
@@ -9,7 +10,8 @@
 	class BlockReader;
 	class ActorComponent;
 	class Actor;
-	
+	struct ActorAnimationEvent;
+
 	class ComponentAnimation
 	{
 		private:
@@ -24,6 +26,7 @@
 
 			void read(BlockReader* reader, ActorComponent** components);
 			void apply(float time, Actor* actor, float mix);
+			void triggerEvents(ActorComponent** components, float fromTime, float toTime, std::vector<ActorAnimationEvent>& events);
 
 	};
 }
diff --git a/Source/Animation/KeyFrames/KeyFrameTrigger.cpp b/Source/Animation/KeyFrames/KeyFrameTrigger.cpp
new file mode 100644
index 0000000..8fb137a
--- /dev/null
+++ b/Source/Animation/KeyFrames/KeyFrameTrigger.cpp
@@ -0,0 +1,42 @@
+#include "KeyFrameTrigger.hpp"
+#include "../../Actor.hpp"
+#include "../../ActorImage.hpp"
+#include "../../BlockReader.hpp"
+
+using namespace nima;
+
+			
+KeyFrameTrigger::KeyFrameTrigger()
+{
+
+}
+
+KeyFrameTrigger::~KeyFrameTrigger()
+{
+}
+
+
+bool KeyFrameTrigger::read(BlockReader* reader, ActorComponent* component)
+{
+	if(!Base::read(reader, component))
+	{
+		return false;
+	}
+	
+	return true;
+}
+
+void KeyFrameTrigger::setNext(KeyFrame* frame)
+{
+	// Do nothing, we don't interpolate.
+}
+
+void KeyFrameTrigger::apply(ActorComponent* component, float mix)
+{
+	// Intentionally blank.
+}
+
+void KeyFrameTrigger::applyInterpolation(ActorComponent* node, float time, KeyFrame* toFrame, float mix)
+{
+	// Do nothing, we don't interpolate.
+}
\ No newline at end of file
diff --git a/Source/Animation/KeyFrames/KeyFrameTrigger.hpp b/Source/Animation/KeyFrames/KeyFrameTrigger.hpp
new file mode 100644
index 0000000..238694f
--- /dev/null
+++ b/Source/Animation/KeyFrames/KeyFrameTrigger.hpp
@@ -0,0 +1,25 @@
+#ifndef _NIMA_KEYFRAMETRIGGER_HPP_
+#define _NIMA_KEYFRAMETRIGGER_HPP_
+
+#include "KeyFrame.hpp"
+
+namespace nima
+{
+	class ActorComponent;
+
+	class KeyFrameTrigger : public KeyFrame
+	{
+		typedef KeyFrame Base;
+
+		public:	
+			KeyFrameTrigger();
+			virtual ~KeyFrameTrigger();
+
+			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 a155633..36fa085 100644
--- a/Source/Animation/PropertyAnimation.cpp
+++ b/Source/Animation/PropertyAnimation.cpp
@@ -11,6 +11,7 @@
 #include "KeyFrames/KeyFrameLength.hpp"
 #include "KeyFrames/KeyFrameVertexDeform.hpp"
 #include "KeyFrames/KeyFrameIKStrength.hpp"
+#include "KeyFrames/KeyFrameTrigger.hpp"
 #include <cassert> 
 
 using namespace nima;
@@ -32,6 +33,16 @@
 	delete [] m_KeyFrames;
 }
 
+int PropertyAnimation::keyFramesCount() const
+{
+	return m_KeyFramesCount;
+}
+
+PropertyType PropertyAnimation::type() const
+{
+	return m_Type;
+}
+
 void PropertyAnimation::read(BlockReader* reader, ActorComponent* component)
 {
 	BlockReader* block = reader->readNextBlock();
@@ -84,6 +95,9 @@
 			case PropertyType::IKStrength:
 				frame = new KeyFrameIKStrength();
 				break;
+			case PropertyType::Trigger:
+				frame = new KeyFrameTrigger();
+				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 80254e0..8062544 100644
--- a/Source/Animation/PropertyAnimation.hpp
+++ b/Source/Animation/PropertyAnimation.hpp
@@ -21,6 +21,7 @@
 		Length = 8,
 		VertexDeform = 9,
 		IKStrength = 10,
+		Trigger = 11,
 		Max
 	};
 
@@ -35,6 +36,14 @@
 
 			PropertyAnimation();
 			~PropertyAnimation();
+
+			int keyFramesCount() const;
+			inline const KeyFrame* keyFrame(int idx) const
+			{
+				return m_KeyFrames[idx];
+			}
+
+			PropertyType type() const;
 			void read(BlockReader* reader, ActorComponent* component);
 			void apply(float time, ActorComponent* component, float mix);