public void SetPreviewTilemap(Unity_Map map, Unity_Tile[,] newTiles) { int w = newTiles.GetLength(0); int h = newTiles.GetLength(1); if (w <= 0 || h <= 0) { ClearPreviewTilemap(); return; } int cellSize = LevelEditorData.Level.CellSize; Texture2D tex = new Texture2D(w * cellSize, h * cellSize); for (int y = 0; y < h; y++) { for (int x = 0; x < w; x++) { Unity_Tile newTile = newTiles[x, y]; Unity_TileTexture tile = map.GetTile(newTile, LevelEditorData.CurrentSettings); FillInTilePixels(tex, tile, newTile, x, y, cellSize, applyTexture: false); } } tex.filterMode = FilterMode.Point; tex.Apply(); tilemapPreview.sprite = Sprite.Create(tex, new Rect(0, 0, tex.width, tex.height), new Vector2(0, 0), LevelEditorData.Level.PixelsPerUnit, 0, SpriteMeshType.FullRect); }
public Unity_Level(Unity_Map[] maps, Unity_ObjectManager objManager, List <Unity_Object> eventData = null, Unity_Object rayman = null, IReadOnlyDictionary <string, string[]> localization = null, int defaultMap = 0, int defaultCollisionMap = 0, int pixelsPerUnit = 16, int cellSize = 16, Func <ushort, string> getCollisionTypeNameFunc = null, Func <ushort, Unity_MapCollisionTypeGraphic> getCollisionTypeGraphicFunc = null, Texture2D background = null, Texture2D parallaxBackground = null, Unity_Sector[] sectors = null, Unity_IsometricData isometricData = null) { Maps = maps; ObjManager = objManager; EventData = eventData ?? new List <Unity_Object>(); Rayman = rayman; Localization = localization; DefaultMap = defaultMap; DefaultCollisionMap = defaultCollisionMap == -1 ? 0 : defaultCollisionMap; PixelsPerUnit = pixelsPerUnit; CellSize = cellSize; GetCollisionTypeNameFunc = getCollisionTypeNameFunc ?? (x => ((R1_TileCollisionType)x).ToString()); GetCollisionTypeGraphicFunc = getCollisionTypeGraphicFunc ?? (x => ((R1_TileCollisionType)x).GetCollisionTypeGraphic()); Background = background; ParallaxBackground = parallaxBackground; Sectors = sectors; IsometricData = isometricData; MaxWidth = Maps.Max(m => m.Width); MaxHeight = Maps.Max(m => m.Height); GridMap = new Unity_Map { Width = MaxWidth, Height = MaxHeight, TileSet = new Unity_TileSet[] { new Unity_TileSet(Util.GetGridTex(cellSize), cellSize), }, MapTiles = Enumerable.Range(0, MaxWidth * MaxHeight).Select(x => new Unity_Tile(new MapTile())).ToArray(), Type = Unity_Map.MapType.Graphics, Layer = Unity_Map.MapLayer.Overlay }; }
public async UniTask<Unity_Level> LoadAsync(Context context, bool loadTextures) { Controller.DetailedState = $"Loading data"; await Controller.WaitIfNecessary(); // Read the rom var rom = FileFactory.Read<SNES_Proto_ROM>(GetROMFilePath, context); // Get the map var map = rom.MapData; var maps = new Unity_Map[] { new Unity_Map() { // Set the dimensions Width = map.Width, Height = map.Height, // Create the tile arrays TileSet = new Unity_MapTileMap[1], MapTiles = map.Tiles.Select(x => new Unity_Tile(x)).ToArray(), TileSetWidth = 1 } }; // Convert levelData to common level format Unity_Level level = new Unity_Level(maps, new Unity_ObjectManager(context), getCollisionTypeGraphicFunc: x => ((R1Jaguar_TileCollisionType)x).GetCollisionTypeGraphic()); Controller.DetailedState = $"Loading tile set"; await Controller.WaitIfNecessary(); // Load tile set and treat black as transparent level.Maps[0].TileSet[0] = GetTileSet(context, rom); return level; }
/// <summary> /// Loads the specified level for the editor /// </summary> /// <param name="context">The serialization context</param> /// <param name="loadTextures">Indicates if textures should be loaded</param> /// <returns>The level</returns> public override async UniTask <Unity_Level> LoadAsync(Context context, bool loadTextures) { // Get the level folder path var basePath = await GetLevelFolderPath(context); // TODO: Parse .ini file to get background etc. // Get file paths var mapPath = GetMapFilePath(basePath); var mapEventsPath = GetMapEventsFilePath(basePath); var saveEventsPath = GetSaveEventsFilePath(basePath); var pcxPath = GetPCXFilePath(context.Settings); var eventsCsvPath = GetEventManfiestFilePath(context.Settings.R1_World); // Load files to context await AddFile(context, mapPath); await AddFile(context, mapEventsPath, endianness : BinaryFile.Endian.Big); // Big endian just like on Jaguar await AddFile(context, pcxPath); // Read the files Controller.DetailedState = $"Loading map data"; await Controller.WaitIfNecessary(); var mapData = FileFactory.Read <MapData>(mapPath, context); Controller.DetailedState = $"Loading event data"; await Controller.WaitIfNecessary(); var mapEvents = FileFactory.Read <R1Jaguar_MapEvents>(mapEventsPath, context); var saveEvents = FileFactory.ReadText <R1_Mapper_SaveEvents>(saveEventsPath, context); var csv = FileFactory.ReadText <R1_Mapper_EventManifest>(eventsCsvPath, context); Controller.DetailedState = $"Loading tileset"; await Controller.WaitIfNecessary(); var pcx = FileFactory.Read <PCX>(pcxPath, context); // Get the palette from the PCX file var vgaPalette = pcx.VGAPalette; // Load the sprites var eventDesigns = loadTextures ? await LoadSpritesAsync(context, vgaPalette) : new Unity_ObjectManager_R1.DESData[0]; // Read the world data var worldData = FileFactory.Read <R1_PC_WorldFile>(GetWorldFilePath(context.Settings), context); var maps = new Unity_Map[] { new Unity_Map() { // Set the dimensions Width = mapData.Width, Height = mapData.Height, // Create the tile arrays TileSet = new Unity_MapTileMap[1], MapTiles = mapData.Tiles.Select(x => new Unity_Tile(x)).ToArray(), TileSetWidth = 1 } }; var allEventInstances = saveEvents.SaveEventInstances.SelectMany(x => x).ToArray(); // Create a linking table var linkTable = new ushort[allEventInstances.Length]; // Handle each event link group foreach (var linkedEvents in allEventInstances.Select((x, i) => new { Index = i, Data = x }).GroupBy(x => x.Data.LinkID)) { // Get the group var group = linkedEvents.ToArray(); // Handle every event for (int i = 0; i < group.Length; i++) { // Get the item var item = group[i]; if (group.Length == i + 1) { linkTable[item.Index] = (ushort)group[0].Index; } else { linkTable[item.Index] = (ushort)group[i + 1].Index; } } } // Create the object manager var objManager = new Unity_ObjectManager_R1( context: context, des: eventDesigns.Select((x, i) => new Unity_ObjectManager_R1.DataContainer <Unity_ObjectManager_R1.DESData>(x, i, worldData.DESFileNames?.ElementAtOrDefault(i))).ToArray(), eta: GetCurrentEventStates(context).Select((x, i) => new Unity_ObjectManager_R1.DataContainer <R1_EventState[][]>(x.States, i, worldData.ETAFileNames?.ElementAtOrDefault(i))).ToArray(), linkTable: linkTable, usesPointers: false, hasDefinedDesEtaNames: true); Controller.DetailedState = $"Loading events"; await Controller.WaitIfNecessary(); var levelEvents = new List <Unity_Object>(); // Create events for (var i = 0; i < saveEvents.SaveEventInstances.Length; i++) { // Get the map base position, based on the event map var mapPos = mapEvents.EventIndexMap.FindItemIndex(z => z == i + 1); // Get the x and y positions var mapY = (uint)Math.Floor(mapPos / (double)(mapEvents.Width)); var mapX = (uint)(mapPos - (mapY * mapEvents.Width)); // Calculate the actual position on the map mapX *= 4 * (uint)Settings.CellSize; mapY *= 4 * (uint)Settings.CellSize; // Add every instance foreach (var instance in saveEvents.SaveEventInstances[i]) { // Get the definition var def = csv.EventDefinitions.FirstOrDefault(x => x.Name == instance.EventDefinitionKey); if (def == null) { throw new Exception($"No matching event definition found for {instance.EventDefinitionKey}"); } var ed = new R1_EventData() { Type = def.Type, Etat = def.Etat, SubEtat = def.SubEtat, XPosition = (short)(mapX + instance.OffsetX), YPosition = (short)(mapY + instance.OffsetY), OffsetBX = def.OffsetBX, OffsetBY = def.OffsetBY, OffsetHY = def.OffsetHY, FollowSprite = def.FollowSprite, ActualHitPoints = (uint)instance.HitPoints, DisplayPrio = instance.DisplayPrio, HitSprite = def.HitSprite, PS1Demo_Unk1 = new byte[40], Unk_98 = new byte[5], LabelOffsets = new ushort[0], Commands = R1_EventCommandCollection.FromBytes(def.EventCommands, context.Settings), }; ed.SetFollowEnabled(context.Settings, def.FollowEnabled > 0); // Add the event levelEvents.Add(new Unity_Object_R1( eventData: ed, objManager: objManager, ETAIndex: worldData.ETAFileNames.FindItemIndex(x => x == def.ETAFile)) { DESIndex = worldData.DESFileNames.FindItemIndex(x => x.Length > 4 && x.Substring(0, x.Length - 4) == def.DESFile) }); } } // Convert levelData to common level format var level = new Unity_Level(maps, objManager, levelEvents, rayman: new Unity_Object_R1(R1_EventData.GetRayman(context, levelEvents.Cast <Unity_Object_R1>().FirstOrDefault(x => x.EventData.Type == R1_EventType.TYPE_RAY_POS)?.EventData), objManager)); Controller.DetailedState = $"Creating tileset"; await Controller.WaitIfNecessary(); // Load the tile set level.Maps[0].TileSet[0] = LoadTileSet(pcx); // Return the level return(level); }
public async UniTask <Unity_Level> LoadAsync(Context context, bool loadTextures) { Controller.DetailedState = $"Loading data"; await Controller.WaitIfNecessary(); // Read the rom var rom = FileFactory.Read <SNES_Proto_ROM>(GetROMFilePath, context); Controller.DetailedState = $"Loading maps"; await Controller.WaitIfNecessary(); // Get the tilesets var tileSet_0000_shadow = LoadTileSet(rom.TileSet_0000, rom.TilePalette, false, true, animatedTiles: rom.AnimatedTiles, shadow: true); var tileSet_0000 = LoadTileSet(rom.TileSet_0000, rom.TilePalette, false, true, animatedTiles: rom.AnimatedTiles); var tileSet_8000 = LoadTileSet(rom.TileSet_8000, rom.TilePalette, true, false); // Load the primary map var map = LoadMap(rom.BG1_Map, rom.BG1_Tiles).Select(x => { x.TileMapY = (ushort)(x.PaletteIndex * tileSet_0000.SNES_BaseLength + x.TileMapY); return(new Unity_Tile(x)); }).ToArray(); var maps = new Unity_Map[] { // Background new Unity_Map() { Type = Unity_Map.MapType.Graphics, Width = 32, Height = 32, TileSet = new Unity_TileSet[] { tileSet_8000 }, MapTiles = rom.BG3_Tiles.Select(x => { x.TileMapY = (ushort)(x.PaletteIndex * tileSet_8000.SNES_BaseLength + x.TileMapY); return(new Unity_Tile(x)); }).ToArray(), }, // Map (no priority) new Unity_Map() { Type = Unity_Map.MapType.Graphics, Width = (ushort)(rom.BG1_Map.Width * 2), Height = (ushort)(rom.BG1_Map.Height * 2), TileSet = new Unity_TileSet[] { tileSet_0000 }, MapTiles = map.Select(x => x.Data.Priority ? new Unity_Tile(new MapTile()) : x).ToArray(), }, // Map (no priority) new Unity_Map() { Type = Unity_Map.MapType.Graphics, Width = (ushort)(rom.BG1_Map.Width * 2), Height = (ushort)(rom.BG1_Map.Height * 2), TileSet = new Unity_TileSet[] { tileSet_0000_shadow }, MapTiles = map.Select(x => x.Data.Priority ? x : new Unity_Tile(new MapTile())).ToArray(), }, // Map (priority) new Unity_Map() { Type = Unity_Map.MapType.Graphics, Width = (ushort)(rom.BG1_Map.Width * 2), Height = (ushort)(rom.BG1_Map.Height * 2), TileSet = new Unity_TileSet[] { tileSet_0000 }, MapTiles = map.Select(x => !x.Data.Priority ? new Unity_Tile(new MapTile()) : x).ToArray(), Layer = Unity_Map.MapLayer.Front, IsAdditive = true, Alpha = 1f }, // Foreground new Unity_Map() { Type = Unity_Map.MapType.Graphics, Width = 32, Height = 32, TileSet = new Unity_TileSet[] { tileSet_0000 }, MapTiles = rom.BG2_Tiles.Select(x => { x.TileMapY = (ushort)(x.PaletteIndex * tileSet_0000.SNES_BaseLength + x.TileMapY); return(new Unity_Tile(x)); }).ToArray(), Layer = Unity_Map.MapLayer.Front, }, // Collision new Unity_Map() { Type = Unity_Map.MapType.Collision, Width = rom.BG1_Map.Width, Height = rom.BG1_Map.Height, TileSet = new Unity_TileSet[0], MapTiles = rom.BG1_Map.Tiles.Select(x => new Unity_Tile(x)).ToArray() }, }; Controller.DetailedState = $"Loading sprites"; await Controller.WaitIfNecessary(); var objManager = new Unity_ObjectManager_SNES(context, GetGraphicsGroups(rom)); // Create Rayman var rayman = new Unity_Object_SNES(rom.Rayman, objManager); // Convert levelData to common level format return(new Unity_Level( maps: maps, objManager: objManager, getCollisionTypeNameFunc: x => ((R1Jaguar_TileCollisionType)x).ToString(), getCollisionTypeGraphicFunc: x => ((R1Jaguar_TileCollisionType)x).GetCollisionTypeGraphic(), rayman: rayman, cellSize: 8) { CellSizeOverrideCollision = 16 }); }
public override async UniTask <Unity_Level> LoadAsync(Context context, bool loadTextures) { if (GetLevelType(context) != LevelType.R3SinglePak) { return(await base.LoadAsync(context, loadTextures)); } Controller.DetailedState = $"Loading data"; await Controller.WaitIfNecessary(); // Get the rom var rom = FileFactory.Read <GBA_ROM>(GetROMFilePath(context), context); Controller.DetailedState = $"Loading background"; await Controller.WaitIfNecessary(); var pal = Util.ConvertGBAPalette(rom.R3SinglePak_Palette, transparentIndex: null); var tileSetTex = Util.ToTileSetTexture(rom.R3SinglePak_TileSet, pal, Util.TileEncoding.Linear_8bpp, CellSize, false); // Create the background map var map = new Unity_Map { Width = 32, Height = 32, TileSet = new Unity_TileSet[] { new Unity_TileSet(tileSetTex, CellSize), }, MapTiles = rom.R3SinglePak_TileMap.Select(x => new Unity_Tile(new MapTile() { TileMapY = x })).ToArray(), Type = Unity_Map.MapType.Graphics, }; Controller.DetailedState = $"Loading puppets"; await Controller.WaitIfNecessary(); // Create dummy actor models from the puppets, with one action for every animation var actorModels = rom.R3SinglePak_Puppets.Select((x, i) => new Unity_ObjectManager_GBA.ModelData( index: i, actions: Enumerable.Range(0, x.AnimationsCount).Select(animIndex => new GBA_Action() { AnimationIndex = (ushort)animIndex }).ToArray(), puppets: new Unity_ObjGraphics[] { GetCommonDesign(x, false, null, new GBA_Animation[0]) })).ToArray(); // Create an object manager var objManager = new Unity_ObjectManager_GBA(context, actorModels); // Create a single dummy game object var obj = new Unity_Object_GBA(new GBA_Actor() { Type = GBA_Actor.ActorType.Actor, ActorModel = new GBA_ActorModel(), XPos = 128, YPos = 128 }, objManager); // Return the level return(new Unity_Level( maps: new Unity_Map[] { map }, objManager: objManager, eventData: new List <Unity_Object>() { obj }, cellSize: CellSize)); }