Example #1
0
        /// <summary>
        /// Captures the current values for a given entity and creates a keyframe
        /// at the given time and with the captured values
        /// </summary>
        /// <param name="entity">entity to capture</param>
        /// <param name="time">Time to create keyframe at</param>
        public void Capture(Entity entity, int time)
        {
            if (entity == null)
            {
                throw new ArgumentNullException(nameof(entity), "entity cannot be null");
            }
            PerfStopwatch stopwatch = PerfStopwatch.StartNew("Capturing New keyframe");
            //Get all behaviours on entity
            IEnumerable <BehaviourComponent> behaviours   = entity.Components;
            List <KeyframePropertyData>      propertyData = new List <KeyframePropertyData>();

            foreach (BehaviourComponent behaviour in behaviours)
            {
                //Check if the cache contains entry for this behaviour
                if (!keyframeInfoCache.ContainsKey(behaviour))
                {
                    //Get all properties with the KeyframeAnimationProperty attribute
                    Type behaviourType = behaviour.GetType();
                    IEnumerable <PropertyInfo> reflectedProperties = behaviourType.GetProperties().Where(
                        prop => Attribute.IsDefined(prop, typeof(KeyframeProperty))
                        );
                    List <KeyframePropertyInfo> propInfos = new List <KeyframePropertyInfo>();
                    foreach (PropertyInfo propInfo in reflectedProperties)
                    {
                        if (!propInfo.CanWrite || !propInfo.CanRead)
                        {
                            DebugUtil.LogWithLocation($"Property {propInfo.Name} needs both read and write access");
                            continue;
                        }
                        propInfos.Add(new KeyframePropertyInfo(propInfo, PropertyType.Interpolatable));
                    }

                    keyframeInfoCache.Add(behaviour, propInfos.ToArray());
                }

                KeyframePropertyInfo[] properties = keyframeInfoCache[behaviour];
                for (int i = 0, l = properties.Length; i < l; i++)
                {
                    object currentPropertyValue = properties[i].Property.GetValue(behaviour);
                    KeyframePropertyData key    = new ValueKeyframe(properties[i], behaviour, currentPropertyValue);
                    //Add it to the timeline
                    propertyData.Add(key);
                }
            }
            //Check if entity has a timeline or if we need to create one for it
            if (!timelines.ContainsKey(entity))
            {
                CreateTimeline(entity);
            }

            KeyContainer newKey = new KeyContainer(propertyData);

            newKey.Time = time;
            timelines[entity].AddKeyframe(newKey);

            stopwatch.Stop();
        }
Example #2
0
        private void SeekValueKeyframe(KeyframeTimeline timeline, KeyframePropertyInfo property, int time)
        {
            //Get closest keys
            KeySet interval = timeline.GetClosestKeys(property, time);
            //int t = 5;
            Type valueType = property.Property.PropertyType;

            //If both keys are the same, no need for interpolation
            if (interval.TimeBefore == interval.TimeAfter)
            {
                ValueKeyframe value = timeline.GetPropertyKey(property, interval.TimeBefore) as ValueKeyframe;

                if (value == null)
                {
                    //Property had no keyframes or was not a value keyframe there is nothing to do, just return
                    return;
                }

                property.Property.SetValue(value.Target, value.Value);
            }
            else
            {
                if (interpolatorCache.ContainsKey(valueType))
                {
                    ValueKeyframe from = timeline.GetPropertyKey(property, interval.TimeBefore) as ValueKeyframe;
                    ValueKeyframe to   = timeline.GetPropertyKey(property, interval.TimeAfter) as ValueKeyframe;

                    double diff           = interval.TimeAfter - interval.TimeBefore;
                    double diffFromLowest = time - interval.TimeBefore;

                    if (diff == 0)
                    {
                        DebugUtil.LogWithLocation($"Difference between keyframes was 0, cannot continue");
                        return;
                    }

                    double t = diffFromLowest / diff;

                    object interpolatedValue = interpolatorCache[valueType].InterpolateBetween(from.Value, to.Value, t);

                    property.Property.SetValue(from.Target, interpolatedValue);
                }
                else
                {
                    DebugUtil.LogWithLocation($"Interpolator cache did not contain a implementation for type {valueType}");
                }
            }
        }