/// <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(); }
/// <summary> /// Pans the Grid Tiles the given amount (only supports one square for now) /// </summary> /// <param name="panAmountX"></param> /// <param name="panAmountY"></param> private void PanGrid(int panAmountX, int panAmountY) { PerfStopwatch ps = PerfStopwatch.StartNew("Pan Grid"); if (panAmountX == 0 && panAmountY == 0) { return; } //If positive move tiles from left edge to right edge int xTileIndexToFind = GetXTileEdge(panAmountX); int yTileIndexToFind = GetYTileEdge(panAmountY); List <MapTileVisual> tilesToMove = new List <MapTileVisual>(); if (panAmountX != 0) { tilesToMove.AddRange(Tiles.Where(t => t.TileX == xTileIndexToFind)); } if (panAmountY != 0) { tilesToMove.AddRange(Tiles.Where(t => t.TileY == yTileIndexToFind)); } OSMWorldScale scale = new OSMWorldScale(); double mapCenterNormalizedX = scale.NormalizeX(TileService.xTileOffset); double mapCenterNormalizedY = scale.NormalizeY(TileService.yTileOffset); double tileTranslateX = scale.GetTileXTranslateFix(mapCenterNormalizedX, mapZoom, TileSize); //TileSize * fracX; double tileTranslateY = scale.GetTileYTranslateFix(mapCenterNormalizedY, mapZoom, TileSize); //TileSize * fracY; foreach (MapTileVisual tile in tilesToMove) { if (tile.TileX == xTileIndexToFind) { tile.TileX += GridSize * panAmountX; } if (tile.TileY == yTileIndexToFind) { tile.TileY += GridSize * panAmountY; } TranslateTransform3D transform = tile.Transform as TranslateTransform3D; //Apply this as a transformation as well if (transform != null) { transform.OffsetX = ((tile.TileX * TileSize * -1) - TileSize / 2) - tileTranslateX; transform.OffsetY = ((tile.TileY * TileSize) - TileSize / 2) - tileTranslateY; } tile.UpdateDebugLabels(); //Send of a request to update the tile TileGenerator.LoadTileImageAsync(tile, tile.TileX, tile.TileY, MapZoomLevel); } currentTileX += panAmountX; currentTileY += panAmountY; ps.Stop(); }