Example #1
0
        /// <summary>
        /// Converts to the format
        /// </summary>
        /// <returns>The task</returns>
        public override async Task ConvertToAsync()
        {
            var attr     = GameModeSelection.SelectedValue.GetAttribute <OpenSpaceGameModeInfoAttribute>();
            var settings = OpenSpaceSettings.GetDefaultSettings(attr.Game, attr.Platform);

            await ConvertToAsync <OpenSpaceGFFile>(settings, (filePath, format) =>
            {
                // Create the GF data
                var gf = new OpenSpaceGFFile
                {
                    // Set the .gf format
                    GFPixelFormat = Enum.Parse(typeof(OpenSpaceGFFormat), format).CastTo <OpenSpaceGFFormat>()
                };

                // Read the image
                using var bmp = new Bitmap(filePath);

                // IDEA: If bmp is not in supported format, then convert it?

                // Import from the bitmap
                gf.ImportFromBitmap(settings, new RawBitmapData(bmp), RCPServices.Data.Archive_GF_GenerateMipmaps);

                // Return the data
                return(gf);
            }, new FileFilterItemCollection(ImageHelpers.GetSupportedBitmapExtensions().Select(x => new FileFilterItem($"*{x}",
                                                                                                                       x.Substring(1).ToUpper()))).ToString(), new FileExtension(".gf"), Enum.GetNames(typeof(OpenSpaceGFFormat)));
        }
 /// <summary>
 /// Default constructor
 /// </summary>
 /// <param name="fileEntry">The file data</param>
 /// <param name="settings">The settings when serializing the data</param>
 /// <param name="directory">The directory the file is located under</param>
 public OpenSpaceCntArchiveFileData(OpenSpaceCntFileEntry fileEntry, OpenSpaceSettings settings, string directory)
 {
     Directory = directory;
     FileEntry = fileEntry;
     FileName  = FileEntry.FileName;
     Settings  = settings;
 }
    /// <summary>
    /// Converts the file data from the specified format
    /// </summary>
    /// <param name="inputFormat">The format to convert from</param>
    /// <param name="outputFormat">The format to convert to</param>
    /// <param name="currentFileStream">The current file stream</param>
    /// <param name="inputStream">The input file data stream to convert from</param>
    /// <param name="outputStream">The output stream for the converted data</param>
    /// <param name="manager">The manager</param>
    public void ConvertFrom(FileExtension inputFormat, FileExtension outputFormat, ArchiveFileStream currentFileStream, ArchiveFileStream inputStream, ArchiveFileStream outputStream, IArchiveDataManager manager)
    {
        // Load the bitmap
        using Bitmap bmp = new(inputStream.Stream);

        // Load the current file
        GF gf = GetFileContent(currentFileStream, manager);

        // IDEA: If bmp is not in supported format, then convert it?

        RawBitmapData rawBitmapData;

        // Get the bitmap lock
        using (BitmapLock bmpLock = new(bmp))
        {
            // Get the raw bitmap data
            rawBitmapData = new RawBitmapData(bmp.Width, bmp.Height, bmpLock.Pixels, bmp.PixelFormat);

            // Force the new pixel format to be 888 or 8888 if set to do so
            if (Services.Data.Archive_GF_ForceGF8888Import)
            {
                gf.PixelFormat = gf.PixelFormat.SupportsTransparency() ? GF_Format.Format_32bpp_BGRA_8888 : GF_Format.Format_24bpp_BGR_888;
            }

            // Check if the format should be updated for transparency
            if (Services.Data.Archive_GF_UpdateTransparency != UserData_Archive_GF_TransparencyMode.PreserveFormat)
            {
                // NOTE: Only 24 and 32 bpp bitmaps are supported
                // Check if the imported file is transparent
                bool?isTransparent = bmp.PixelFormat switch
                {
                    PixelFormat.Format32bppArgb => (Services.Data.Archive_GF_UpdateTransparency == UserData_Archive_GF_TransparencyMode.UpdateBasedOnPixelFormat ||
                                                    bmpLock.UtilizesAlpha()),
                    PixelFormat.Format24bppRgb => false,
                    _ => null
                };

                // NOTE: Currently only supported for formats with 3 or 4 channels
                // Check if the format should be updated for transparency
                if (gf.Channels >= 3 && isTransparent != null)
                {
                    // Update the format
                    gf.PixelFormat = isTransparent.Value ? GF_Format.Format_32bpp_BGRA_8888 : GF_Format.Format_24bpp_BGR_888;
                }
            }
        }

        byte oldRepeatByte = gf.RepeatByte;

        OpenSpaceSettings settings = manager.Context !.GetSettings <OpenSpaceSettings>();

        // Import the bitmap
        gf.ImportFromBitmap(settings, rawBitmapData, Services.Data.Archive_GF_GenerateMipmaps);

        Logger.Debug("The repeat byte has been updated for a .gf file from {0} to {1}", oldRepeatByte, gf.RepeatByte);

        // Serialize the data to get the bytes
        manager.Context.WriteStreamData(outputStream.Stream, gf, name: outputStream.Name, leaveOpen: true);
    }
        /// <summary>
        /// Opens the archive explorer
        /// </summary>
        /// <returns>The task</returns>
        public async Task OpenAsync()
        {
            var attr     = GameMode.GetAttribute <OpenSpaceGameModeInfoAttribute>();
            var settings = OpenSpaceSettings.GetDefaultSettings(attr.Game, attr.Platform);

            // Show the archive explorer
            await RCPServices.UI.ShowArchiveExplorerAsync(new OpenSpaceCntArchiveExplorerDataManager(settings), ArchiveFiles.Where(x => x.FileExists));
        }
 /// <summary>
 /// Gets the file extension for the level data files
 /// </summary>
 /// <param name="gameSettings">The settings</param>
 /// <returns>The file extension</returns>
 protected string GetLevelFileExtension(OpenSpaceSettings gameSettings)
 {
     return(gameSettings.EngineVersion switch
     {
         OpenSpaceEngineVersion.Rayman2 => ".sna",
         OpenSpaceEngineVersion.Rayman3 => ".lvl",
         _ => throw new ArgumentOutOfRangeException(nameof(gameSettings.EngineVersion), gameSettings.EngineVersion, null)
     });
Example #6
0
        /// <summary>
        /// Imports an exported save slot to the save slot from the specified path
        /// </summary>
        /// <param name="inputFilePath">The input file path</param>
        /// <returns>The task</returns>
        protected override Task ImportSaveDataAsync(FileSystemPath inputFilePath)
        {
            // Deserialize the input data
            var data = JsonHelpers.DeserializeFromFile <RaymanMPCSaveData>(inputFilePath);

            // Import the data
            BinarySerializableHelpers.WriteToFile(data, SaveSlotFilePath, OpenSpaceSettings.GetDefaultSettings(OpenSpaceGame.RaymanM, Platform.PC), RCPServices.App.GetBinarySerializerLogger());

            return(Task.CompletedTask);
        }
Example #7
0
    /// <summary>
    /// Default constructor
    /// </summary>
    /// <param name="settings">The settings when serializing the data</param>
    public OpenSpaceCntArchiveDataManager(OpenSpaceSettings settings)
    {
        Settings = settings;

        Context = new RCPContext(String.Empty, new RCPSerializerSettings()
        {
            DefaultEndianness = settings.GetEndian
        });
        Context.AddSettings(settings);
    }
Example #8
0
        /// <summary>
        /// Converts to the format
        /// </summary>
        /// <returns>The task</returns>
        public override async Task ConvertToAsync()
        {
            var settings = OpenSpaceSettings.GetDefaultSettings(OpenSpaceGame.Rayman2, Platform.PC);

            await ConvertToAsync(settings, (filePath, format) =>
            {
                // Read the data
                return(DeserializeJSON <Rayman2PCConfigData>(filePath));
            }, new FileFilterItem("*.json", "JSON").ToString(), new FileExtension(".cfg"), null, new Rayman12PCSaveDataEncoder());
        }
        /// <summary>
        /// Converts to the format
        /// </summary>
        /// <returns>The task</returns>
        public override async Task ConvertToAsync()
        {
            var settings = OpenSpaceSettings.GetDefaultSettings(OpenSpaceGame.Rayman3, GameModeSelection.SelectedValue);

            await ConvertToAsync(settings, (filePath, format) =>
            {
                // Read the data
                return(DeserializeJSON <Rayman3PCSaveData>(filePath));
            }, new FileFilterItem("*.json", "JSON").ToString(), new FileExtension(".sav"), null, new Rayman3SaveDataEncoder());
        }
Example #10
0
        /// <summary>
        /// Converts to the format
        /// </summary>
        /// <returns>The task</returns>
        public override async Task ConvertToAsync()
        {
            var attr     = GameModeSelection.SelectedValue.GetAttribute <OpenSpaceGameModeInfoAttribute>();
            var settings = OpenSpaceSettings.GetDefaultSettings(attr.Game, attr.Platform);

            await ConvertToAsync(settings, (filePath, format) =>
            {
                // Read the data
                return(DeserializeJSON <RaymanMPCSaveData>(filePath));
            }, new FileFilterItem("*.json", "JSON").ToString(), new FileExtension(".sav"));
        }
    /// <summary>
    /// Synchronizes the texture info for the selected game data directory
    /// </summary>
    /// <returns>The task</returns>
    public async Task SyncTextureInfoAsync()
    {
        OpenSpaceGameModeInfoAttribute attr = GameModeSelection.SelectedValue.GetAttribute <OpenSpaceGameModeInfoAttribute>();

        DirectoryBrowserResult result = await Services.BrowseUI.BrowseDirectoryAsync(new DirectoryBrowserViewModel()
        {
            Title            = Resources.Utilities_SyncTextureInfo_SelectDirHeader,
            DefaultDirectory = attr.Game?.GetInstallDir(false) ?? FileSystemPath.EmptyPath
        });

        if (result.CanceledByUser)
        {
            return;
        }

        try
        {
            IsLoading = true;

            TextureInfoEditResult syncResult = await Task.Run(() =>
            {
                // Get the settings
                OpenSpaceSettings gameSettings = attr.GetSettings();

                // Get the file extension for the level data files
                var fileExt = GetLevelFileExtension(gameSettings);

                // Get the level data files
                var dataFiles = Directory.GetFiles(result.SelectedDirectory, $"*{fileExt}", SearchOption.AllDirectories).Select(x => new FileSystemPath(x));

                // Get the .cnt file names
                var fileNames = GetCntFileNames(gameSettings);

                // Get the full paths and only keep the ones which exist
                var cntFiles = fileNames.Select(x => result.SelectedDirectory + x).Where(x => x.FileExists);

                // Sync the texture info
                return(EditTextureInfo(gameSettings, dataFiles, cntFiles));
            });

            await Services.MessageUI.DisplaySuccessfulActionMessageAsync(String.Format(Resources.Utilities_SyncTextureInfo_Success, syncResult.EditedTextures, syncResult.TotalTextures));
        }
        catch (Exception ex)
        {
            Logger.Error(ex, "Syncing texture info");

            await Services.MessageUI.DisplayExceptionMessageAsync(ex, Resources.Utilities_SyncTextureInfo_Error);
        }
        finally
        {
            IsLoading = false;
        }
    }
        /// <summary>
        /// Converts from the format
        /// </summary>
        /// <returns>The task</returns>
        public override async Task ConvertFromAsync()
        {
            var settings = OpenSpaceSettings.GetDefaultSettings(OpenSpaceGame.Rayman3, GameModeSelection.SelectedValue);

            await ConvertFromAsync <Rayman3PCSaveData>(settings, (data, filePath) =>
            {
                // Save the data
                SerializeJSON(data, filePath);
            }, new FileFilterItem("*.sav", "SAV").ToString(), new[]
            {
                ".json"
            }, Games.Rayman3.GetInstallDir(false), new Rayman3SaveDataEncoder());
        }
Example #13
0
        /// <summary>
        /// Converts from the format
        /// </summary>
        /// <returns>The task</returns>
        public override async Task ConvertFromAsync()
        {
            var settings = OpenSpaceSettings.GetDefaultSettings(OpenSpaceGame.Rayman2, Platform.PC);

            await ConvertFromAsync <Rayman2PCConfigData>(settings, (data, filePath) =>
            {
                // Save the data
                SerializeJSON(data, filePath);
            }, new FileFilterItem("*.cfg", "CFG").ToString(), new[]
            {
                ".json"
            }, Games.Rayman2.GetInstallDir(false), new Rayman12PCSaveDataEncoder());
        }
Example #14
0
    /// <summary>
    /// Synchronizes the texture info for the selected game data directory
    /// </summary>
    /// <returns>The task</returns>
    public async Task SyncTextureInfoAsync()
    {
        try
        {
            IsLoading = true;

            TextureInfoEditResult syncResult = await Task.Run(() =>
            {
                // Get the game install directory
                FileSystemPath installDir = Game.GetInstallDir();

                // Get the settings
                OpenSpaceGameModeInfoAttribute attr = GameMode.GetAttribute <OpenSpaceGameModeInfoAttribute>();
                OpenSpaceSettings gameSettings      = attr.GetSettings();

                // Get the file extension for the level data files
                string fileExt = GetLevelFileExtension(gameSettings);

                // Get the level data files
                IEnumerable <FileSystemPath> dataFiles = GameDataDirNames.
                                                         Select(x => Directory.GetFiles(installDir + x, $"*{fileExt}", SearchOption.AllDirectories).
                                                                Select(y => new FileSystemPath(y))).
                                                         SelectMany(x => x);

                // Get the .cnt file names
                string[] fileNames = GetCntFileNames(gameSettings);

                // Get the full paths and only keep the ones which exist
                IEnumerable <FileSystemPath> cntFiles = GameDataDirNames.
                                                        Select(dataDir => fileNames.
                                                               Select(cnt => installDir + dataDir + cnt).
                                                               Where(cntPath => cntPath.FileExists)).
                                                        SelectMany(x => x);

                // Sync the texture info
                return(EditTextureInfo(gameSettings, dataFiles, cntFiles));
            });

            await Services.MessageUI.DisplaySuccessfulActionMessageAsync(String.Format(Resources.Utilities_SyncTextureInfo_Success, syncResult.EditedTextures, syncResult.TotalTextures));
        }
        catch (Exception ex)
        {
            Logger.Error(ex, "Syncing texture info");

            await Services.MessageUI.DisplayExceptionMessageAsync(ex, Resources.Utilities_SyncTextureInfo_Error);
        }
        finally
        {
            IsLoading = false;
        }
    }
Example #15
0
        /// <summary>
        /// Converts from the format
        /// </summary>
        /// <returns>The task</returns>
        public override async Task ConvertFromAsync()
        {
            var attr     = GameModeSelection.SelectedValue.GetAttribute <OpenSpaceGameModeInfoAttribute>();
            var settings = OpenSpaceSettings.GetDefaultSettings(attr.Game, attr.Platform);

            await ConvertFromAsync <RaymanMPCSaveData>(settings, (data, filePath) =>
            {
                // Save the data
                SerializeJSON(data, filePath);
            }, new FileFilterItem("*.sav", "SAV").ToString(), new[]
            {
                ".json"
            }, GameModeSelection.SelectedValue.GetGame()?.GetInstallDir(false));
        }
Example #16
0
        /// <summary>
        /// Converts from the format
        /// </summary>
        /// <returns>The task</returns>
        public override async Task ConvertFromAsync()
        {
            var attr     = GameModeSelection.SelectedValue.GetAttribute <OpenSpaceGameModeInfoAttribute>();
            var settings = OpenSpaceSettings.GetDefaultSettings(attr.Game, attr.Platform);

            await ConvertFromAsync <OpenSpaceGFFile>(settings, (data, filePath) =>
            {
                // Get a bitmap from the image data
                using var bmp = data.GetRawBitmapData().GetBitmap();

                // Save the image
                bmp.Save(filePath, ImageHelpers.GetImageFormat(filePath.FileExtension));
            }, new FileFilterItem("*.gf", "GF").ToString(), ImageHelpers.GetSupportedBitmapExtensions(), null);
        }
Example #17
0
        /// <summary>
        /// Imports an exported save slot to the save slot from the specified path
        /// </summary>
        /// <param name="inputFilePath">The input file path</param>
        /// <returns>The task</returns>
        protected override Task ImportSaveDataAsync(FileSystemPath inputFilePath)
        {
            // Deserialize the input data
            var data = JsonHelpers.DeserializeFromFile <Rayman3PCSaveData>(inputFilePath);

            // Create streams
            using var decodedDataStream = new MemoryStream();
            using var saveFileStream    = File.Create(SaveSlotFilePath);

            // Import the data
            BinarySerializableHelpers.WriteToStream(data, decodedDataStream, OpenSpaceSettings.GetDefaultSettings(OpenSpaceGame.Rayman3, Platform.PC), RCPServices.App.GetBinarySerializerLogger());

            // Set position to 0
            decodedDataStream.Position = 0;

            // Encode the data to the file
            new Rayman3SaveDataEncoder().Encode(decodedDataStream, saveFileStream);

            return(Task.CompletedTask);
        }
Example #18
0
        /// <summary>
        /// Get the progression slot view model for the save data from the specified file
        /// </summary>
        /// <param name="filePath">The slot file path</param>
        /// <param name="slotName">The generator for the name of the save slot</param>
        /// <returns>The progression slot view model</returns>
        protected ProgressionSlotViewModel GetProgressionSlotViewModel(FileSystemPath filePath, string slotName)
        {
            RL.Logger?.LogInformationSource($"Rayman 2 slot {slotName} is being loaded...");

            // Make sure the file exists
            if (!filePath.FileExists)
            {
                RL.Logger?.LogInformationSource($"Slot was not loaded due to not being found");

                return(null);
            }

            // Open the file in a stream
            using var fileStream = File.Open(filePath, FileMode.Open, FileAccess.Read);

            // Create a memory stream
            using var memStream = new MemoryStream();

            // Decode the data
            new Rayman12PCSaveDataEncoder().Decode(fileStream, memStream);

            // Set the position
            memStream.Position = 0;

            // Deserialize and return the data
            var saveData = BinarySerializableHelpers.ReadFromStream <Rayman2PCSaveData>(memStream, OpenSpaceSettings.GetDefaultSettings(OpenSpaceGame.Rayman2, Platform.PC), RCPServices.App.GetBinarySerializerLogger());

            RL.Logger?.LogInformationSource($"Slot has been deserialized");

            // Get the bit array
            var array = saveData.GlobalArrayAsBitFlags();

            // Get total amount of Lums and cages
            var lums =
                array.Skip(0).Take(800).Select(x => x ? 1 : 0).Sum() +
                array.Skip(1200).Take(194).Select(x => x ? 1 : 0).Sum() +
                // Woods of Light
                array.Skip(1395).Take(5).Select(x => x ? 1 : 0).Sum() +
                // 1000th Lum
                (array[1013] ? 1 : 0);

            var cages           = array.Skip(839).Take(80).Select(x => x ? 1 : 0).Sum();
            var walkOfLifeTime  = saveData.GlobalArray[12] * 10;
            var walkOfPowerTime = saveData.GlobalArray[11] * 10;

            // Create the collection with items for cages + lives
            var progressItems = new List <ProgressionInfoItemViewModel>
            {
                new ProgressionInfoItemViewModel(ProgressionIcons.R2_Lum, new LocalizedString(() => $"{lums}/1000")),
                new ProgressionInfoItemViewModel(ProgressionIcons.R2_Cage, new LocalizedString(() => $"{cages}/80")),
            };

            if (walkOfLifeTime > 120)
            {
                progressItems.Add(new ProgressionInfoItemViewModel(ProgressionIcons.R2_Clock, new LocalizedString(() => $"{new TimeSpan(0, 0, 0, 0, walkOfLifeTime):mm\\:ss\\:ff}"), new LocalizedString(() => Resources.R2_BonusLevelName_1)));
            }

            if (walkOfPowerTime > 120)
            {
                progressItems.Add(new ProgressionInfoItemViewModel(ProgressionIcons.R2_Clock, new LocalizedString(() => $"{new TimeSpan(0, 0, 0, 0, walkOfPowerTime):mm\\:ss\\:ff}"), new LocalizedString(() => Resources.R2_BonusLevelName_2)));
            }

            RL.Logger?.LogInformationSource($"General progress info has been set");

            // Get the name and percentage
            var separatorIndex = slotName.LastIndexOf((char)0x20);
            var name           = slotName.Substring(0, separatorIndex);
            var percentage     = slotName.Substring(separatorIndex + 1);

            RL.Logger?.LogInformationSource($"Slot percentage is {percentage}%");

            // Return the data with the collection
            return(new Rayman2ProgressionSlotViewModel(new LocalizedString(() => $"{name} ({percentage}%)"), progressItems.ToArray(), filePath, this));
        }
Example #19
0
        /// <summary>
        /// Loads the current save data if available
        /// </summary>
        protected override void LoadData()
        {
            // Make sure the file exists
            if (!ConfigFilePath.FileExists)
            {
                return;
            }

            // Create streams
            using var saveFileStream    = File.OpenRead(ConfigFilePath);
            using var decodedDataStream = new MemoryStream();

            // Decode the save file
            new Rayman12PCSaveDataEncoder().Decode(saveFileStream, decodedDataStream);

            // Set position to 0
            decodedDataStream.Position = 0;

            // Get the serialized data
            var config = BinarySerializableHelpers.ReadFromStream <Rayman2PCConfigData>(decodedDataStream, OpenSpaceSettings.GetDefaultSettings(OpenSpaceGame.Rayman2, Platform.PC), RCPServices.App.GetBinarySerializerLogger());

            // Read and set slot data
            ProgressionSlots.AddRange(config.Slots.Select(x => GetProgressionSlotViewModel(SaveGamePath + $"Slot{x.SlotIndex}" + "General.sav", x.SlotDisplayName)));
        }
 /// <summary>
 /// Default constructor
 /// </summary>
 /// <param name="settings">The settings when serializing the data</param>
 protected BaseOpenSpaceCntArchiveDataManager(OpenSpaceSettings settings)
 {
     Settings = settings;
 }
Example #21
0
        /// <summary>
        /// Exports the save slot from the specified path
        /// </summary>
        /// <param name="outputFilePath">The output file path</param>
        /// <returns>The task</returns>
        protected override Task ExportSaveDataAsync(FileSystemPath outputFilePath)
        {
            // Create streams
            using var saveFileStream    = File.OpenRead(SaveSlotFilePath);
            using var decodedDataStream = new MemoryStream();

            // Decode the save file
            new Rayman3SaveDataEncoder().Decode(saveFileStream, decodedDataStream);

            // Set position to 0
            decodedDataStream.Position = 0;

            // Get the serialized data
            var data = BinarySerializableHelpers.ReadFromStream <Rayman3PCSaveData>(decodedDataStream, OpenSpaceSettings.GetDefaultSettings(OpenSpaceGame.Rayman3, Platform.PC), RCPServices.App.GetBinarySerializerLogger());

            // Export the data
            JsonHelpers.SerializeToFile(data, outputFilePath);

            return(Task.CompletedTask);
        }
Example #22
0
        /// <summary>
        /// Get the progression slot view models for the save data from the specified file
        /// </summary>
        /// <param name="filePath">The slot file path</param>
        /// <returns>The progression slot view models</returns>
        protected IEnumerable <ProgressionSlotViewModel> GetProgressionSlotViewModels(FileSystemPath filePath)
        {
            RL.Logger?.LogInformationSource($"Rayman M/Arena save file {filePath.Name} is being loaded...");

            // Make sure the file exists
            if (!filePath.FileExists)
            {
                RL.Logger?.LogInformationSource($"Slot was not loaded due to not being found");

                yield break;
            }

            // Deserialize the save data
            var saveData = BinarySerializableHelpers.ReadFromFile <RaymanMPCSaveData>(filePath, OpenSpaceSettings.GetDefaultSettings(OpenSpaceGame.RaymanM, Platform.PC), RCPServices.App.GetBinarySerializerLogger());

            RL.Logger?.LogInformationSource($"Save file has been deserialized");

            // Helper for getting the entry with a specific key
            int[] GetValues(string key) => saveData.Items.First(x => x.Key == key).Values;
Example #23
0
        /// <summary>
        /// Exports the save slot from the specified path
        /// </summary>
        /// <param name="outputFilePath">The output file path</param>
        /// <returns>The task</returns>
        protected override Task ExportSaveDataAsync(FileSystemPath outputFilePath)
        {
            // Get the serialized data
            var data = BinarySerializableHelpers.ReadFromFile <RaymanMPCSaveData>(SaveSlotFilePath, OpenSpaceSettings.GetDefaultSettings(OpenSpaceGame.RaymanM, Platform.PC), RCPServices.App.GetBinarySerializerLogger());

            // Export the data
            JsonHelpers.SerializeToFile(data, outputFilePath);

            return(Task.CompletedTask);
        }
 /// <summary>
 /// Default constructor
 /// </summary>
 /// <param name="settings">The settings when serializing the data</param>
 public OpenSpaceCntArchiveExplorerDataManager(OpenSpaceSettings settings) : base(settings)
 {
 }
Example #25
0
        /// <summary>
        /// Get the progression slot view model for the save data from the specified file
        /// </summary>
        /// <param name="filePath">The slot file path</param>
        /// <returns>The progression slot view model</returns>
        protected ProgressionSlotViewModel GetProgressionSlotViewModel(FileSystemPath filePath)
        {
            RL.Logger?.LogInformationSource($"Rayman 3 slot {filePath.Name} is being loaded...");

            // Make sure the file exists
            if (!filePath.FileExists)
            {
                RL.Logger?.LogInformationSource($"Slot was not loaded due to not being found");

                return(null);
            }

            // Open the file in a stream
            using var fileStream = File.Open(filePath, FileMode.Open, FileAccess.Read);

            // Create a memory stream
            using var memStream = new MemoryStream();

            // Decode the data
            new Rayman3SaveDataEncoder().Decode(fileStream, memStream);

            // Set the position
            memStream.Position = 0;

            // Deserialize the data
            var saveData = BinarySerializableHelpers.ReadFromStream <Rayman3PCSaveData>(memStream, OpenSpaceSettings.GetDefaultSettings(OpenSpaceGame.Rayman3, Platform.PC), RCPServices.App.GetBinarySerializerLogger());

            RL.Logger?.LogInformationSource($"Slot has been deserialized");

            var formatInfo = new NumberFormatInfo()
            {
                NumberGroupSeparator = " ",
                NumberDecimalDigits  = 0
            };

            // Create the collection with items for each level + general information
            var progressItems = new ProgressionInfoItemViewModel[]
            {
                new ProgressionInfoItemViewModel(ProgressionIcons.R3_Cage, new LocalizedString(() => $"{saveData.TotalCages}/60")),
                new ProgressionInfoItemViewModel(ProgressionIcons.R3_Score, new LocalizedString(() => $"{Resources.Progression_R3_TotalHeader}: {saveData.TotalScore.ToString("n", formatInfo)}")),
                new ProgressionInfoItemViewModel(ProgressionIcons.R3_Score, new LocalizedString(() => $"{Resources.Progression_R3_Level1Header}: {saveData.Levels[0].Score.ToString("n", formatInfo)}")),
                new ProgressionInfoItemViewModel(ProgressionIcons.R3_Score, new LocalizedString(() => $"{Resources.Progression_R3_Level2Header}: {saveData.Levels[1].Score.ToString("n", formatInfo)}")),
                new ProgressionInfoItemViewModel(ProgressionIcons.R3_Score, new LocalizedString(() => $"{Resources.Progression_R3_Level3Header}: {saveData.Levels[2].Score.ToString("n", formatInfo)}")),
                new ProgressionInfoItemViewModel(ProgressionIcons.R3_Score, new LocalizedString(() => $"{Resources.Progression_R3_Level4Header}: {saveData.Levels[3].Score.ToString("n", formatInfo)}")),
                new ProgressionInfoItemViewModel(ProgressionIcons.R3_Score, new LocalizedString(() => $"{Resources.Progression_R3_Level5Header}: {saveData.Levels[4].Score.ToString("n", formatInfo)}")),
                new ProgressionInfoItemViewModel(ProgressionIcons.R3_Score, new LocalizedString(() => $"{Resources.Progression_R3_Level6Header}: {saveData.Levels[5].Score.ToString("n", formatInfo)}")),
                new ProgressionInfoItemViewModel(ProgressionIcons.R3_Score, new LocalizedString(() => $"{Resources.Progression_R3_Level7Header}: {saveData.Levels[6].Score.ToString("n", formatInfo)}")),
                new ProgressionInfoItemViewModel(ProgressionIcons.R3_Score, new LocalizedString(() => $"{Resources.Progression_R3_Level8Header}: {saveData.Levels[7].Score.ToString("n", formatInfo)}")),
                new ProgressionInfoItemViewModel(ProgressionIcons.R3_Score, new LocalizedString(() => $"{Resources.Progression_R3_Level9Header}: {saveData.Levels[8].Score.ToString("n", formatInfo)}"))
            };

            RL.Logger?.LogInformationSource($"General progress info has been set");

            // Return the data with the collection
            return(new Rayman3ProgressionSlotViewModel(new LocalizedString(() => $"{filePath.RemoveFileExtension().Name}"), progressItems, filePath, this));
        }
    /// <summary>
    /// Imports a bitmap image into the file, keeping the structure based on the properties and generating mipmaps if needed. This will reset the mipmaps, requiring them to be generated again.
    /// </summary>
    /// <param name="gf">The GF file data</param>
    /// <param name="settings">The serializer settings</param>
    /// <param name="bmp">The bitmap data to import from</param>
    /// <param name="generateMipmaps">Indicates if mipmaps should be generated for the image</param>
    public static void ImportFromBitmap(this GF gf, OpenSpaceSettings settings, RawBitmapData bmp, bool generateMipmaps)
    {
        // Helper method for writing the pixel data
        void WritePixelData(RawBitmapData bitmapData, long offset)
        {
            // Make sure the pixel format is supported
            if (bitmapData.PixelFormat != PixelFormat.Format32bppArgb && bitmapData.PixelFormat != PixelFormat.Format24bppRgb)
            {
                throw new Exception($"The bitmap pixel format {bitmapData.PixelFormat} is not supported for importing");
            }

            // Get the number of bitmap channels
            int bmpChannels = Image.GetPixelFormatSize(bitmapData.PixelFormat) / 8;

            // Get the format
            GF_Format format = gf.PixelFormat;

            byte[] bmpColorData = new byte[4];

            for (uint y = 0; y < bitmapData.Height; y++)
            {
                for (uint x = 0; x < bitmapData.Width; x++)
                {
                    // Get the offsets for the pixel colors
                    var pixelOffset = (bitmapData.Width * y + x) * gf.Channels + offset;

                    // NOTE: We reverse the Y-axis here since the .gf images are always flipper vertically
                    var rawOffset = (bitmapData.Width * (bitmapData.Height - y - 1) + x) * bmpChannels;

                    // Get the bitmap color bytes for this pixel
                    bmpColorData[0] = bitmapData.PixelData[rawOffset + 0];
                    bmpColorData[1] = bitmapData.PixelData[rawOffset + 1];
                    bmpColorData[2] = bitmapData.PixelData[rawOffset + 2];
                    bmpColorData[3] = bmpChannels == 4 ? bitmapData.PixelData[rawOffset + 3] : (byte)255;

                    // Get the pixels
                    foreach (var b in gf.GetGfPixelBytes(format, bmpColorData))
                    {
                        gf.PixelData[pixelOffset] = b;
                        pixelOffset++;
                    }
                }
            }
        }

        // Set size
        gf.Width  = bmp.Width;
        gf.Height = bmp.Height;

        // Set the pixel count
        gf.PixelCount = gf.Width * gf.Height;

        // Update the mipmap count
        if (generateMipmaps && gf.SupportsMipmaps(settings))
        {
            gf.MipmapsCount = gf.DeterminePreferredMipmapsCount();
        }
        else
        {
            gf.MipmapsCount = 0;
        }

        // Enumerate each mipmap size
        foreach ((int Width, int Height)size in gf.GetExclusiveMipmapSizes())
        {
            // Get the mipmap pixel count
            var count = size.Width * size.Height;

            // Add to the total pixel count
            gf.PixelCount += count;
        }

        // Create the data array
        gf.PixelData = new byte[gf.Channels * gf.PixelCount];

        // Set the main pixel data
        WritePixelData(bmp, 0);

        // Keep track of the offset
        long mipmapOffset = gf.Width * gf.Height * gf.Channels;

        // Generate mipmaps if available
        if (gf.ExclusiveMipmapCount > 0)
        {
            // Get the bitmap
            using Bitmap bitmap = bmp.GetBitmap();

            // Generate every mipmap
            foreach ((int Width, int Height)size in gf.GetExclusiveMipmapSizes())
            {
                // Resize the bitmap
                using Bitmap resizedBmp = bitmap.ResizeImage(size.Width, size.Height, false);

                // Write the mipmap
                WritePixelData(new RawBitmapData(resizedBmp), mipmapOffset);

                // Increase the index
                mipmapOffset += size.Height * size.Width * gf.Channels;
            }
        }

        // Update the repeat byte
        gf.UpdateRepeatByte();
    }
Example #27
0
 /// <summary>
 /// Default constructor
 /// </summary>
 /// <param name="settings">The settings when serializing the data</param>
 public OpenSpaceCntArchiveCreatorDataManager(OpenSpaceSettings settings) : base(settings)
 {
 }