/// <summary> /// Initializes local working data for processing the specified <see cref="TilesetCompilerInput"/>. /// </summary> /// <param name="input"></param> private void InitWorkingData(TilesetCompilerInput input) { // Determine how many source tiles we have. This will be the smallest overlap // of available rendering input layers this.inputTileCount = int.MaxValue; for (int renderInputIndex = 0; renderInputIndex < input.RenderConfig.Count; renderInputIndex++) { TilesetRenderInput renderInput = input.RenderConfig[renderInputIndex] ?? DefaultRenderInput; PixelData sourceLayerData = (renderInput.SourceData.Res ?? Pixmap.Checkerboard.Res).MainLayer; LayerGeometry layerGeometry = this.CalculateLayerGeometry(renderInput, sourceLayerData); this.inputTileCount = Math.Min(this.inputTileCount, layerGeometry.SourceTileCount); } if (input.RenderConfig.Count == 0) { this.inputTileCount = 0; } // Initialize intermediate tile data to be big enough for the source data this.outputTileCount = this.inputTileCount; this.tiles.Count = this.inputTileCount; TileInfo[] data = this.tiles.Data; for (int i = 0; i < this.inputTileCount; i++) { data[i].IsVisuallyEmpty = true; } // Copy input data to our intermediate data structures TileInput[] inputData = input.TileInput.Data; for (int i = MathF.Min(this.inputTileCount, input.TileInput.Count); i >= 0; i--) { data[i].DepthOffset = inputData[i].DepthOffset; data[i].IsVertical = inputData[i].IsVertical; data[i].Collision = inputData[i].Collision; } }
/// <summary> /// Compiles a <see cref="Tileset"/> using its specified source data, in order to /// generate optimized target data for rendering and collision detection. /// </summary> public TilesetCompilerOutput Compile(TilesetCompilerInput input) { TilesetCompilerOutput output = input.ExistingOutput; output.TileData = output.TileData ?? new RawList<TileInfo>(input.TileInput.Count); output.RenderData = output.RenderData ?? new List<Texture>(); output.AutoTileData = output.AutoTileData ?? new List<TilesetAutoTileInfo>(); // Clear existing data, but keep the sufficiently big data structures output.TileData.Clear(); output.RenderData.Clear(); output.AutoTileData.Clear(); // Determine how many source tiles we have int sourceTileCount = int.MaxValue; for (int renderInputIndex = 0; renderInputIndex < input.RenderConfig.Count; renderInputIndex++) { TilesetRenderInput renderInput = input.RenderConfig[renderInputIndex] ?? DefaultRenderInput; PixelData sourceLayerData = (renderInput.SourceData.Res ?? Pixmap.Checkerboard.Res).MainLayer; LayerGeometry layerGeometry = this.CalculateLayerGeometry(renderInput, sourceLayerData); sourceTileCount = Math.Min(sourceTileCount, layerGeometry.SourceTileCount); } if (input.RenderConfig.Count == 0) sourceTileCount = 0; // Transform AutoTile data for (int autoTileIndex = 0; autoTileIndex < input.AutoTileConfig.Count; autoTileIndex++) { TilesetAutoTileInput autoTileInput = input.AutoTileConfig[autoTileIndex]; TilesetAutoTileInfo autoTileInfo = this.TransformAutoTileData( autoTileIndex, autoTileInput, output.TileData, sourceTileCount); output.AutoTileData.Add(autoTileInfo); } // Initialize all tiles to being visually empty. They will be subtractively updated // during output pixel data generation in the next step. { int tileDataCount = output.TileData.Count; TileInfo[] tileData = output.TileData.Data; for (int i = 0; i < tileDataCount; i++) { tileData[i].IsVisuallyEmpty = true; } } // Generate output pixel data for (int renderInputIndex = 0; renderInputIndex < input.RenderConfig.Count; renderInputIndex++) { TilesetRenderInput renderInput = input.RenderConfig[renderInputIndex] ?? DefaultRenderInput; PixelData sourceLayerData = (renderInput.SourceData.Res ?? Pixmap.Checkerboard.Res).MainLayer; // Determine overal geometry values for this layer, such as tile bounds and texture sizes LayerGeometry layerGeometry = this.CalculateLayerGeometry(renderInput, sourceLayerData); // Generate pixel data and atlas values for this layer's texture LayerPixelData targetLayerData = this.GenerateLayerPixelData( renderInput, sourceLayerData, layerGeometry, output.TileData); // Create the texture to be used for this rendering input using (Pixmap targetPixmap = new Pixmap(targetLayerData.PixelData)) { targetPixmap.Atlas = targetLayerData.Atlas; Texture targetTexture = new Texture( targetPixmap, TextureSizeMode.Enlarge, renderInput.TargetMagFilter, renderInput.TargetMinFilter, TextureWrapMode.Clamp, TextureWrapMode.Clamp, renderInput.TargetFormat); output.RenderData.Add(targetTexture); } } // Generate additional per-tile data this.TransformTileData(input.TileInput, output.TileData, output.RenderData); // Apply global tileset stats output.TileCount = sourceTileCount; return output; }
/// <summary> /// Compiles a <see cref="Tileset"/> using its specified source data, in order to /// generate optimized target data for rendering and collision detection. /// </summary> public TilesetCompilerOutput Compile(TilesetCompilerInput input) { // Clear private working data before beginning a new operation this.ClearWorkingData(); // Initialize private working data with the required space for our new input this.InitWorkingData(input); // Gather data on AutoTiles that are partially transformed from the input tileset, // and partially generated from existing tiles as part of the compilation. this.GatherAutoTileData(input.AutoTileConfig); // Generate metadata for scheduled tiles this.GenerateTileMetadata(); // Draw output pixel data for (int renderInputIndex = 0; renderInputIndex < input.RenderConfig.Count; renderInputIndex++) { TilesetRenderInput renderInput = input.RenderConfig[renderInputIndex] ?? DefaultRenderInput; PixelData sourceLayerData = (renderInput.SourceData.Res ?? Pixmap.Checkerboard.Res).MainLayer; // Determine overall geometry values for this layer, such as tile bounds and texture sizes LayerGeometry layerGeometry = this.CalculateLayerGeometry(renderInput, sourceLayerData); // Generate pixel data and atlas values for this layer's texture LayerPixelData targetLayerData = this.ComposeLayerPixelData( renderInput, sourceLayerData, layerGeometry); // Create the texture to be used for this rendering input using (Pixmap targetPixmap = new Pixmap(targetLayerData.PixelData)) { targetPixmap.Atlas = targetLayerData.Atlas; Texture targetTexture = new Texture( targetPixmap, TextureSizeMode.Enlarge, renderInput.TargetMagFilter, renderInput.TargetMinFilter, TextureWrapMode.Clamp, TextureWrapMode.Clamp, renderInput.TargetFormat); this.renderData.Add(targetTexture); } } // Retrieve texture atlas data for quick lookup during rendering if (this.renderData.Count > 0) { for (int i = 0; i < this.tiles.Count; i++) { this.renderData[0].LookupAtlas(i, out this.tiles.Data[i].TexCoord0); } } // Prepare output, keeping existing structures to avoid allocations TilesetCompilerOutput output = input.ExistingOutput; output.TileCount = this.outputTileCount; output.TileData = output.TileData ?? new RawList <TileInfo>(input.TileInput.Count); output.TileData.Clear(); this.tiles.CopyTo(output.TileData, 0, this.tiles.Count); output.RenderData = output.RenderData ?? new List <Texture>(this.renderData); output.RenderData.Clear(); output.RenderData.AddRange(this.renderData); output.AutoTileData = output.AutoTileData ?? new List <TilesetAutoTileInfo>(); output.AutoTileData.Clear(); this.TransformAutoTileData(output.AutoTileData); output.EmptyTileIndex = this.GetEmptyTileIndex(); this.ClearWorkingData(); return(output); }
/// <summary> /// Compiles a <see cref="Tileset"/> using its specified source data, in order to /// generate optimized target data for rendering and collision detection. /// </summary> public TilesetCompilerOutput Compile(TilesetCompilerInput input) { TilesetCompilerOutput output = input.ExistingOutput; output.TileData = output.TileData ?? new RawList <TileInfo>(input.TileInput.Count); output.RenderData = output.RenderData ?? new List <Texture>(); output.AutoTileData = output.AutoTileData ?? new List <TilesetAutoTileInfo>(); // Clear existing data, but keep the sufficiently big data structures output.TileData.Clear(); output.RenderData.Clear(); output.AutoTileData.Clear(); // Determine how many source tiles we have int sourceTileCount = int.MaxValue; for (int renderInputIndex = 0; renderInputIndex < input.RenderConfig.Count; renderInputIndex++) { TilesetRenderInput renderInput = input.RenderConfig[renderInputIndex] ?? DefaultRenderInput; PixelData sourceLayerData = (renderInput.SourceData.Res ?? Pixmap.Checkerboard.Res).MainLayer; LayerGeometry layerGeometry = this.CalculateLayerGeometry(renderInput, sourceLayerData); sourceTileCount = Math.Min(sourceTileCount, layerGeometry.SourceTileCount); } if (input.RenderConfig.Count == 0) { sourceTileCount = 0; } // Transform AutoTile data for (int autoTileIndex = 0; autoTileIndex < input.AutoTileConfig.Count; autoTileIndex++) { TilesetAutoTileInput autoTileInput = input.AutoTileConfig[autoTileIndex]; TilesetAutoTileInfo autoTileInfo = this.TransformAutoTileData( autoTileIndex, autoTileInput, output.TileData, sourceTileCount); output.AutoTileData.Add(autoTileInfo); } // Initialize all tiles to being visually empty. They will be subtractively updated // during output pixel data generation in the next step. { int tileDataCount = output.TileData.Count; TileInfo[] tileData = output.TileData.Data; for (int i = 0; i < tileDataCount; i++) { tileData[i].IsVisuallyEmpty = true; } } // Generate output pixel data for (int renderInputIndex = 0; renderInputIndex < input.RenderConfig.Count; renderInputIndex++) { TilesetRenderInput renderInput = input.RenderConfig[renderInputIndex] ?? DefaultRenderInput; PixelData sourceLayerData = (renderInput.SourceData.Res ?? Pixmap.Checkerboard.Res).MainLayer; // Determine overal geometry values for this layer, such as tile bounds and texture sizes LayerGeometry layerGeometry = this.CalculateLayerGeometry(renderInput, sourceLayerData); // Generate pixel data and atlas values for this layer's texture LayerPixelData targetLayerData = this.GenerateLayerPixelData( renderInput, sourceLayerData, layerGeometry, output.TileData); // Create the texture to be used for this rendering input using (Pixmap targetPixmap = new Pixmap(targetLayerData.PixelData)) { targetPixmap.Atlas = targetLayerData.Atlas; Texture targetTexture = new Texture( targetPixmap, TextureSizeMode.Enlarge, renderInput.TargetMagFilter, renderInput.TargetMinFilter, TextureWrapMode.Clamp, TextureWrapMode.Clamp, renderInput.TargetFormat); output.RenderData.Add(targetTexture); } } // Generate additional per-tile data this.TransformTileData(input.TileInput, output.TileData, output.RenderData); // Apply global tileset stats output.TileCount = sourceTileCount; return(output); }