├── .gitattributes ├── .github └── workflows │ └── build.yml ├── .gitignore ├── .gitmodules ├── Docs ├── Images │ ├── l1.png │ ├── l2.png │ ├── l3.png │ └── window.png └── Localization.md ├── README.md ├── Tools ├── Extractor │ ├── Extractor.csproj │ ├── GameFile.cs │ ├── Program.cs │ └── Properties │ │ └── launchSettings.json ├── LiveMusicPlayerCli │ ├── AssetTables.cs │ ├── CharaTrack.cs │ ├── LiveBuilder.cs │ ├── LiveMusicPlayerCli.csproj │ ├── PanSampleProvider.cs │ ├── PartTrigger.cs │ ├── Program.cs │ └── SongMixer.cs ├── PlayerCli │ ├── GameFile.cs │ ├── HcaWaveStream.cs │ ├── PlayerCli.csproj │ ├── Program.cs │ └── UmaWaveStream.cs └── SqlCreateStatementToClass │ ├── Program.cs │ └── SqlCreateStatementToClass.csproj ├── UmaMusumeAudio ├── HcaWaveStream.cs ├── UmaMusumeAudio.csproj └── UmaWaveStream.cs ├── UmaMusumeData ├── AssetBundleGroup.cs ├── ManifestEntry.cs ├── ManifestEntryKind.cs ├── Tables │ ├── AvailableSkillSet.cs │ ├── CardData.cs │ ├── CardRarityData.cs │ ├── CharaData.cs │ ├── CharacterSystemText.cs │ ├── GachaAvailable.cs │ ├── JukeboxMusicData.cs │ ├── LiveData.cs │ ├── LivePermissionData.cs │ ├── RaceBgm.cs │ ├── RaceBgmPattern.cs │ ├── SingleModeSkillNeedPoint.cs │ ├── SkillData.cs │ ├── SkillSet.cs │ ├── SkillUpgradeCondition.cs │ ├── SkillUpgradeDescription.cs │ ├── SupportCardData.cs │ └── TextData.cs ├── TextCategory.cs ├── UmaDataHelper.cs └── UmaMusumeData.csproj ├── UmaMusumeExplorer.sln └── UmaMusumeExplorer ├── Controls ├── AudioPlayer │ ├── AudioPlayerControl.Designer.cs │ ├── AudioPlayerControl.cs │ ├── AudioPlayerControl.resx │ ├── Classes │ │ ├── AtomAudioSource.cs │ │ ├── AtomAudioTrack.cs │ │ ├── AudioSource.cs │ │ ├── IAudioTrack.cs │ │ └── TrackComboBoxItem.cs │ ├── ConfigureLoopForm.Designer.cs │ ├── ConfigureLoopForm.cs │ ├── ConfigureLoopForm.resx │ ├── MultipleExportDialog.Designer.cs │ ├── MultipleExportDialog.cs │ └── MultipleExportDialog.resx ├── CharacterInfo │ ├── CardInfoControl.Designer.cs │ ├── CardInfoControl.cs │ ├── CardInfoControl.resx │ ├── CharacterInfoControl.Designer.cs │ ├── CharacterInfoControl.cs │ ├── CharacterInfoControl.resx │ ├── CharacterInfoForm.Designer.cs │ ├── CharacterInfoForm.cs │ ├── CharacterInfoForm.resx │ ├── CharacterVoiceListItemControl.Designer.cs │ ├── CharacterVoiceListItemControl.cs │ ├── CharacterVoiceListItemControl.resx │ ├── CircleControl.cs │ ├── Classes │ │ ├── CharaComboBoxItem.cs │ │ ├── CostumeComboBoxItem.cs │ │ ├── Rank.cs │ │ ├── RarityComboBoxItem.cs │ │ ├── SkillBackground.cs │ │ └── SkillColorGenerator.cs │ ├── DoubleBufferedTableLayoutPanel.cs │ ├── ProgressLabel.cs │ ├── ProgressLabel.resx │ ├── RankedLabel.Designer.cs │ ├── RankedLabel.cs │ ├── RankedLabel.resx │ ├── SkillEvolutionConditionContainer.Designer.cs │ ├── SkillEvolutionConditionContainer.cs │ ├── SkillEvolutionConditionContainer.resx │ ├── SkillEvolutionConditionItem.Designer.cs │ ├── SkillEvolutionConditionItem.cs │ ├── SkillEvolutionConditionItem.resx │ ├── SkillEvolutionDetailsForm.Designer.cs │ ├── SkillEvolutionDetailsForm.cs │ ├── SkillEvolutionDetailsForm.resx │ ├── SkillInfoForm.Designer.cs │ ├── SkillInfoForm.cs │ ├── SkillInfoForm.resx │ ├── SkillLarge.Designer.cs │ ├── SkillLarge.cs │ ├── SkillLarge.resx │ ├── SkillSmall.Designer.cs │ ├── SkillSmall.cs │ ├── SkillSmall.resx │ ├── SongsControl.Designer.cs │ ├── SongsControl.cs │ ├── SongsControl.resx │ ├── StatusDisplayLabel.Designer.cs │ ├── StatusDisplayLabel.cs │ ├── StatusDisplayLabel.resx │ ├── SupportCardsControl.Designer.cs │ ├── SupportCardsControl.cs │ ├── SupportCardsControl.resx │ ├── VoiceLinesControl.Designer.cs │ ├── VoiceLinesControl.cs │ └── VoiceLinesControl.resx ├── Common │ ├── CharacterItemsPanel.cs │ ├── CharacterPositionControl.Designer.cs │ ├── CharacterPositionControl.cs │ ├── CharacterPositionControl.resx │ ├── CharacterSelectForm.Designer.cs │ ├── CharacterSelectForm.cs │ ├── CharacterSelectForm.resx │ ├── Classes │ │ ├── CharaTrack.cs │ │ ├── CharacterPosition.cs │ │ ├── CsvReader.cs │ │ ├── ExtendedSampleProvider.cs │ │ ├── FormAnimator.cs │ │ ├── IExtendedSampleProvider.cs │ │ ├── LiveConfigurationManager.cs │ │ ├── LivePermissionDataHelper.cs │ │ ├── LyricsTrigger.cs │ │ ├── MusicManager.cs │ │ ├── PanSampleProvider.cs │ │ ├── PartTrigger.cs │ │ ├── SongLength.cs │ │ └── SongMixer.cs │ ├── HighQualityPictureBox.cs │ ├── HighlightPictureBox.cs │ ├── ItemsPanel.cs │ ├── PlayerForm.Designer.cs │ ├── PlayerForm.cs │ ├── PlayerForm.resx │ ├── SongItemsPanel.cs │ ├── UnitSetupForm.Designer.cs │ ├── UnitSetupForm.cs │ └── UnitSetupForm.resx ├── ControlHelpers.cs ├── FileBrowser │ ├── FileBrowserControl.Designer.cs │ ├── FileBrowserControl.cs │ └── FileBrowserControl.resx ├── Jukebox │ ├── JukeboxControl.Designer.cs │ ├── JukeboxControl.cs │ ├── JukeboxControl.resx │ └── JukeboxItemsPanel.cs ├── LiveMusicPlayer │ ├── DownloadWorkaroundForm.Designer.cs │ ├── DownloadWorkaroundForm.cs │ ├── DownloadWorkaroundForm.resx │ ├── LiveMusicPlayerControl.Designer.cs │ ├── LiveMusicPlayerControl.cs │ └── LiveMusicPlayerControl.resx ├── LoadingProgress.cs ├── RaceMusicPlayer │ ├── Classes │ │ ├── AutoRemoveMixingSampleProvider.cs │ │ ├── Bgm.cs │ │ ├── BgmComboBoxItem.cs │ │ ├── FadeInOutEventSampleProvider.cs │ │ ├── IEventSampleProvider.cs │ │ ├── Pattern.cs │ │ └── TestRunningBgmSampleProvider.cs │ ├── RaceMusicPlayerControl.Designer.cs │ ├── RaceMusicPlayerControl.cs │ └── RaceMusicPlayerControl.resx └── SupportCardInfo │ ├── SupportCardInfoControl.Designer.cs │ ├── SupportCardInfoControl.cs │ ├── SupportCardInfoControl.resx │ └── SupportCardItemsPanel.cs ├── Game ├── AssetTables.cs ├── ImagePointerContainer.cs ├── LoadingForm.Designer.cs ├── LoadingForm.cs ├── LoadingForm.resx ├── PinnedBitmap.cs └── UnityAssets.cs ├── MainForm.Designer.cs ├── MainForm.cs ├── MainForm.resx ├── Program.cs ├── Properties ├── Resources.Designer.cs └── Resources.resx ├── Resources ├── FileIcon.ico ├── FolderIcon.ico └── ProgramIcon.ico ├── SplashForm.Designer.cs ├── SplashForm.cs ├── SplashForm.resx ├── UmaApplicationContext.cs └── UmaMusumeExplorer.csproj /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: [ "master" ] 6 | pull_request: 7 | branches: [ "master" ] 8 | workflow_dispatch: 9 | jobs: 10 | build: 11 | runs-on: windows-latest 12 | steps: 13 | - name: Checkout branch and submodules 14 | uses: actions/checkout@v4.2.2 15 | with: 16 | submodules: 'recursive' 17 | - name: Setup MSBuild 18 | uses: microsoft/setup-msbuild@v2 19 | with: 20 | msbuild-architecture: x64 21 | - name: Generate AssetsTools.NET texture decoder CMake config 22 | run: cmake -S .\AssetsTools.NET -B .\AssetsTools.NET\build 23 | - name: Build AssetsTools.NET texture decoder 24 | run: cmake --build .\AssetsTools.NET\build 25 | - name: Build .NET project 26 | run: dotnet publish .\UmaMusumeExplorer --no-self-contained -r win-x64 -c Release -p:PublishSingleFile=true 27 | - name: Zip up files 28 | run: Compress-Archive .\UmaMusumeExplorer\bin\Release\net8.0-windows\win-x64\publish\* build-win-x64.zip 29 | - name: Upload build artifact 30 | uses: actions/upload-artifact@v4.4.3 31 | with: 32 | name: build-win-x64 33 | path: .\UmaMusumeExplorer\bin\Release\net8.0-windows\win-x64\publish\ 34 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "ClHcaSharp"] 2 | path = ClHcaSharp 3 | url = https://github.com/MarshmallowAndroid/ClHcaSharp 4 | [submodule "CriWareTools"] 5 | path = CriWareTools 6 | url = https://github.com/MarshmallowAndroid/CriWareTools 7 | [submodule "CriWareLibrary"] 8 | path = CriWareLibrary 9 | url = https://github.com/MarshmallowAndroid/CriWareLibrary 10 | [submodule "AssetsTools.NET"] 11 | path = AssetsTools.NET 12 | url = https://github.com/nesrak1/AssetsTools.NET.git 13 | -------------------------------------------------------------------------------- /Docs/Images/l1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarshmallowAndroid/UmaMusumeExplorer/52e8001492235d85a40e3731eb53143d2ca1596b/Docs/Images/l1.png -------------------------------------------------------------------------------- /Docs/Images/l2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarshmallowAndroid/UmaMusumeExplorer/52e8001492235d85a40e3731eb53143d2ca1596b/Docs/Images/l2.png -------------------------------------------------------------------------------- /Docs/Images/l3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarshmallowAndroid/UmaMusumeExplorer/52e8001492235d85a40e3731eb53143d2ca1596b/Docs/Images/l3.png -------------------------------------------------------------------------------- /Docs/Images/window.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarshmallowAndroid/UmaMusumeExplorer/52e8001492235d85a40e3731eb53143d2ca1596b/Docs/Images/window.png -------------------------------------------------------------------------------- /Docs/Localization.md: -------------------------------------------------------------------------------- 1 | # Localization 2 | This project is built on Windows Forms, which has support for localization built into the 3 | Visual Studio designer via different resource (`.resx`) files for each language. 4 | 5 | To generate localized resources for a form or user control: 6 | 7 | 1. In your forked repository, open the form in the designer and check if `Localizable` is set to `True` 8 | 9 | ![](Images/l1.png) 10 | 2. Set the `Language` property to the language you want to localize the form in 11 | 12 | ![](Images/l2.png) 13 | 3. Change the text properties of the controls to your localized text 14 | 15 | ![](Images/l3.png) 16 | 17 | Commit the changes of the resource files (or the designer code in some cases) and make a new pull request. 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Uma Musume Explorer 2 | [![CI](https://github.com/MarshmallowAndroid/UmaMusumeExplorer/actions/workflows/build.yml/badge.svg?branch=master)](https://github.com/MarshmallowAndroid/UmaMusumeExplorer/actions/workflows/build.yml) 3 | 4 | A GUI utility for viewing certain assets from the game ウマ娘 プリティーダービー (Uma Musume Pretty Derby) developed by Cygames, Inc. 5 | 6 | DISCLAIMER: You must have your own installation of the game from DMM Games to use this utility. 7 | Game data such as stats is not modified in any way, and can be viewed with any SQLite database viewer. 8 | 9 | ## Functions included 10 | 11 | * File browser with search and export 12 | * Audio player with export 13 | * Live music player with export 14 | * Access more options by right clicking the window 15 | * Race music simulator 16 | * Character info 17 | * 5 main stats (speed, stamina, etc.) for each costume and its rarity 18 | * Skill view 19 | 20 | ![File browser](Docs/Images/window.png) 21 | 22 | ## Credits 23 | 24 | * [sqlite-net](https://github.com/praeclarum/sqlite-net) for SQLite functionality 25 | * [vgmstream](https://github.com/vgmstream/vgmstream) for the CRIWARE code 26 | * [AssetsTools.NET](https://github.com/nesrak1/AssetsTools.NET) for reading Unity assets 27 | -------------------------------------------------------------------------------- /Tools/Extractor/Extractor.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | Extractor.Program 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /Tools/Extractor/GameFile.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using SQLite; 7 | 8 | namespace Extractor 9 | { 10 | [Table("a")] 11 | public class GameFile 12 | { 13 | [PrimaryKey] 14 | [Column("i")] 15 | public int Id { get; set; } 16 | 17 | [Column("n"), NotNull] 18 | public string Name { get; set; } 19 | 20 | [Column("l"), NotNull] 21 | public string Length { get; set; } 22 | 23 | [Column("h"), NotNull] 24 | public string Hash { get; set; } 25 | 26 | [Column("m")] 27 | public string Category { get; set; } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Tools/Extractor/Program.cs: -------------------------------------------------------------------------------- 1 | using SQLite; 2 | using System; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace Extractor 8 | { 9 | class Program 10 | { 11 | static void Main(string[] args) 12 | { 13 | if (args.Length >= 1) 14 | { 15 | string localLow = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "AppData", "LocalLow"); 16 | string umaMusumeDirectory = Path.Combine(localLow, "Cygames", "umamusume"); 17 | 18 | SQLiteConnection connection = new(Path.Combine(umaMusumeDirectory, "meta")); 19 | string dataDirectory = Path.Combine(umaMusumeDirectory, "dat"); 20 | string outputDirectory = args[0]; 21 | 22 | var realFiles = Directory.GetFiles(dataDirectory, "*", SearchOption.AllDirectories).ToList(); 23 | var gameFiles = connection.Table().ToList(); 24 | gameFiles.Sort((gf1, gf2) => { return string.Compare(gf1.Name, gf2.Name); }); 25 | 26 | int total = gameFiles.Count; 27 | int finished = 0; 28 | 29 | object finishedLock = new(); 30 | 31 | Task[] copyTasks = new Task[total]; 32 | int index = 0; 33 | foreach (var gameFile in gameFiles) 34 | { 35 | copyTasks[index] = new Task(() => 36 | { 37 | string dataFileName = gameFile.Hash; 38 | string dataFilePath = Path.Combine(dataDirectory, dataFileName[..2], dataFileName); 39 | string realFileName = gameFile.Name.TrimStart('/'); 40 | if (gameFile.Category.StartsWith("manifest")) realFileName += ".manifest"; 41 | string realFilePath = Path.Combine(outputDirectory, realFileName); 42 | string destinationDirectory; 43 | 44 | if (!string.IsNullOrEmpty(Path.GetDirectoryName(realFileName))) 45 | destinationDirectory = Path.Combine(outputDirectory, Path.GetDirectoryName(realFileName)); 46 | else destinationDirectory = outputDirectory; 47 | 48 | Directory.CreateDirectory(destinationDirectory); 49 | 50 | if (!File.Exists(realFilePath) && File.Exists(dataFilePath)) File.Copy(dataFilePath, realFilePath); 51 | 52 | lock (finishedLock) 53 | { 54 | finished++; 55 | Console.CursorTop = 0; 56 | Console.CursorLeft = 0; 57 | Console.WriteLine($"Copying {((float)finished / total) * 100.0f:f2}% complete"); 58 | } 59 | }); 60 | copyTasks[index].Start(); 61 | 62 | index++; 63 | } 64 | 65 | Task.WaitAll(copyTasks); 66 | } 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /Tools/Extractor/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "Extractor": { 4 | "commandName": "Project", 5 | "commandLineArgs": "D:\\umamusume_" 6 | } 7 | } 8 | } -------------------------------------------------------------------------------- /Tools/LiveMusicPlayerCli/AssetTables.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using UmaMusumeData; 7 | using UmaMusumeData.Tables; 8 | 9 | namespace LiveMusicPlayerCli 10 | { 11 | internal static class AssetTables 12 | { 13 | public static IEnumerable AudioAssetEntries { get; } = UmaDataHelper.GetManifestEntries(ga => ga.Name.StartsWith("sound/")); 14 | 15 | public static IEnumerable CharaNameTextDatas { get; } = UmaDataHelper.GetMasterDatabaseRows(td => td.Category == 170); 16 | public static IEnumerable CharaNameKatakanaTextDatas { get; } = UmaDataHelper.GetMasterDatabaseRows(td => td.Category == 182); 17 | public static IEnumerable CharaVoiceNameTextDatas { get; } = UmaDataHelper.GetMasterDatabaseRows(td => td.Category == 7); 18 | public static IEnumerable CharaCostumeNameTextDatas { get; } = UmaDataHelper.GetMasterDatabaseRows(td => td.Category == 5); 19 | 20 | public static IEnumerable LiveDatas { get; } = UmaDataHelper.GetMasterDatabaseRows(); 21 | public static IEnumerable LivePermissionDatas { get; } = UmaDataHelper.GetMasterDatabaseRows(); 22 | 23 | public static IEnumerable LiveNameTextDatas { get; } = UmaDataHelper.GetMasterDatabaseRows(td => td.Category == 16); 24 | public static IEnumerable LiveInfoTextDatas { get; } = UmaDataHelper.GetMasterDatabaseRows(td => td.Category == 17); 25 | 26 | public static string GetText(IEnumerable textDatas, int index) 27 | { 28 | return textDatas.First(td => td.Index == index).Text; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Tools/LiveMusicPlayerCli/LiveMusicPlayerCli.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /Tools/LiveMusicPlayerCli/PanSampleProvider.cs: -------------------------------------------------------------------------------- 1 | using NAudio.Wave; 2 | using System; 3 | 4 | namespace LiveMusicPlayerCli 5 | { 6 | class PanSampleProvider : ISampleProvider 7 | { 8 | private readonly ISampleProvider sampleProvider; 9 | 10 | public PanSampleProvider(ISampleProvider source) 11 | { 12 | sampleProvider = source; 13 | 14 | if (source.WaveFormat.Channels != 2) 15 | throw new Exception("Must be stereo."); 16 | } 17 | 18 | public WaveFormat WaveFormat => sampleProvider.WaveFormat; 19 | 20 | public float Pan { get; set; } 21 | 22 | public int Read(float[] buffer, int offset, int count) 23 | { 24 | int read = sampleProvider.Read(buffer, offset, count); 25 | 26 | float left; 27 | float right; 28 | 29 | int bufferIndex = 0; 30 | for (int i = offset; i < count / 2; i++) 31 | { 32 | left = Pan <= 0 ? 1.0F : (1.0F - Pan); 33 | right = Pan >= 0 ? 1.0F : (Pan + 1.0F); 34 | 35 | buffer[bufferIndex++] *= left; 36 | buffer[bufferIndex++] *= right; 37 | } 38 | 39 | return read; 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Tools/LiveMusicPlayerCli/PartTrigger.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace LiveMusicPlayerCli 4 | { 5 | class PartTrigger 6 | { 7 | public int TimeMs { get; } 8 | 9 | public int[] MemberTracks { get; } 10 | 11 | public float[] MemberVolumes { get; } 12 | 13 | public float[] MemberPans { get; } 14 | 15 | public float VolumeRate { get; } 16 | 17 | public PartTrigger(string partCsvLine, bool hasVolumeRate) 18 | { 19 | string[] columns = partCsvLine.Split(','); 20 | 21 | int activeMembers; 22 | 23 | int ignoreColumns = hasVolumeRate ? 2 : 1; 24 | 25 | if (columns.Length - ignoreColumns > 5) 26 | activeMembers = (columns.Length - ignoreColumns) / 3; 27 | else 28 | activeMembers = columns.Length - ignoreColumns; 29 | 30 | MemberTracks = new int[activeMembers]; 31 | MemberVolumes = new float[activeMembers]; 32 | MemberPans = new float[activeMembers]; 33 | 34 | int currentIndex = 0; 35 | TimeMs = int.Parse(columns[currentIndex++]); 36 | 37 | int pivot = activeMembers / 2; 38 | 39 | for (int i = 0; i < activeMembers; i++) 40 | { 41 | MemberTracks[PositionToIndex(i, pivot)] = int.Parse(columns[currentIndex++]); 42 | } 43 | 44 | if (columns.Length - 1 > 5) 45 | { 46 | for (int i = 0; i < activeMembers; i++) 47 | { 48 | MemberVolumes[PositionToIndex(i, pivot)] = float.Parse(columns[currentIndex++]); 49 | } 50 | for (int i = 0; i < activeMembers; i++) 51 | { 52 | MemberPans[PositionToIndex(i, pivot)] = float.Parse(columns[currentIndex++]); 53 | } 54 | } 55 | else 56 | { 57 | for (int i = 0; i < activeMembers; i++) 58 | { 59 | MemberVolumes[i] = 1.0F; 60 | MemberPans[i] = 999; 61 | } 62 | } 63 | 64 | if (hasVolumeRate) 65 | VolumeRate = float.Parse(columns[currentIndex++]); 66 | } 67 | 68 | private static int PositionToIndex(int position, int pivot) 69 | { 70 | int distance = Math.Abs(pivot - position); 71 | int multiply = distance * 2; 72 | if (position < pivot) multiply -= 1; 73 | return multiply; 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /Tools/PlayerCli/GameFile.cs: -------------------------------------------------------------------------------- 1 | using SQLite; 2 | 3 | namespace PlayerCli 4 | { 5 | [Table("a")] 6 | public class GameFile 7 | { 8 | [PrimaryKey] 9 | [Column("i")] 10 | public int Id { get; set; } 11 | 12 | [Column("n"), NotNull] 13 | public string Name { get; set; } 14 | 15 | [Column("l"), NotNull] 16 | public string Length { get; set; } 17 | 18 | [Column("h"), NotNull] 19 | public string Hash { get; set; } 20 | 21 | public string BaseName 22 | { 23 | get 24 | { 25 | int lastSlash = Name.LastIndexOf('/'); 26 | return Name[(lastSlash + 1)..]; 27 | } 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /Tools/PlayerCli/PlayerCli.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net8.0 6 | PlayerCli.Program 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /Tools/PlayerCli/UmaWaveStream.cs: -------------------------------------------------------------------------------- 1 | using NAudio.Wave; 2 | using System; 3 | using System.IO; 4 | using CriWareLibrary; 5 | 6 | namespace PlayerCli 7 | { 8 | public class UmaWaveStream : WaveStream 9 | { 10 | private const ulong umaMusumeKey = 75923756697503; 11 | 12 | private readonly HcaWaveStream hcaWaveStream; 13 | 14 | public UmaWaveStream(AwbReader awbReader, int waveId) 15 | { 16 | Stream awbSubfile = awbReader.GetWaveSubfileStream(awbReader.Waves.Find((wave) => wave.WaveId == waveId)); 17 | hcaWaveStream = new(awbSubfile, MixKey(umaMusumeKey, awbReader.Subkey)); 18 | } 19 | 20 | public override WaveFormat WaveFormat => hcaWaveStream.WaveFormat; 21 | 22 | public bool Loop { get => hcaWaveStream.Loop; set { hcaWaveStream.Loop = value; } } 23 | 24 | public long LoopStartSample { get => hcaWaveStream.LoopStartSample; set { hcaWaveStream.LoopStartSample = value; } } 25 | 26 | public long LoopEndSample { get => hcaWaveStream.LoopEndSample; set { hcaWaveStream.LoopEndSample = value; } } 27 | 28 | public override long Length => hcaWaveStream.Length; 29 | 30 | public override long Position { get => hcaWaveStream.Position; set => hcaWaveStream.Position = value; } 31 | 32 | public override int Read(byte[] buffer, int offset, int count) 33 | { 34 | return hcaWaveStream.Read(buffer, offset, count); 35 | } 36 | 37 | public void ResetLoop() => hcaWaveStream.ResetLoop(); 38 | 39 | private static ulong MixKey(ulong key, ushort subkey) => 40 | key * (((ulong)subkey << 16) | ((ushort)~subkey + 2u)); 41 | 42 | protected override void Dispose(bool disposing) 43 | { 44 | hcaWaveStream.Dispose(); 45 | 46 | base.Dispose(disposing); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Tools/SqlCreateStatementToClass/Program.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | 3 | string createStatement = args.Length > 0 ? args[0] : ""; 4 | 5 | if (createStatement == "") 6 | createStatement = Console.ReadLine() ?? ""; 7 | 8 | if (createStatement != "") 9 | { 10 | createStatement = createStatement["CREATE TABLE".Length..]; 11 | 12 | string tableName = ExtractFromQuotesAndUpdate(ref createStatement); 13 | 14 | using var writer = new StreamWriter(File.Create(UnderscoredToCamelCase(tableName) + ".cs")); 15 | 16 | writer.WriteLine("using SQLite;\n"); 17 | writer.WriteLine($"[Table(\"{tableName}\")]"); 18 | writer.WriteLine($"public class {UnderscoredToCamelCase(tableName)}"); 19 | writer.WriteLine("{"); 20 | 21 | createStatement = createStatement[(createStatement.IndexOf('('))..].Trim(); 22 | 23 | Dictionary properties = new(); 24 | 25 | while (true) 26 | { 27 | if (createStatement.StartsWith(',')) 28 | createStatement = createStatement[1..]; 29 | createStatement = createStatement.Trim(); 30 | 31 | if (createStatement.StartsWith("PRIMARY KEY(")) 32 | { 33 | while (true) 34 | { 35 | string columnName = ExtractFromQuotesAndUpdate(ref createStatement); 36 | properties[columnName] += " PRIMARY KEY"; 37 | if (createStatement.StartsWith(")")) 38 | { 39 | createStatement = createStatement[1..]; 40 | break; 41 | } 42 | } 43 | } 44 | else if (createStatement.StartsWith("UNIQUE(")) 45 | { 46 | while (true) 47 | { 48 | string columnName = ExtractFromQuotesAndUpdate(ref createStatement); 49 | properties[columnName] += " UNIQUE"; 50 | if (createStatement.StartsWith(")")) 51 | { 52 | createStatement = createStatement[1..]; 53 | break; 54 | } 55 | } 56 | } 57 | else 58 | { 59 | 60 | int spaceIndex = createStatement.IndexOf(' '); 61 | if (spaceIndex < 0) break; 62 | 63 | string columnName = ExtractFromQuotesAndUpdate(ref createStatement); 64 | createStatement = createStatement.Trim(); 65 | 66 | string type = createStatement[..createStatement.IndexOf(',')]; 67 | createStatement = createStatement[(type.Length)..]; 68 | 69 | properties.Add(columnName, type); 70 | } 71 | } 72 | 73 | int index = 0; 74 | foreach (var property in properties) 75 | { 76 | string type = property.Value[..property.Value.IndexOf(' ')]; 77 | type = type switch 78 | { 79 | "INTEGER" => "int", 80 | "TEXT" => "string", 81 | _ => "object", 82 | }; 83 | 84 | writer.Write(" "); 85 | writer.WriteLine($"[Column(\"{property.Key}\")" + 86 | $"{(property.Value.Contains("NOT NULL") ? ", NotNull" : "")}" + 87 | $"{(property.Value.Contains("PRIMARY KEY") ? ", PrimaryKey" : "")}" + 88 | $"{(property.Value.Contains("UNIQUE") ? ", Unique" : "")}]"); 89 | writer.Write(" "); 90 | writer.Write($"public {type} {UnderscoredToCamelCase(property.Key)} "); 91 | 92 | if (type == "string") 93 | writer.WriteLine("{ get; set; } = \"\";"); 94 | else 95 | writer.WriteLine("{ get; set; }"); 96 | 97 | if (index < properties.Count - 1) 98 | writer.WriteLine(); 99 | 100 | index++; 101 | } 102 | 103 | writer.WriteLine("}"); 104 | } 105 | 106 | string ExtractFromQuotesAndUpdate(ref string source) 107 | { 108 | source = source[(source.IndexOf('\'') + 1)..]; 109 | string value = source[..source.IndexOf('\'')]; 110 | source = source[(value.Length + 1)..]; 111 | 112 | return value; 113 | } 114 | 115 | string UnderscoredToCamelCase(string value) 116 | { 117 | string[] words = value.Split('_'); 118 | 119 | StringBuilder newString = new(); 120 | 121 | foreach (var word in words) 122 | { 123 | newString.Append(char.ToUpper(word[0])); 124 | newString.Append(word[1..]); 125 | } 126 | 127 | return newString.ToString(); 128 | } -------------------------------------------------------------------------------- /Tools/SqlCreateStatementToClass/SqlCreateStatementToClass.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /UmaMusumeAudio/UmaMusumeAudio.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /UmaMusumeAudio/UmaWaveStream.cs: -------------------------------------------------------------------------------- 1 | using NAudio.Wave; 2 | using System; 3 | using System.IO; 4 | using CriWareLibrary; 5 | 6 | namespace UmaMusumeAudio 7 | { 8 | public class UmaWaveStream : WaveStream 9 | { 10 | private const ulong umaMusumeKey = 75923756697503; 11 | 12 | private readonly HcaWaveStream hcaWaveStream; 13 | 14 | public UmaWaveStream(AwbReader awbReader, int waveId) 15 | { 16 | Stream awbSubfile = awbReader.GetWaveSubfileStream(awbReader.Waves.Find((wave) => wave.WaveId == waveId)); 17 | hcaWaveStream = new(awbSubfile, MixKey(umaMusumeKey, awbReader.Subkey)); 18 | } 19 | 20 | public override WaveFormat WaveFormat => hcaWaveStream.WaveFormat; 21 | 22 | public bool Loop { get => hcaWaveStream.Loop; set { hcaWaveStream.Loop = value; } } 23 | 24 | public long LoopStartSample { get => hcaWaveStream.LoopStartSample; set { hcaWaveStream.LoopStartSample = value; } } 25 | 26 | public long LoopEndSample { get => hcaWaveStream.LoopEndSample; set { hcaWaveStream.LoopEndSample = value; } } 27 | 28 | public override long Length => hcaWaveStream.Length; 29 | 30 | public override long Position { get => hcaWaveStream.Position; set => hcaWaveStream.Position = value; } 31 | 32 | public override int Read(byte[] buffer, int offset, int count) 33 | { 34 | return hcaWaveStream.Read(buffer, offset, count); 35 | } 36 | 37 | public void ResetLoop() => hcaWaveStream.ResetLoop(); 38 | 39 | private static ulong MixKey(ulong key, ushort subkey) => 40 | key * (((ulong)subkey << 16) | ((ushort)~subkey + 2u)); 41 | 42 | protected override void Dispose(bool disposing) 43 | { 44 | hcaWaveStream.Dispose(); 45 | 46 | base.Dispose(disposing); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /UmaMusumeData/AssetBundleGroup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace UmaMusumeData 8 | { 9 | [Flags] 10 | public enum AssetBundleGroup : int 11 | { 12 | Default = 0x00, 13 | DeleteOnLogin = 0x01, 14 | DownloadLogin = 0x02, 15 | Tutorial = 0x04, 16 | HomeLogin = 0x08, 17 | RequiredTutorialStart = 0x10, 18 | DelayRelease = 0x20, 19 | RealFanfare = 0x40, 20 | WithRealFanfare = 0x80 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /UmaMusumeData/ManifestEntry.cs: -------------------------------------------------------------------------------- 1 | using SQLite; 2 | 3 | namespace UmaMusumeData 4 | { 5 | [Table("a")] 6 | public class ManifestEntry 7 | { 8 | [Column("i"), PrimaryKey] 9 | public int Id { get; set; } 10 | 11 | [Column("n"), NotNull] 12 | public string Name { get; set; } = ""; 13 | 14 | [Column("d")] 15 | public string Dependencies { get; set; } = ""; 16 | 17 | [Column("g"), NotNull] 18 | public AssetBundleGroup Group { get; set; } 19 | 20 | [Column("l"), NotNull] 21 | public long Length { get; set; } 22 | 23 | [Column("c"), NotNull] 24 | public long Checksum { get; set; } 25 | 26 | [Column("h"), NotNull] 27 | public string HashName { get; set; } = ""; 28 | 29 | [Column("m"), NotNull] 30 | public string Manifest { get; set; } = ""; 31 | 32 | [Column("k"), NotNull] 33 | public ManifestEntryKind Kind { get; set; } 34 | 35 | [Column("s"), NotNull] 36 | public byte State { get; set; } 37 | 38 | [Column("p"), NotNull] 39 | public int Priority { get; set; } 40 | 41 | public string BaseName 42 | { 43 | get 44 | { 45 | int lastSlash = Name.LastIndexOf('/'); 46 | return Name[(lastSlash + 1)..]; 47 | } 48 | } 49 | 50 | public override bool Equals(object? obj) 51 | { 52 | return (obj as ManifestEntry)?.HashName == HashName; 53 | } 54 | 55 | public override int GetHashCode() 56 | { 57 | return HashName.GetHashCode(); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /UmaMusumeData/ManifestEntryKind.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace UmaMusumeData 8 | { 9 | public enum ManifestEntryKind : byte 10 | { 11 | Default = 0x0, 12 | AssetManifest = 0x1, 13 | PlatformManifest = 0x2, 14 | RootManifest = 0x3, 15 | Master = 0xA, 16 | Sound = 0xB, 17 | Movie = 0xC, 18 | Font = 0xD 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /UmaMusumeData/Tables/AvailableSkillSet.cs: -------------------------------------------------------------------------------- 1 | using SQLite; 2 | 3 | namespace UmaMusumeData.Tables 4 | { 5 | [Table("available_skill_set")] 6 | public class AvailableSkillSet 7 | { 8 | [Column("id"), NotNull, PrimaryKey] 9 | public int Id { get; set; } 10 | 11 | [Column("available_skill_set_id"), NotNull] 12 | public int AvailableSkillSetId { get; set; } 13 | 14 | [Column("skill_id"), NotNull] 15 | public int SkillId { get; set; } 16 | 17 | [Column("need_rank"), NotNull] 18 | public int NeedRank { get; set; } 19 | } 20 | } -------------------------------------------------------------------------------- /UmaMusumeData/Tables/CardData.cs: -------------------------------------------------------------------------------- 1 | using SQLite; 2 | 3 | namespace UmaMusumeData.Tables 4 | { 5 | [Table("card_data")] 6 | public class CardData 7 | { 8 | [Column("id"), NotNull, PrimaryKey] 9 | public int Id { get; set; } 10 | 11 | [Column("chara_id"), NotNull] 12 | public int CharaId { get; set; } 13 | 14 | [Column("default_rarity"), NotNull] 15 | public int DefaultRarity { get; set; } 16 | 17 | [Column("limited_chara"), NotNull] 18 | public int LimitedChara { get; set; } 19 | 20 | [Column("available_skill_set_id"), NotNull] 21 | public int AvailableSkillSetId { get; set; } 22 | 23 | [Column("talent_speed"), NotNull] 24 | public int TalentSpeed { get; set; } 25 | [Column("talent_stamina"), NotNull] 26 | public int TalentStamina { get; set; } 27 | [Column("talent_pow"), NotNull] 28 | public int TalentPow { get; set; } 29 | [Column("talent_guts"), NotNull] 30 | public int TalentGuts { get; set; } 31 | [Column("talent_wiz"), NotNull] 32 | public int TalentWiz { get; set; } 33 | 34 | [Column("talent_group_id"), NotNull] 35 | public int TalentGroupId { get; set; } 36 | 37 | [Column("bg_id"), NotNull] 38 | public int BgId { get; set; } 39 | 40 | [Column("get_piece_id"), NotNull] 41 | public int GetPieceId { get; set; } 42 | 43 | [Column("running_style"), NotNull] 44 | public int RunningStyle { get; set; } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /UmaMusumeData/Tables/CardRarityData.cs: -------------------------------------------------------------------------------- 1 | using SQLite; 2 | 3 | namespace UmaMusumeData.Tables 4 | { 5 | [Table("card_rarity_data")] 6 | public class CardRarityData 7 | { 8 | [Column("id"), NotNull, PrimaryKey] 9 | public int Id { get; set; } 10 | 11 | [Column("card_id"), NotNull] 12 | public int CardId { get; set; } 13 | 14 | [Column("rarity"), NotNull] 15 | public int Rarity { get; set; } 16 | 17 | [Column("race_dress_id"), NotNull] 18 | public int RaceDressId { get; set; } 19 | 20 | [Column("skill_set"), NotNull] 21 | public int SkillSet { get; set; } 22 | 23 | [Column("speed"), NotNull] 24 | public int Speed { get; set; } 25 | [Column("stamina"), NotNull] 26 | public int Stamina { get; set; } 27 | [Column("pow"), NotNull] 28 | public int Pow { get; set; } 29 | [Column("guts"), NotNull] 30 | public int Guts { get; set; } 31 | [Column("wiz"), NotNull] 32 | public int Wiz { get; set; } 33 | 34 | [Column("max_speed"), NotNull] 35 | public int MaxSpeed { get; set; } 36 | [Column("max_stamina"), NotNull] 37 | public int MaxStamina { get; set; } 38 | [Column("max_pow"), NotNull] 39 | public int MaxPow { get; set; } 40 | [Column("max_guts"), NotNull] 41 | public int MaxGuts { get; set; } 42 | [Column("max_wiz"), NotNull] 43 | public int MaxWiz { get; set; } 44 | 45 | [Column("proper_distance_short"), NotNull] 46 | public int ProperDistanceShort { get; set; } 47 | [Column("proper_distance_mile"), NotNull] 48 | public int ProperDistanceMile { get; set; } 49 | [Column("proper_distance_middle"), NotNull] 50 | public int ProperDistanceMiddle { get; set; } 51 | [Column("proper_distance_long"), NotNull] 52 | public int ProperDistanceLong { get; set; } 53 | 54 | [Column("proper_running_style_nige"), NotNull] 55 | public int ProperRunningStyleNige { get; set; } 56 | [Column("proper_running_style_senko"), NotNull] 57 | public int ProperRunningStyleSenko { get; set; } 58 | [Column("proper_running_style_sashi"), NotNull] 59 | public int ProperRunningStyleSashi { get; set; } 60 | [Column("proper_running_style_oikomi"), NotNull] 61 | public int ProperRunningStyleOikomi { get; set; } 62 | 63 | [Column("proper_ground_turf"), NotNull] 64 | public int ProperGroundTurf { get; set; } 65 | [Column("proper_ground_dirt"), NotNull] 66 | public int ProperGroundDirt { get; set; } 67 | 68 | [Column("get_dress_id_1"), NotNull] 69 | public int GetDressId1 { get; set; } 70 | [Column("get_dress_id_2"), NotNull] 71 | public int GetDressId2 { get; set; } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /UmaMusumeData/Tables/CharaData.cs: -------------------------------------------------------------------------------- 1 | using SQLite; 2 | 3 | namespace UmaMusumeData.Tables 4 | { 5 | [Table("chara_data")] 6 | public class CharaData 7 | { 8 | [Column("id"), NotNull, PrimaryKey] 9 | public int Id { get; set; } 10 | 11 | [Column("birth_year"), NotNull] 12 | public int BirthYear { get; set; } 13 | [Column("birth_month"), NotNull] 14 | public int BirthMonth { get; set; } 15 | [Column("birth_day"), NotNull] 16 | public int BirthDay { get; set; } 17 | 18 | [Column("sex"), NotNull] 19 | public int Sex { get; set; } 20 | 21 | [Column("image_color_main"), NotNull] 22 | public string ImageColorMain { get; set; } = ""; 23 | [Column("image_color_sub"), NotNull] 24 | public string ImageColorSub { get; set; } = ""; 25 | 26 | [Column("ui_color_main"), NotNull] 27 | public string UIColorMain { get; set; } = ""; 28 | [Column("ui_color_sub"), NotNull] 29 | public string UIColorSub { get; set; } = ""; 30 | 31 | [Column("ui_training_color_1"), NotNull] 32 | public string UITrainingColor1 { get; set; } = ""; 33 | [Column("ui_training_color_2"), NotNull] 34 | public string UITrainingColor2 { get; set; } = ""; 35 | 36 | [Column("ui_border_color"), NotNull] 37 | public string UIBorderColor { get; set; } = ""; 38 | 39 | [Column("ui_num_color_1"), NotNull] 40 | public string UINumColor1 { get; set; } = ""; 41 | [Column("ui_num_color_2"), NotNull] 42 | public string UINumColor2 { get; set; } = ""; 43 | 44 | [Column("ui_turn_color"), NotNull] 45 | public string UITurnColor { get; set; } = ""; 46 | 47 | [Column("ui_wipe_color_1"), NotNull] 48 | public string UIWipeColor1 { get; set; } = ""; 49 | [Column("ui_wipe_color_2"), NotNull] 50 | public string UIWipeColor2 { get; set; } = ""; 51 | [Column("ui_wipe_color_3"), NotNull] 52 | public string UIWipeColor3 { get; set; } = ""; 53 | 54 | [Column("ui_speech_color_1"), NotNull] 55 | public string UISpeechColor1 { get; set; } = ""; 56 | [Column("ui_speech_color_2"), NotNull] 57 | public string UISpeechColor2 { get; set; } = ""; 58 | 59 | [Column("ui_nameplate_color_1"), NotNull] 60 | public string UINameplateColor1 { get; set; } = ""; 61 | [Column("ui_nameplate_color_2"), NotNull] 62 | public string UINameplateColor2 { get; set; } = ""; 63 | 64 | [Column("height"), NotNull] 65 | public int Height { get; set; } 66 | 67 | [Column("bust"), NotNull] 68 | public int Bust { get; set; } 69 | 70 | [Column("scale"), NotNull] 71 | public int Scale { get; set; } 72 | 73 | [Column("skin"), NotNull] 74 | public int Skin { get; set; } 75 | 76 | [Column("shape"), NotNull] 77 | public int Shape { get; set; } 78 | 79 | [Column("socks"), NotNull] 80 | public int Socks { get; set; } 81 | 82 | [Column("personal_dress"), NotNull] 83 | public int PersonalDress { get; set; } 84 | 85 | [Column("tail_model_id"), NotNull] 86 | public int TailModelId { get; set; } 87 | 88 | [Column("race_running_type"), NotNull] 89 | public int RaceRunningType { get; set; } 90 | 91 | [Column("ear_random_time_min"), NotNull] 92 | public int EarRandomTimeMin { get; set; } 93 | [Column("ear_random_time_max"), NotNull] 94 | public int EarRandomTimeMax { get; set; } 95 | 96 | [Column("tail_random_time_min"), NotNull] 97 | public int TailRandomTimeMin { get; set; } 98 | [Column("tail_random_time_max"), NotNull] 99 | public int TailRandomTimeMax { get; set; } 100 | 101 | [Column("story_ear_random_time_min"), NotNull] 102 | public int StoryEarRandomTimeMin { get; set; } 103 | [Column("story_ear_random_time_max"), NotNull] 104 | public int StoryEarRandomTimeMax { get; set; } 105 | 106 | [Column("story_tail_random_time_min"), NotNull] 107 | public int StoryTailRandomTimeMin { get; set; } 108 | [Column("story_tail_random_time_max"), NotNull] 109 | public int StoryTailRandomTimeMax { get; set; } 110 | 111 | [Column("attachment_model_id"), NotNull] 112 | public int AttachmentModelId { get; set; } 113 | 114 | [Column("mini_mayu_shader_type"), NotNull] 115 | public int MiniMayuShaderType { get; set; } 116 | 117 | [Column("start_date"), NotNull] 118 | public int StartDate { get; set; } 119 | 120 | [Column("chara_category"), NotNull] 121 | public int CharaCategory { get; set; } 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /UmaMusumeData/Tables/CharacterSystemText.cs: -------------------------------------------------------------------------------- 1 | using SQLite; 2 | 3 | namespace UmaMusumeData.Tables 4 | { 5 | [Table("character_system_text")] 6 | public class CharacterSystemText 7 | { 8 | [Column("character_id"), NotNull, PrimaryKey] 9 | public int CharacterId { get; set; } 10 | 11 | [Column("voice_id"), NotNull, PrimaryKey] 12 | public int VoiceId { get; set; } 13 | 14 | [Column("text"), NotNull] 15 | public string Text { get; set; } = ""; 16 | 17 | [Column("cue_sheet"), NotNull] 18 | public string CueSheet { get; set; } = ""; 19 | 20 | [Column("cue_id"), NotNull] 21 | public int CueId { get; set; } 22 | 23 | [Column("motion_set"), NotNull] 24 | public int MotionSet { get; set; } 25 | 26 | [Column("scene"), NotNull] 27 | public int Scene { get; set; } 28 | 29 | [Column("use_gallery"), NotNull] 30 | public int UseGallery { get; set; } 31 | 32 | [Column("card_id"), NotNull] 33 | public int CardId { get; set; } 34 | 35 | [Column("lip_sync_data"), NotNull] 36 | public string LipSyncData { get; set; } = ""; 37 | 38 | [Column("gender"), NotNull] 39 | public int Gender { get; set; } 40 | 41 | [Column("motion_second_set"), NotNull] 42 | public int MotionSecondSet { get; set; } 43 | 44 | [Column("motion_second_start"), NotNull] 45 | public int MotionSecondStart { get; set; } 46 | 47 | [Column("start_date"), NotNull] 48 | public int StartDate { get; set; } 49 | } 50 | } -------------------------------------------------------------------------------- /UmaMusumeData/Tables/GachaAvailable.cs: -------------------------------------------------------------------------------- 1 | using SQLite; 2 | 3 | namespace UmaMusumeData.Tables 4 | { 5 | [Table("gacha_available")] 6 | public class GachaAvailable 7 | { 8 | [Column("gacha_id"), NotNull, PrimaryKey] 9 | public int GachaId { get; set; } 10 | 11 | [Column("card_id"), NotNull, PrimaryKey] 12 | public int CardId { get; set; } 13 | 14 | [Column("card_type"), NotNull] 15 | public int CardType { get; set; } 16 | 17 | [Column("rarity"), NotNull] 18 | public int Rarity { get; set; } 19 | 20 | [Column("odds"), NotNull] 21 | public int Odds { get; set; } 22 | 23 | [Column("is_pickup"), NotNull] 24 | public int IsPickup { get; set; } 25 | 26 | [Column("recommend_order"), NotNull] 27 | public int RecommendOrder { get; set; } 28 | 29 | [Column("is_prize_selectable"), NotNull] 30 | public int IsPrizeSelectable { get; set; } 31 | } 32 | } -------------------------------------------------------------------------------- /UmaMusumeData/Tables/JukeboxMusicData.cs: -------------------------------------------------------------------------------- 1 | using SQLite; 2 | 3 | namespace UmaMusumeData.Tables 4 | { 5 | [Table("jukebox_music_data")] 6 | public class JukeboxMusicData 7 | { 8 | [Column("music_id"), NotNull, PrimaryKey] 9 | public int MusicId { get; set; } 10 | 11 | [Column("sort"), NotNull] 12 | public int Sort { get; set; } 13 | 14 | [Column("condition_type"), NotNull] 15 | public int ConditionType { get; set; } 16 | 17 | [Column("is_hidden"), NotNull] 18 | public int IsHidden { get; set; } 19 | 20 | [Column("version_type"), NotNull] 21 | public int VersionType { get; set; } 22 | 23 | [Column("request_type"), NotNull] 24 | public int RequestType { get; set; } 25 | 26 | [Column("lamp_color"), NotNull] 27 | public int LampColor { get; set; } 28 | 29 | [Column("lamp_animation"), NotNull] 30 | public int LampAnimation { get; set; } 31 | 32 | [Column("name_texture_length"), NotNull] 33 | public int NameTextureLength { get; set; } 34 | 35 | [Column("song_type"), NotNull] 36 | public int SongType { get; set; } 37 | 38 | [Column("bgm_cue_name_short"), NotNull] 39 | public string BgmCueNameShort { get; set; } = ""; 40 | 41 | [Column("bgm_cuesheet_name_short"), NotNull] 42 | public string BgmCuesheetNameShort { get; set; } = ""; 43 | 44 | [Column("bgm_cue_name_gamesize"), NotNull] 45 | public string BgmCueNameGamesize { get; set; } = ""; 46 | 47 | [Column("bgm_cuesheet_name_gamesize"), NotNull] 48 | public string BgmCuesheetNameGamesize { get; set; } = ""; 49 | 50 | [Column("short_length"), NotNull] 51 | public int ShortLength { get; set; } 52 | 53 | [Column("alter_jacket"), NotNull] 54 | public int AlterJacket { get; set; } 55 | 56 | [Column("start_date"), NotNull] 57 | public int StartDate { get; set; } 58 | 59 | [Column("end_date"), NotNull] 60 | public int EndDate { get; set; } 61 | } 62 | } -------------------------------------------------------------------------------- /UmaMusumeData/Tables/LiveData.cs: -------------------------------------------------------------------------------- 1 | using SQLite; 2 | 3 | namespace UmaMusumeData.Tables 4 | { 5 | [Table("live_data")] 6 | public class LiveData 7 | { 8 | [Column("music_id"), NotNull, PrimaryKey] 9 | public int MusicId { get; set; } 10 | 11 | [Column("sort"), NotNull] 12 | public int Sort { get; set; } 13 | 14 | [Column("music_type"), NotNull] 15 | public int MusicType { get; set; } 16 | 17 | [Column("title_color_top"), NotNull] 18 | public string TitleColorTop { get; set; } = ""; 19 | 20 | [Column("title_color_bottom"), NotNull] 21 | public string TitleColorBottom { get; set; } = ""; 22 | 23 | [Column("condition_type"), NotNull] 24 | public int ConditionType { get; set; } 25 | 26 | [Column("song_chara_type"), NotNull] 27 | public int SongCharaType { get; set; } 28 | 29 | [Column("live_member_number"), NotNull] 30 | public int LiveMemberNumber { get; set; } 31 | 32 | [Column("default_main_dress"), NotNull] 33 | public int DefaultMainDress { get; set; } 34 | 35 | [Column("default_main_dress_color"), NotNull] 36 | public int DefaultMainDressColor { get; set; } 37 | 38 | [Column("default_mob_dress"), NotNull] 39 | public int DefaultMobDress { get; set; } 40 | 41 | [Column("default_mob_dress_color"), NotNull] 42 | public int DefaultMobDressColor { get; set; } 43 | 44 | [Column("backdancer_order"), NotNull] 45 | public int BackdancerOrder { get; set; } 46 | 47 | [Column("backdancer_dress"), NotNull] 48 | public int BackdancerDress { get; set; } 49 | 50 | [Column("backdancer_dress_color"), NotNull] 51 | public int BackdancerDressColor { get; set; } 52 | 53 | [Column("has_live"), NotNull] 54 | public int HasLive { get; set; } 55 | 56 | [Column("start_date"), NotNull] 57 | public int StartDate { get; set; } 58 | 59 | [Column("end_date"), NotNull] 60 | public int EndDate { get; set; } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /UmaMusumeData/Tables/LivePermissionData.cs: -------------------------------------------------------------------------------- 1 | using SQLite; 2 | 3 | namespace UmaMusumeData.Tables 4 | { 5 | [Table("live_permission_data")] 6 | public class LivePermissionData 7 | { 8 | [Column("music_id"), NotNull, PrimaryKey] 9 | public int MusicId { get; set; } 10 | 11 | [Column("chara_id"), NotNull, PrimaryKey] 12 | public int CharaId { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /UmaMusumeData/Tables/RaceBgm.cs: -------------------------------------------------------------------------------- 1 | using SQLite; 2 | 3 | namespace UmaMusumeData.Tables 4 | { 5 | [Table("race_bgm")] 6 | public class RaceBgm 7 | { 8 | [Column("id"), NotNull, PrimaryKey] 9 | public int Id { get; set; } 10 | 11 | [Column("race_type"), NotNull] 12 | public int RaceType { get; set; } 13 | 14 | [Column("race_instance_id"), NotNull] 15 | public int RaceInstanceId { get; set; } 16 | 17 | [Column("grade"), NotNull] 18 | public int Grade { get; set; } 19 | 20 | [Column("single_mode_route_race_id"), NotNull] 21 | public int SingleModeRouteRaceId { get; set; } 22 | 23 | [Column("single_mode_program_id"), NotNull] 24 | public int SingleModeProgramId { get; set; } 25 | 26 | [Column("paddock_bgm_cue_name"), NotNull] 27 | public string PaddockBgmCueName { get; set; } = ""; 28 | 29 | [Column("paddock_bgm_cuesheet_name"), NotNull] 30 | public string PaddockBgmCuesheetName { get; set; } = ""; 31 | 32 | [Column("entrytable_bgm_cue_name"), NotNull] 33 | public string EntrytableBgmCueName { get; set; } = ""; 34 | 35 | [Column("entrytable_bgm_cuesheet_name"), NotNull] 36 | public string EntrytableBgmCuesheetName { get; set; } = ""; 37 | 38 | [Column("first_bgm_pattern"), NotNull] 39 | public int FirstBgmPattern { get; set; } 40 | 41 | [Column("second_bgm_pattern"), NotNull] 42 | public int SecondBgmPattern { get; set; } 43 | 44 | [Column("result_cutin_bgm_cue_name_1"), NotNull] 45 | public string ResultCutinBgmCueName1 { get; set; } = ""; 46 | 47 | [Column("result_cutin_bgm_cuesheet_name_1"), NotNull] 48 | public string ResultCutinBgmCuesheetName1 { get; set; } = ""; 49 | 50 | [Column("result_cutin_bgm_cue_name_2"), NotNull] 51 | public string ResultCutinBgmCueName2 { get; set; } = ""; 52 | 53 | [Column("result_cutin_bgm_cuesheet_name_2"), NotNull] 54 | public string ResultCutinBgmCuesheetName2 { get; set; } = ""; 55 | 56 | [Column("result_cutin_bgm_cue_name_3"), NotNull] 57 | public string ResultCutinBgmCueName3 { get; set; } = ""; 58 | 59 | [Column("result_cutin_bgm_cuesheet_name_3"), NotNull] 60 | public string ResultCutinBgmCuesheetName3 { get; set; } = ""; 61 | 62 | [Column("result_list_bgm_cue_name_1"), NotNull] 63 | public string ResultListBgmCueName1 { get; set; } = ""; 64 | 65 | [Column("result_list_bgm_cuesheet_name_1"), NotNull] 66 | public string ResultListBgmCuesheetName1 { get; set; } = ""; 67 | 68 | [Column("result_list_bgm_cue_name_2"), NotNull] 69 | public string ResultListBgmCueName2 { get; set; } = ""; 70 | 71 | [Column("result_list_bgm_cuesheet_name_2"), NotNull] 72 | public string ResultListBgmCuesheetName2 { get; set; } = ""; 73 | 74 | [Column("result_list_bgm_cue_name_3"), NotNull] 75 | public string ResultListBgmCueName3 { get; set; } = ""; 76 | 77 | [Column("result_list_bgm_cuesheet_name_3"), NotNull] 78 | public string ResultListBgmCuesheetName3 { get; set; } = ""; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /UmaMusumeData/Tables/SingleModeSkillNeedPoint.cs: -------------------------------------------------------------------------------- 1 | using SQLite; 2 | 3 | namespace UmaMusumeData.Tables 4 | { 5 | [Table("single_mode_skill_need_point")] 6 | public class SingleModeSkillNeedPoint 7 | { 8 | [Column("id"), NotNull, PrimaryKey] 9 | public int Id { get; set; } 10 | 11 | [Column("need_skill_point"), NotNull] 12 | public int NeedSkillPoint { get; set; } 13 | 14 | [Column("status_type"), NotNull] 15 | public int StatusType { get; set; } 16 | 17 | [Column("status_value"), NotNull] 18 | public int StatusValue { get; set; } 19 | 20 | [Column("solvable_type"), NotNull] 21 | public int SolvableType { get; set; } 22 | } 23 | } -------------------------------------------------------------------------------- /UmaMusumeData/Tables/SkillSet.cs: -------------------------------------------------------------------------------- 1 | using SQLite; 2 | 3 | namespace UmaMusumeData.Tables 4 | { 5 | [Table("skill_set")] 6 | public class SkillSet 7 | { 8 | [Column("id"), NotNull, PrimaryKey] 9 | public int Id { get; set; } 10 | 11 | [Column("skill_id1"), NotNull] 12 | public int SkillId1 { get; set; } 13 | 14 | [Column("skill_level1"), NotNull] 15 | public int SkillLevel1 { get; set; } 16 | 17 | [Column("skill_id2"), NotNull] 18 | public int SkillId2 { get; set; } 19 | 20 | [Column("skill_level2"), NotNull] 21 | public int SkillLevel2 { get; set; } 22 | 23 | [Column("skill_id3"), NotNull] 24 | public int SkillId3 { get; set; } 25 | 26 | [Column("skill_level3"), NotNull] 27 | public int SkillLevel3 { get; set; } 28 | 29 | [Column("skill_id4"), NotNull] 30 | public int SkillId4 { get; set; } 31 | 32 | [Column("skill_level4"), NotNull] 33 | public int SkillLevel4 { get; set; } 34 | 35 | [Column("skill_id5"), NotNull] 36 | public int SkillId5 { get; set; } 37 | 38 | [Column("skill_level5"), NotNull] 39 | public int SkillLevel5 { get; set; } 40 | 41 | [Column("skill_id6"), NotNull] 42 | public int SkillId6 { get; set; } 43 | 44 | [Column("skill_level6"), NotNull] 45 | public int SkillLevel6 { get; set; } 46 | 47 | [Column("skill_id7"), NotNull] 48 | public int SkillId7 { get; set; } 49 | 50 | [Column("skill_level7"), NotNull] 51 | public int SkillLevel7 { get; set; } 52 | 53 | [Column("skill_id8"), NotNull] 54 | public int SkillId8 { get; set; } 55 | 56 | [Column("skill_level8"), NotNull] 57 | public int SkillLevel8 { get; set; } 58 | 59 | [Column("skill_id9"), NotNull] 60 | public int SkillId9 { get; set; } 61 | 62 | [Column("skill_level9"), NotNull] 63 | public int SkillLevel9 { get; set; } 64 | 65 | [Column("skill_id10"), NotNull] 66 | public int SkillId10 { get; set; } 67 | 68 | [Column("skill_level10"), NotNull] 69 | public int SkillLevel10 { get; set; } 70 | } 71 | } -------------------------------------------------------------------------------- /UmaMusumeData/Tables/SkillUpgradeCondition.cs: -------------------------------------------------------------------------------- 1 | using SQLite; 2 | 3 | namespace UmaMusumeData.Tables 4 | { 5 | [Table("skill_upgrade_condition")] 6 | public class SkillUpgradeCondition 7 | { 8 | [Column("id"), NotNull, PrimaryKey] 9 | public int Id { get; set; } 10 | 11 | [Column("description_id"), NotNull, Unique] 12 | public int DescriptionId { get; set; } 13 | 14 | [Column("num"), NotNull, Unique] 15 | public int Num { get; set; } 16 | 17 | [Column("sub_num"), NotNull, Unique] 18 | public int SubNum { get; set; } 19 | 20 | [Column("timing_type"), NotNull] 21 | public int TimingType { get; set; } 22 | 23 | [Column("count_type"), NotNull] 24 | public int CountType { get; set; } 25 | } 26 | } -------------------------------------------------------------------------------- /UmaMusumeData/Tables/SkillUpgradeDescription.cs: -------------------------------------------------------------------------------- 1 | using SQLite; 2 | 3 | namespace UmaMusumeData.Tables 4 | { 5 | [Table("skill_upgrade_description")] 6 | public class SkillUpgradeDescription 7 | { 8 | [Column("id"), NotNull, PrimaryKey] 9 | public int Id { get; set; } 10 | 11 | [Column("card_id"), NotNull, Unique] 12 | public int CardId { get; set; } 13 | 14 | [Column("rank"), NotNull] 15 | public int Rank { get; set; } 16 | 17 | [Column("skill_id"), NotNull, Unique] 18 | public int SkillId { get; set; } 19 | 20 | [Column("start_date"), NotNull] 21 | public int StartDate { get; set; } 22 | } 23 | } -------------------------------------------------------------------------------- /UmaMusumeData/Tables/SupportCardData.cs: -------------------------------------------------------------------------------- 1 | using SQLite; 2 | 3 | namespace UmaMusumeData.Tables 4 | { 5 | [Table("support_card_data")] 6 | public class SupportCardData 7 | { 8 | [Column("id"), NotNull, PrimaryKey] 9 | public int Id { get; set; } 10 | 11 | [Column("chara_id"), NotNull] 12 | public int CharaId { get; set; } 13 | 14 | [Column("rarity"), NotNull] 15 | public int Rarity { get; set; } 16 | 17 | [Column("exchange_item_id"), NotNull] 18 | public int ExchangeItemId { get; set; } 19 | 20 | [Column("effect_table_id"), NotNull] 21 | public int EffectTableId { get; set; } 22 | 23 | [Column("unique_effect_id"), NotNull] 24 | public int UniqueEffectId { get; set; } 25 | 26 | [Column("command_type"), NotNull] 27 | public int CommandType { get; set; } 28 | 29 | [Column("command_id"), NotNull] 30 | public int CommandId { get; set; } 31 | 32 | [Column("support_card_type"), NotNull] 33 | public int SupportCardType { get; set; } 34 | 35 | [Column("skill_set_id"), NotNull] 36 | public int SkillSetId { get; set; } 37 | 38 | [Column("detail_pos_x"), NotNull] 39 | public int DetailPosX { get; set; } 40 | 41 | [Column("detail_pos_y"), NotNull] 42 | public int DetailPosY { get; set; } 43 | 44 | [Column("detail_scale"), NotNull] 45 | public int DetailScale { get; set; } 46 | 47 | [Column("detail_rot_z"), NotNull] 48 | public int DetailRotZ { get; set; } 49 | 50 | [Column("start_date"), NotNull] 51 | public int StartDate { get; set; } 52 | 53 | [Column("outing_max"), NotNull] 54 | public int OutingMax { get; set; } 55 | 56 | [Column("effect_id"), NotNull] 57 | public int EffectId { get; set; } 58 | } 59 | } -------------------------------------------------------------------------------- /UmaMusumeData/Tables/TextData.cs: -------------------------------------------------------------------------------- 1 | using SQLite; 2 | 3 | namespace UmaMusumeData.Tables 4 | { 5 | [Table("text_data")] 6 | public class TextData 7 | { 8 | [Column("id"), NotNull] 9 | public int Id { get; set; } 10 | 11 | [Column("category"), NotNull, PrimaryKey] 12 | public int Category { get; set; } 13 | 14 | [Column("index"), NotNull, PrimaryKey] 15 | public int Index { get; set; } 16 | 17 | [Column("text"), NotNull] 18 | public string Text { get; set; } = ""; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /UmaMusumeData/UmaDataHelper.cs: -------------------------------------------------------------------------------- 1 | using SQLite; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Linq; 6 | 7 | namespace UmaMusumeData 8 | { 9 | public static class UmaDataHelper 10 | { 11 | private static readonly string localLow = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "Low"); 12 | private static string umaMusumeDirectory = Path.Combine(localLow, "Cygames", "umamusume"); 13 | 14 | private static List? manifestEntries; 15 | 16 | public static string UmaMusumeDirectory { get => umaMusumeDirectory; set => umaMusumeDirectory = value; } 17 | 18 | public static string DataDirectory => Path.Combine(UmaMusumeDirectory, "dat"); 19 | 20 | public static string MetaFile => Path.Combine(UmaMusumeDirectory, "meta"); 21 | 22 | public static string MasterFile => Path.Combine(UmaMusumeDirectory, "master", "master.mdb"); 23 | 24 | public static bool CheckDirectory() 25 | { 26 | return Directory.Exists(UmaMusumeDirectory) && 27 | File.Exists(MetaFile) && File.Exists(MasterFile); 28 | } 29 | 30 | public static string GetPath(ManifestEntry? entry) 31 | { 32 | if (entry is not null) 33 | { 34 | string path = Path.Combine(DataDirectory, entry.HashName[..2], entry.HashName); 35 | 36 | if (File.Exists(path)) return path; 37 | else return ""; 38 | } 39 | else return ""; 40 | } 41 | 42 | public static string GetPath(IEnumerable entryList, string gameFileBaseName) 43 | { 44 | ManifestEntry? entry = entryList.FirstOrDefault(gf => gf.BaseName == gameFileBaseName); 45 | 46 | if (entry is not null) 47 | return GetPath(entry); 48 | else return ""; 49 | } 50 | 51 | public static List GetManifestEntries(Func? condition = null) 52 | { 53 | manifestEntries ??= GetRows(MetaFile); 54 | 55 | if (condition is not null) 56 | return manifestEntries.Where(condition).ToList(); 57 | else 58 | return manifestEntries; 59 | } 60 | 61 | public static List GetMasterDatabaseRows(Func? condition = null) where T : new() 62 | => GetRows(MasterFile, condition); 63 | 64 | private static List GetRows(string databaseFile, Func? condition = null) where T : new() 65 | { 66 | try 67 | { 68 | SQLiteConnection connection = new(databaseFile, SQLiteOpenFlags.ReadOnly); 69 | 70 | List rows; 71 | if (condition is not null) 72 | rows = connection.Table().Where(condition).ToList(); 73 | else 74 | rows = connection.Table().ToList(); 75 | 76 | connection.Close(); 77 | connection.Dispose(); 78 | 79 | return rows; 80 | } 81 | catch (SQLiteException) 82 | { 83 | throw; 84 | } 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /UmaMusumeData/UmaMusumeData.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/AudioPlayer/Classes/AtomAudioSource.cs: -------------------------------------------------------------------------------- 1 | using CriWareLibrary; 2 | 3 | namespace UmaMusumeExplorer.Controls.AudioPlayer.Classes 4 | { 5 | internal class AtomAudioSource : AudioSource 6 | { 7 | private readonly string acb; 8 | private readonly string awb; 9 | 10 | private readonly AwbReader awbReader; 11 | 12 | public AtomAudioSource(string name, string acbPath, string awbPath) 13 | { 14 | Name = name; 15 | acb = acbPath; 16 | awb = awbPath; 17 | 18 | awbReader = new(File.OpenRead(awbPath)); 19 | 20 | TrackCount = awbReader.Waves.Count; 21 | } 22 | 23 | public override string Name { get; } 24 | 25 | public override int TrackCount { get; } 26 | 27 | protected override IAudioTrack[] InitializeTracks() 28 | { 29 | AtomAudioTrack[] tracks = new AtomAudioTrack[TrackCount]; 30 | 31 | for (int i = 0; i < TrackCount; i++) 32 | { 33 | tracks[i] = new AtomAudioTrack(acb, awb, i); 34 | } 35 | 36 | return tracks; 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/AudioPlayer/Classes/AtomAudioTrack.cs: -------------------------------------------------------------------------------- 1 | using CriWareLibrary; 2 | using NAudio.Wave; 3 | using UmaMusumeAudio; 4 | 5 | namespace UmaMusumeExplorer.Controls.AudioPlayer.Classes 6 | { 7 | internal class AtomAudioTrack : IAudioTrack 8 | { 9 | private readonly string awb; 10 | private readonly int index; 11 | 12 | public AtomAudioTrack(string acbPath, string awbPath, int waveIndex) 13 | { 14 | using var acbFile = File.OpenRead(acbPath); 15 | AcbParser acbNameLoader = new(acbFile); 16 | 17 | Name = acbNameLoader.LoadWaveName(waveIndex, 0, false); 18 | 19 | awb = awbPath; 20 | index = waveIndex; 21 | } 22 | 23 | public string Name { get; } 24 | 25 | public WaveStream WaveStream 26 | { 27 | get 28 | { 29 | AwbReader awbReader = new(File.OpenRead(awb)); 30 | 31 | return new UmaWaveStream(awbReader, awbReader.Waves[index].WaveId); 32 | } 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/AudioPlayer/Classes/AudioSource.cs: -------------------------------------------------------------------------------- 1 | namespace UmaMusumeExplorer.Controls.AudioPlayer.Classes 2 | { 3 | public abstract class AudioSource 4 | { 5 | private IAudioTrack[]? tracks; 6 | 7 | public abstract string Name { get; } 8 | 9 | public abstract int TrackCount { get; } 10 | 11 | public IAudioTrack[] Tracks 12 | { 13 | get 14 | { 15 | tracks ??= InitializeTracks(); 16 | return tracks; 17 | } 18 | } 19 | 20 | protected abstract IAudioTrack[] InitializeTracks(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/AudioPlayer/Classes/IAudioTrack.cs: -------------------------------------------------------------------------------- 1 | using NAudio.Wave; 2 | 3 | namespace UmaMusumeExplorer.Controls.AudioPlayer.Classes 4 | { 5 | public interface IAudioTrack 6 | { 7 | public string Name { get; } 8 | 9 | public WaveStream WaveStream { get; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/AudioPlayer/Classes/TrackComboBoxItem.cs: -------------------------------------------------------------------------------- 1 | namespace UmaMusumeExplorer.Controls.AudioPlayer.Classes 2 | { 3 | record TrackComboBoxItem(string TrackName, int Index, IAudioTrack Track) 4 | { 5 | public override string ToString() 6 | { 7 | return $"{Index}: {TrackName}"; 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/AudioPlayer/ConfigureLoopForm.cs: -------------------------------------------------------------------------------- 1 | using UmaMusumeAudio; 2 | 3 | namespace UmaMusumeExplorer.Controls.AudioPlayer 4 | { 5 | partial class ConfigureLoopForm : Form 6 | { 7 | private readonly UmaWaveStream hcaWaveStream; 8 | 9 | public ConfigureLoopForm(UmaWaveStream waveStream) 10 | { 11 | InitializeComponent(); 12 | 13 | hcaWaveStream = waveStream; 14 | } 15 | 16 | private void LoopModifyForm_Load(object sender, EventArgs e) 17 | { 18 | LoadValues(); 19 | } 20 | 21 | private void OKButton_Click(object sender, EventArgs e) 22 | { 23 | hcaWaveStream.Loop = loopEnabledCheckBox.Checked; 24 | hcaWaveStream.LoopStartSample = (long)startSampleNumericUpDown.Value; 25 | hcaWaveStream.LoopEndSample = (long)endSampleNumericUpDown.Value; 26 | 27 | Close(); 28 | } 29 | 30 | private void ResetButton_Click(object sender, EventArgs e) 31 | { 32 | hcaWaveStream.ResetLoop(); 33 | LoadValues(); 34 | } 35 | 36 | private void LoadValues() 37 | { 38 | loopEnabledCheckBox.Checked = hcaWaveStream.Loop; 39 | startSampleNumericUpDown.Value = hcaWaveStream.LoopStartSample; 40 | endSampleNumericUpDown.Value = hcaWaveStream.LoopEndSample; 41 | } 42 | 43 | private void CancelButton_Click(object sender, EventArgs e) 44 | { 45 | Close(); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/AudioPlayer/MultipleExportDialog.cs: -------------------------------------------------------------------------------- 1 | using NAudio.Wave; 2 | using System.ComponentModel; 3 | using UmaMusumeAudio; 4 | using UmaMusumeExplorer.Controls.AudioPlayer.Classes; 5 | 6 | namespace UmaMusumeExplorer.Controls.AudioPlayer 7 | { 8 | public partial class MultipleExportDialog : Form 9 | { 10 | private readonly AudioSource[] sources; 11 | private readonly string outputPath; 12 | 13 | public MultipleExportDialog(AudioSource[] audioSources, string outputDirectory) 14 | { 15 | InitializeComponent(); 16 | 17 | sources = audioSources; 18 | outputPath = outputDirectory; 19 | 20 | exportBackgroundWorker.RunWorkerAsync(); 21 | } 22 | 23 | private void ExportBackgroundWorker_DoWork(object sender, DoWorkEventArgs e) 24 | { 25 | int currentFile = 1; 26 | 27 | foreach (var audioSource in sources) 28 | { 29 | if (exportBackgroundWorker.CancellationPending) 30 | { 31 | e.Cancel = true; 32 | break; 33 | } 34 | 35 | State state; 36 | state.Name = audioSource.Name; 37 | state.CurrentFile = currentFile; 38 | 39 | exportBackgroundWorker.ReportProgress((int)(((float)currentFile / sources.Length) * 100), state); 40 | 41 | if (audioSource.Tracks.Length > 1) 42 | { 43 | string directory = Path.Combine(outputPath, audioSource.Name); 44 | Directory.CreateDirectory(directory); 45 | 46 | foreach (var track in audioSource.Tracks) 47 | { 48 | UmaWaveStream waveStream = (UmaWaveStream)track.WaveStream; 49 | waveStream.Loop = false; 50 | WaveFileWriter.CreateWaveFile16(Path.Combine(directory, track.Name + ".wav"), waveStream.ToSampleProvider()); 51 | } 52 | } 53 | else 54 | { 55 | IAudioTrack audioTrack = audioSource.Tracks[0]; 56 | UmaWaveStream waveStream = (UmaWaveStream)audioTrack.WaveStream; 57 | waveStream.Loop = false; 58 | WaveFileWriter.CreateWaveFile16(Path.Combine(outputPath, audioTrack.Name + ".wav"), waveStream.ToSampleProvider()); 59 | } 60 | 61 | currentFile++; 62 | } 63 | } 64 | 65 | private void ExportBackgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e) 66 | { 67 | progressBar.Value = e.ProgressPercentage; 68 | 69 | if (e.UserState is not State state) return; 70 | 71 | currentFileLabel.Text = "Exporing " + state.Name; 72 | progressLabel.Text = $"{state.CurrentFile} of {sources.Length}"; 73 | } 74 | 75 | private void ExportBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 76 | { 77 | if (e.Cancelled) 78 | MessageBox.Show("Export cancelled.", "Cancelled", MessageBoxButtons.OK, MessageBoxIcon.Information); 79 | else 80 | MessageBox.Show("Export complete.", "Success", MessageBoxButtons.OK, MessageBoxIcon.Information); 81 | 82 | Close(); 83 | } 84 | 85 | private void CancelButton_Click(object sender, EventArgs e) 86 | { 87 | exportBackgroundWorker.CancelAsync(); 88 | } 89 | 90 | struct State 91 | { 92 | public string Name; 93 | public int CurrentFile; 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/CharacterInfo/CharacterInfoControl.Designer.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace UmaMusumeExplorer.Controls.CharacterInfo 3 | { 4 | partial class CharacterInfoControl 5 | { 6 | /// 7 | /// Required designer variable. 8 | /// 9 | private System.ComponentModel.IContainer components = null; 10 | 11 | /// 12 | /// Clean up any resources being used. 13 | /// 14 | /// true if managed resources should be disposed; otherwise, false. 15 | protected override void Dispose(bool disposing) 16 | { 17 | if (disposing && (components != null)) 18 | { 19 | components.Dispose(); 20 | } 21 | base.Dispose(disposing); 22 | } 23 | 24 | #region Component Designer generated code 25 | 26 | /// 27 | /// Required method for Designer support - do not modify 28 | /// the contents of this method with the code editor. 29 | /// 30 | private void InitializeComponent() 31 | { 32 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(CharacterInfoControl)); 33 | selectLabel = new Label(); 34 | goButton = new Button(); 35 | charaListComboBox = new ComboBox(); 36 | markPlayableCheckBox = new CheckBox(); 37 | characterItemsPanel = new Common.CharacterItemsPanel(); 38 | SuspendLayout(); 39 | // 40 | // selectLabel 41 | // 42 | resources.ApplyResources(selectLabel, "selectLabel"); 43 | selectLabel.Name = "selectLabel"; 44 | // 45 | // goButton 46 | // 47 | resources.ApplyResources(goButton, "goButton"); 48 | goButton.Name = "goButton"; 49 | goButton.UseVisualStyleBackColor = true; 50 | goButton.Click += GoButton_Click; 51 | // 52 | // charaListComboBox 53 | // 54 | charaListComboBox.AutoCompleteMode = AutoCompleteMode.SuggestAppend; 55 | charaListComboBox.AutoCompleteSource = AutoCompleteSource.ListItems; 56 | charaListComboBox.FormattingEnabled = true; 57 | resources.ApplyResources(charaListComboBox, "charaListComboBox"); 58 | charaListComboBox.Name = "charaListComboBox"; 59 | // 60 | // markPlayableCheckBox 61 | // 62 | resources.ApplyResources(markPlayableCheckBox, "markPlayableCheckBox"); 63 | markPlayableCheckBox.Name = "markPlayableCheckBox"; 64 | markPlayableCheckBox.UseVisualStyleBackColor = true; 65 | markPlayableCheckBox.CheckedChanged += ShowPlayableCheckBox_CheckedChanged; 66 | // 67 | // characterItemsPanel 68 | // 69 | resources.ApplyResources(characterItemsPanel, "characterItemsPanel"); 70 | characterItemsPanel.Items = null; 71 | characterItemsPanel.Name = "characterItemsPanel"; 72 | // 73 | // CharacterInfoControl 74 | // 75 | AutoScaleMode = AutoScaleMode.Inherit; 76 | Controls.Add(characterItemsPanel); 77 | Controls.Add(markPlayableCheckBox); 78 | Controls.Add(charaListComboBox); 79 | Controls.Add(goButton); 80 | Controls.Add(selectLabel); 81 | Name = "CharacterInfoControl"; 82 | resources.ApplyResources(this, "$this"); 83 | Load += CharacterInfoControl_Load; 84 | ResumeLayout(false); 85 | PerformLayout(); 86 | } 87 | 88 | #endregion 89 | private Label selectLabel; 90 | private Button goButton; 91 | private ComboBox charaListComboBox; 92 | private CheckBox markPlayableCheckBox; 93 | private Common.CharacterItemsPanel characterItemsPanel; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/CharacterInfo/CharacterInfoControl.cs: -------------------------------------------------------------------------------- 1 | using UmaMusumeData.Tables; 2 | using UmaMusumeExplorer.Controls.CharacterInfo.Classes; 3 | using UmaMusumeExplorer.Controls.Common; 4 | using UmaMusumeExplorer.Game; 5 | 6 | namespace UmaMusumeExplorer.Controls.CharacterInfo 7 | { 8 | partial class CharacterInfoControl : UserControl 9 | { 10 | private readonly IEnumerable charaDatas = AssetTables.CharaDatas; 11 | 12 | public CharacterInfoControl() 13 | { 14 | InitializeComponent(); 15 | 16 | characterItemsPanel.ItemClick += (s, e) => 17 | { 18 | if (s is not PictureBox pictureBox) return; 19 | if (pictureBox.Tag is not CharaData charaData) return; 20 | 21 | CharacterInfoForm details = new(charaData); 22 | ControlHelpers.ShowFormCenter(details, this); 23 | }; 24 | } 25 | 26 | private void CharacterInfoControl_Load(object sender, EventArgs e) 27 | { 28 | characterItemsPanel.Items = charaDatas; 29 | 30 | foreach (var item in charaDatas) 31 | { 32 | charaListComboBox.Items.Add(new CharaComboBoxItem(item)); 33 | } 34 | } 35 | 36 | private void GoButton_Click(object sender, EventArgs e) 37 | { 38 | if (charaListComboBox.SelectedItem is CharaComboBoxItem item) ControlHelpers.ShowFormCenter(new CharacterInfoForm(item.CharaData), this); 39 | } 40 | 41 | private void ShowPlayableCheckBox_CheckedChanged(object sender, EventArgs e) 42 | { 43 | foreach (HighlightPictureBox hpb in characterItemsPanel.Controls) 44 | { 45 | hpb.ShowHighlight = markPlayableCheckBox.Checked; 46 | } 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/CharacterInfo/CharacterInfoForm.cs: -------------------------------------------------------------------------------- 1 | using UmaMusumeData; 2 | using UmaMusumeData.Tables; 3 | using UmaMusumeExplorer.Game; 4 | 5 | namespace UmaMusumeExplorer.Controls.CharacterInfo 6 | { 7 | partial class CharacterInfoForm : Form 8 | { 9 | public CharacterInfoForm(CharaData chara) 10 | { 11 | InitializeComponent(); 12 | 13 | cardInfoControl.CharaData = chara; 14 | voiceLinesControl.CharaId = chara.Id; 15 | songsControl.CharaId = chara.Id; 16 | supportCardsControl.CharaId = chara.Id; 17 | 18 | Text = AssetTables.GetText(TextCategory.MasterCharaName, chara.Id); 19 | } 20 | 21 | private void CharacterInfoForm_FormClosing(object sender, FormClosingEventArgs e) 22 | { 23 | voiceLinesControl.StopAllPlayback(); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/CharacterInfo/CharacterVoiceListItemControl.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace UmaMusumeExplorer.Controls.CharacterInfo 2 | { 3 | partial class CharacterVoiceListItemControl 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Component Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | playButton = new System.Windows.Forms.Button(); 32 | idLabel = new System.Windows.Forms.Label(); 33 | checkBox = new System.Windows.Forms.CheckBox(); 34 | voiceLineTextLabel = new ProgressLabel(); 35 | SuspendLayout(); 36 | // 37 | // playButton 38 | // 39 | playButton.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right; 40 | playButton.Location = new System.Drawing.Point(325, 25); 41 | playButton.Name = "playButton"; 42 | playButton.Size = new System.Drawing.Size(45, 45); 43 | playButton.TabIndex = 1; 44 | playButton.Text = "Play"; 45 | playButton.UseVisualStyleBackColor = true; 46 | // 47 | // idLabel 48 | // 49 | idLabel.AutoSize = true; 50 | idLabel.Location = new System.Drawing.Point(24, 3); 51 | idLabel.Margin = new System.Windows.Forms.Padding(3); 52 | idLabel.Name = "idLabel"; 53 | idLabel.Size = new System.Drawing.Size(18, 15); 54 | idLabel.TabIndex = 2; 55 | idLabel.Text = "ID"; 56 | // 57 | // checkBox 58 | // 59 | checkBox.AutoSize = true; 60 | checkBox.Location = new System.Drawing.Point(3, 4); 61 | checkBox.Name = "checkBox"; 62 | checkBox.Size = new System.Drawing.Size(15, 14); 63 | checkBox.TabIndex = 3; 64 | checkBox.UseVisualStyleBackColor = true; 65 | // 66 | // voiceLineTextLabel 67 | // 68 | voiceLineTextLabel.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right; 69 | voiceLineTextLabel.Font = new System.Drawing.Font("Segoe UI", 11.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); 70 | voiceLineTextLabel.Location = new System.Drawing.Point(3, 24); 71 | voiceLineTextLabel.Margin = new System.Windows.Forms.Padding(3); 72 | voiceLineTextLabel.Name = "voiceLineTextLabel"; 73 | voiceLineTextLabel.Progress = 0F; 74 | voiceLineTextLabel.Size = new System.Drawing.Size(316, 68); 75 | voiceLineTextLabel.TabIndex = 4; 76 | voiceLineTextLabel.Text = "Voice line"; 77 | voiceLineTextLabel.Click += VoiceLineTextLabel_DoubleClick; 78 | // 79 | // CharacterVoiceListItemControl 80 | // 81 | AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); 82 | AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 83 | Controls.Add(voiceLineTextLabel); 84 | Controls.Add(checkBox); 85 | Controls.Add(idLabel); 86 | Controls.Add(playButton); 87 | Name = "CharacterVoiceListItemControl"; 88 | Size = new System.Drawing.Size(373, 95); 89 | Click += ClickHit; 90 | DoubleClick += ClickHit; 91 | ResumeLayout(false); 92 | PerformLayout(); 93 | } 94 | 95 | #endregion 96 | private System.Windows.Forms.Button playButton; 97 | private System.Windows.Forms.Label idLabel; 98 | private System.Windows.Forms.CheckBox checkBox; 99 | private ProgressLabel voiceLineTextLabel; 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/CharacterInfo/CharacterVoiceListItemControl.cs: -------------------------------------------------------------------------------- 1 | using CriWareLibrary; 2 | using NAudio.Wave; 3 | using UmaMusumeAudio; 4 | using UmaMusumeData; 5 | using UmaMusumeData.Tables; 6 | using UmaMusumeExplorer.Game; 7 | using Timer = System.Windows.Forms.Timer; 8 | 9 | namespace UmaMusumeExplorer.Controls.CharacterInfo 10 | { 11 | public partial class CharacterVoiceListItemControl : UserControl 12 | { 13 | private WaveStream? voiceWaveStream; 14 | private Timer? animationTimer; 15 | private bool processingClick = false; 16 | 17 | public CharacterVoiceListItemControl() 18 | { 19 | InitializeComponent(); 20 | 21 | DoubleBuffered = true; 22 | 23 | idLabel.Click += ClickHit; 24 | idLabel.DoubleClick += ClickHit; 25 | } 26 | 27 | public CharacterVoiceListItemControl(CharacterSystemText systemText, IWavePlayer waveOut) : this() 28 | { 29 | CharacterSystemText = systemText; 30 | 31 | idLabel.Text = systemText.VoiceId.ToString(); 32 | voiceLineTextLabel.Text = systemText.Text; 33 | playButton.Click += (s, e) => 34 | { 35 | waveOut.PlaybackStopped -= PlaybackStopped; 36 | 37 | if (waveOut.PlaybackState == PlaybackState.Playing) 38 | waveOut.Stop(); 39 | 40 | voiceWaveStream?.Dispose(); 41 | voiceWaveStream = GetWaveStream(); 42 | 43 | voiceLineTextLabel.Progress = 0; 44 | animationTimer?.Stop(); 45 | animationTimer?.Dispose(); 46 | 47 | animationTimer = new() 48 | { 49 | Enabled = true, 50 | Interval = 50 51 | }; 52 | animationTimer.Tick += (s, e) => 53 | { 54 | if (voiceWaveStream is not null) 55 | voiceLineTextLabel.Progress = (float)voiceWaveStream.Position / voiceWaveStream.Length; 56 | }; 57 | animationTimer.Start(); 58 | 59 | waveOut.PlaybackStopped += PlaybackStopped; 60 | 61 | waveOut.Init(voiceWaveStream); 62 | waveOut.Play(); 63 | }; 64 | } 65 | 66 | public CharacterSystemText? CharacterSystemText { get; } 67 | 68 | public bool Checked => checkBox.Checked; 69 | 70 | public WaveStream? GetWaveStream() 71 | { 72 | if (CharacterSystemText is null) return null; 73 | 74 | ManifestEntry? acbAsset = AssetTables.AudioAssetEntries.FirstOrDefault(a => a.BaseName == CharacterSystemText.CueSheet + ".acb"); 75 | ManifestEntry? awbAsset = AssetTables.AudioAssetEntries.FirstOrDefault(a => a.BaseName == CharacterSystemText.CueSheet + ".awb"); 76 | 77 | if (acbAsset is null && awbAsset is null) return null; 78 | 79 | string acbPath = UmaDataHelper.GetPath(acbAsset); 80 | string awbPath = UmaDataHelper.GetPath(awbAsset); 81 | 82 | if (!File.Exists(awbPath)) return null; 83 | 84 | AcbReader acb = new(File.OpenRead(acbPath)); 85 | AwbReader awb = new(File.OpenRead(awbPath)); 86 | 87 | return new UmaWaveStream(awb, acb.GetWaveIdFromCueId(CharacterSystemText.CueId)); 88 | } 89 | 90 | private void ClickHit(object? sender, EventArgs e) 91 | { 92 | if (processingClick) return; 93 | 94 | processingClick = true; 95 | 96 | try 97 | { 98 | if (e is not MouseEventArgs mouseEventArgs) return; 99 | if (mouseEventArgs.Button != MouseButtons.Left) return; 100 | 101 | checkBox.Checked = !checkBox.Checked; 102 | } 103 | finally 104 | { 105 | processingClick = false; 106 | } 107 | } 108 | 109 | private void VoiceLineTextLabel_DoubleClick(object? sender, EventArgs e) 110 | { 111 | Clipboard.SetText(voiceLineTextLabel.Text); 112 | } 113 | 114 | private void PlaybackStopped(object? sender, EventArgs e) 115 | { 116 | voiceLineTextLabel.Progress = 0; 117 | animationTimer?.Stop(); 118 | } 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/CharacterInfo/CircleControl.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing.Drawing2D; 2 | using Rectangle = System.Drawing.Rectangle; 3 | 4 | namespace UmaMusumeExplorer.Controls.CharacterInfo 5 | { 6 | internal class CircleControl : Label 7 | { 8 | public CircleControl() : base() 9 | { 10 | } 11 | 12 | protected override void OnPaint(PaintEventArgs e) 13 | { 14 | e.Graphics.SmoothingMode = SmoothingMode.AntiAlias; 15 | 16 | Rectangle clip = e.ClipRectangle; 17 | clip.Width -= 1; 18 | clip.Height -= 1; 19 | 20 | e.Graphics.FillEllipse(new SolidBrush(ForeColor), clip); 21 | 22 | base.OnPaint(e); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/CharacterInfo/Classes/CharaComboBoxItem.cs: -------------------------------------------------------------------------------- 1 | using UmaMusumeData; 2 | using UmaMusumeData.Tables; 3 | using UmaMusumeExplorer.Game; 4 | 5 | namespace UmaMusumeExplorer.Controls.CharacterInfo.Classes 6 | { 7 | class CharaComboBoxItem 8 | { 9 | public CharaComboBoxItem(CharaData chara) 10 | { 11 | CharaData = chara; 12 | } 13 | 14 | public CharaData CharaData { get; } 15 | 16 | public override string ToString() 17 | { 18 | return CharaData.Id.ToString() + ": " + AssetTables.GetText(TextCategory.MasterCharaName, CharaData.Id); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/CharacterInfo/Classes/CostumeComboBoxItem.cs: -------------------------------------------------------------------------------- 1 | using UmaMusumeData; 2 | using UmaMusumeData.Tables; 3 | using UmaMusumeExplorer.Game; 4 | 5 | namespace UmaMusumeExplorer.Controls.CharacterInfo.Classes 6 | { 7 | class CostumeComboBoxItem 8 | { 9 | public CostumeComboBoxItem(CardData cardData) 10 | { 11 | CardData = cardData; 12 | } 13 | 14 | public CardData CardData { get; } 15 | 16 | public override string ToString() 17 | { 18 | return AssetTables.GetText(TextCategory.MasterCardTitleName, CardData.Id); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/CharacterInfo/Classes/Rank.cs: -------------------------------------------------------------------------------- 1 | namespace UmaMusumeExplorer.Controls.CharacterInfo.Classes 2 | { 3 | public enum Rank 4 | { 5 | Unknown, 6 | G, 7 | F, 8 | E, 9 | D, 10 | C, 11 | B, 12 | A, 13 | S 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/CharacterInfo/Classes/RarityComboBoxItem.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | using UmaMusumeData.Tables; 3 | 4 | namespace UmaMusumeExplorer.Controls.CharacterInfo.Classes 5 | { 6 | class RarityComboBoxItem 7 | { 8 | public RarityComboBoxItem(CardRarityData cardRarityData) 9 | { 10 | CardRarityData = cardRarityData; 11 | } 12 | 13 | public CardRarityData CardRarityData { get; } 14 | 15 | public override string ToString() 16 | { 17 | StringBuilder starsString = new(); 18 | for (int i = 0; i < CardRarityData.Rarity; i++) 19 | { 20 | starsString.Append('★'); 21 | } 22 | 23 | return starsString.ToString(); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/CharacterInfo/Classes/SkillBackground.cs: -------------------------------------------------------------------------------- 1 | namespace UmaMusumeExplorer.Controls.CharacterInfo.Classes 2 | { 3 | public enum SkillBackground 4 | { 5 | Rarity1 = 1, 6 | Rarity2 = 2, 7 | Rarity3 = 3, 8 | Rarity4 = 4, 9 | Rarity5 = 5, 10 | Evolution = 6 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/CharacterInfo/Classes/SkillColorGenerator.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing.Drawing2D; 2 | using Color = System.Drawing.Color; 3 | using Rectangle = System.Drawing.Rectangle; 4 | 5 | namespace UmaMusumeExplorer.Controls.CharacterInfo.Classes 6 | { 7 | internal static class SkillColorGenerator 8 | { 9 | public static Brush ColorFromType(SkillBackground rarity, Rectangle colorBounds, out Brush backgroundBrush) 10 | { 11 | Color[] colors = { Color.White, Color.LightSteelBlue }; 12 | float[] positions = { 0F, 1F }; 13 | 14 | backgroundBrush = new SolidBrush(Color.LightSteelBlue); 15 | 16 | bool duplicateBackground = false; 17 | 18 | switch (rarity) 19 | { 20 | case SkillBackground.Rarity2: 21 | colors = new[] 22 | { 23 | Color.LightYellow, 24 | Color.Gold 25 | }; 26 | backgroundBrush = new SolidBrush(Color.Gold); 27 | break; 28 | case SkillBackground.Rarity3: 29 | case SkillBackground.Rarity4: 30 | case SkillBackground.Rarity5: 31 | colors = new[] { 32 | Color.LightGreen, 33 | Color.DeepSkyBlue, 34 | Color.BlueViolet, 35 | Color.DeepPink 36 | }; 37 | positions = new[] { 0F, 1 / 3F, 2 / 3F, 1F }; 38 | duplicateBackground = true; 39 | break; 40 | case SkillBackground.Evolution: 41 | colors = new[] 42 | { 43 | Color.Pink, 44 | Color.HotPink 45 | }; 46 | backgroundBrush = new SolidBrush(Color.HotPink); 47 | break; 48 | default: 49 | break; 50 | } 51 | 52 | LinearGradientBrush linearGradientBrush = new(colorBounds, Color.White, Color.White, LinearGradientMode.Horizontal); 53 | 54 | ColorBlend colorBlend = new(); 55 | colorBlend.Positions = positions; 56 | colorBlend.Colors = colors; 57 | linearGradientBrush.InterpolationColors = colorBlend; 58 | 59 | if (duplicateBackground) 60 | backgroundBrush = linearGradientBrush; 61 | 62 | return linearGradientBrush; 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/CharacterInfo/DoubleBufferedTableLayoutPanel.cs: -------------------------------------------------------------------------------- 1 | namespace UmaMusumeExplorer.Controls.CharacterInfo 2 | { 3 | internal class DoubleBufferedTableLayoutPanel : TableLayoutPanel 4 | { 5 | public DoubleBufferedTableLayoutPanel() 6 | { 7 | DoubleBuffered = true; 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/CharacterInfo/ProgressLabel.cs: -------------------------------------------------------------------------------- 1 | using Color = System.Drawing.Color; 2 | using Rectangle = System.Drawing.Rectangle; 3 | 4 | namespace UmaMusumeExplorer.Controls.CharacterInfo 5 | { 6 | internal class ProgressLabel : Label 7 | { 8 | private float progress; 9 | 10 | public float Progress 11 | { 12 | get => progress; 13 | set 14 | { 15 | progress = value; 16 | Refresh(); 17 | } 18 | } 19 | 20 | protected override void OnPaint(PaintEventArgs e) 21 | { 22 | //e.Graphics.Clear(BackColor); 23 | Rectangle drawRectangle = e.ClipRectangle; 24 | drawRectangle.Width = (int)(drawRectangle.Width * progress); 25 | e.Graphics.FillRectangle(new SolidBrush(Color.LightGreen), drawRectangle); 26 | 27 | base.OnPaint(e); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/CharacterInfo/RankedLabel.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace UmaMusumeExplorer.Controls.CharacterInfo 2 | { 3 | partial class RankedLabel 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Component Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.textLabel = new System.Windows.Forms.Label(); 32 | this.rankLabel = new System.Windows.Forms.Label(); 33 | this.tableLayoutPanel = new System.Windows.Forms.TableLayoutPanel(); 34 | this.tableLayoutPanel.SuspendLayout(); 35 | this.SuspendLayout(); 36 | // 37 | // textLabel 38 | // 39 | this.textLabel.Anchor = System.Windows.Forms.AnchorStyles.None; 40 | this.textLabel.AutoSize = true; 41 | this.textLabel.Location = new System.Drawing.Point(8, 6); 42 | this.textLabel.Margin = new System.Windows.Forms.Padding(0); 43 | this.textLabel.Name = "textLabel"; 44 | this.textLabel.Size = new System.Drawing.Size(71, 15); 45 | this.textLabel.TabIndex = 0; 46 | this.textLabel.Text = "rankedLabel"; 47 | // 48 | // rankLabel 49 | // 50 | this.rankLabel.Anchor = System.Windows.Forms.AnchorStyles.None; 51 | this.rankLabel.AutoSize = true; 52 | this.rankLabel.Font = new System.Drawing.Font("Segoe UI", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point); 53 | this.rankLabel.Location = new System.Drawing.Point(99, 3); 54 | this.rankLabel.Margin = new System.Windows.Forms.Padding(0); 55 | this.rankLabel.Name = "rankLabel"; 56 | this.rankLabel.Size = new System.Drawing.Size(21, 21); 57 | this.rankLabel.TabIndex = 1; 58 | this.rankLabel.Text = "G"; 59 | // 60 | // tableLayoutPanel 61 | // 62 | this.tableLayoutPanel.ColumnCount = 2; 63 | this.tableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 66.66666F)); 64 | this.tableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333F)); 65 | this.tableLayoutPanel.Controls.Add(this.textLabel, 0, 0); 66 | this.tableLayoutPanel.Controls.Add(this.rankLabel, 1, 0); 67 | this.tableLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill; 68 | this.tableLayoutPanel.Location = new System.Drawing.Point(0, 0); 69 | this.tableLayoutPanel.Name = "tableLayoutPanel"; 70 | this.tableLayoutPanel.RowCount = 1; 71 | this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); 72 | this.tableLayoutPanel.Size = new System.Drawing.Size(132, 28); 73 | this.tableLayoutPanel.TabIndex = 0; 74 | // 75 | // RankedLabel 76 | // 77 | this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); 78 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 79 | this.Controls.Add(this.tableLayoutPanel); 80 | this.Name = "RankedLabel"; 81 | this.Size = new System.Drawing.Size(132, 28); 82 | this.tableLayoutPanel.ResumeLayout(false); 83 | this.tableLayoutPanel.PerformLayout(); 84 | this.ResumeLayout(false); 85 | 86 | } 87 | 88 | #endregion 89 | 90 | private System.Windows.Forms.Label textLabel; 91 | private System.Windows.Forms.Label rankLabel; 92 | private System.Windows.Forms.TableLayoutPanel tableLayoutPanel; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/CharacterInfo/RankedLabel.cs: -------------------------------------------------------------------------------- 1 | using UmaMusumeExplorer.Controls.CharacterInfo.Classes; 2 | using Color = System.Drawing.Color; 3 | 4 | namespace UmaMusumeExplorer.Controls.CharacterInfo 5 | { 6 | partial class RankedLabel : UserControl 7 | { 8 | private Rank rank; 9 | 10 | public RankedLabel() 11 | { 12 | InitializeComponent(); 13 | 14 | Rank = Rank.Unknown; 15 | } 16 | 17 | public Rank Rank 18 | { 19 | get 20 | { 21 | return rank; 22 | } 23 | set 24 | { 25 | rank = value; 26 | 27 | switch (rank) 28 | { 29 | case Rank.G: 30 | rankLabel.Text = "G"; 31 | rankLabel.ForeColor = Color.DarkGray; 32 | break; 33 | case Rank.F: 34 | rankLabel.Text = "F"; 35 | rankLabel.ForeColor = Color.SlateBlue; 36 | break; 37 | case Rank.E: 38 | rankLabel.Text = "E"; 39 | rankLabel.ForeColor = Color.DarkViolet; 40 | break; 41 | case Rank.D: 42 | rankLabel.Text = "D"; 43 | rankLabel.ForeColor = Color.DeepSkyBlue; 44 | break; 45 | case Rank.C: 46 | rankLabel.Text = "C"; 47 | rankLabel.ForeColor = Color.LimeGreen; 48 | break; 49 | case Rank.B: 50 | rankLabel.Text = "B"; 51 | rankLabel.ForeColor = Color.HotPink; 52 | break; 53 | case Rank.A: 54 | rankLabel.Text = "A"; 55 | rankLabel.ForeColor = Color.OrangeRed; 56 | break; 57 | case Rank.S: 58 | rankLabel.Text = "S"; 59 | rankLabel.ForeColor = Color.Goldenrod; 60 | break; 61 | default: 62 | rankLabel.Text = "?"; 63 | rankLabel.ForeColor = Color.Black; 64 | break; 65 | } 66 | 67 | Invalidate(); 68 | } 69 | } 70 | 71 | //public override string Text { get => base.Text; set => base.Text = value; } 72 | 73 | public new string Text 74 | { 75 | get 76 | { 77 | return textLabel.Text; 78 | } 79 | set 80 | { 81 | textLabel.Text = value; 82 | Invalidate(); 83 | } 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/CharacterInfo/RankedLabel.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | text/microsoft-resx 50 | 51 | 52 | 2.0 53 | 54 | 55 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 56 | 57 | 58 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 59 | 60 | 61 | True 62 | 63 | 64 | True 65 | 66 | 67 | True 68 | 69 | 70 | True 71 | 72 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/CharacterInfo/SkillEvolutionConditionContainer.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace UmaMusumeExplorer.Controls.CharacterInfo 2 | { 3 | partial class SkillEvolutionConditionContainer 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Component Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | conditionNumberLabel = new System.Windows.Forms.Label(); 32 | conditionDescription = new System.Windows.Forms.Label(); 33 | conditionsPanel = new System.Windows.Forms.FlowLayoutPanel(); 34 | SuspendLayout(); 35 | // 36 | // conditionNumberLabel 37 | // 38 | conditionNumberLabel.BackColor = System.Drawing.SystemColors.ControlLight; 39 | conditionNumberLabel.Location = new System.Drawing.Point(15, 15); 40 | conditionNumberLabel.Margin = new System.Windows.Forms.Padding(15, 15, 15, 0); 41 | conditionNumberLabel.Name = "conditionNumberLabel"; 42 | conditionNumberLabel.Size = new System.Drawing.Size(99, 15); 43 | conditionNumberLabel.TabIndex = 0; 44 | conditionNumberLabel.Text = "Condition 0"; 45 | conditionNumberLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; 46 | // 47 | // conditionDescription 48 | // 49 | conditionDescription.AutoSize = true; 50 | conditionDescription.Location = new System.Drawing.Point(144, 15); 51 | conditionDescription.Margin = new System.Windows.Forms.Padding(15, 15, 15, 0); 52 | conditionDescription.Name = "conditionDescription"; 53 | conditionDescription.Size = new System.Drawing.Size(210, 15); 54 | conditionDescription.TabIndex = 0; 55 | conditionDescription.Text = "Satisfy one of the following conditions"; 56 | // 57 | // conditionsPanel 58 | // 59 | conditionsPanel.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right; 60 | conditionsPanel.Location = new System.Drawing.Point(15, 45); 61 | conditionsPanel.Margin = new System.Windows.Forms.Padding(15); 62 | conditionsPanel.Name = "conditionsPanel"; 63 | conditionsPanel.Size = new System.Drawing.Size(451, 50); 64 | conditionsPanel.TabIndex = 1; 65 | // 66 | // SkillEvolutionConditionContainer 67 | // 68 | AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); 69 | AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 70 | BackColor = System.Drawing.SystemColors.ControlLightLight; 71 | Controls.Add(conditionsPanel); 72 | Controls.Add(conditionDescription); 73 | Controls.Add(conditionNumberLabel); 74 | Name = "SkillEvolutionConditionContainer"; 75 | Size = new System.Drawing.Size(481, 110); 76 | Load += SkillEvolutionConditionMultiple_Load; 77 | ResumeLayout(false); 78 | PerformLayout(); 79 | } 80 | 81 | #endregion 82 | 83 | private System.Windows.Forms.Label conditionNumberLabel; 84 | private System.Windows.Forms.Label conditionDescription; 85 | private System.Windows.Forms.FlowLayoutPanel conditionsPanel; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/CharacterInfo/SkillEvolutionConditionContainer.cs: -------------------------------------------------------------------------------- 1 | using UmaMusumeData; 2 | using UmaMusumeData.Tables; 3 | using UmaMusumeExplorer.Game; 4 | 5 | namespace UmaMusumeExplorer.Controls.CharacterInfo 6 | { 7 | public partial class SkillEvolutionConditionContainer : UserControl 8 | { 9 | private readonly IEnumerable conditions; 10 | private readonly int defaultHeight; 11 | 12 | public SkillEvolutionConditionContainer(IEnumerable upgradeConditions) 13 | { 14 | InitializeComponent(); 15 | 16 | SkillUpgradeCondition firstCondition = upgradeConditions.First(); 17 | 18 | conditionNumberLabel.Text = $"Condition {firstCondition.Num}"; 19 | conditions = upgradeConditions; 20 | 21 | defaultHeight = conditionNumberLabel.Top + conditionNumberLabel.Height + conditionNumberLabel.Margin.Vertical; 22 | Height = defaultHeight; 23 | 24 | if (upgradeConditions.Count() == 1) 25 | { 26 | conditionDescription.Text = AssetTables.GetText(TextCategory.SkillUpgrade1, firstCondition.Id); 27 | conditionsPanel.Height = 0; 28 | } 29 | } 30 | 31 | private void SkillEvolutionConditionMultiple_Load(object sender, EventArgs e) 32 | { 33 | if (conditions.Count() > 1) 34 | { 35 | conditionsPanel.Height = 0; 36 | foreach (var condition in conditions) 37 | { 38 | SkillEvolutionConditionItem conditionSingle = new(condition); 39 | conditionSingle.Width = conditionsPanel.Width - conditionSingle.Margin.Horizontal; 40 | conditionsPanel.Controls.Add(conditionSingle); 41 | 42 | conditionsPanel.Height += conditionSingle.Height + conditionSingle.Margin.Vertical; 43 | } 44 | 45 | Height += conditionsPanel.Height + conditionsPanel.Margin.Bottom; 46 | } 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/CharacterInfo/SkillEvolutionConditionItem.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace UmaMusumeExplorer.Controls.CharacterInfo 2 | { 3 | partial class SkillEvolutionConditionItem 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Component Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | conditionLabel = new System.Windows.Forms.Label(); 32 | SuspendLayout(); 33 | // 34 | // conditionLabel 35 | // 36 | conditionLabel.AutoSize = true; 37 | conditionLabel.Location = new System.Drawing.Point(15, 15); 38 | conditionLabel.Margin = new System.Windows.Forms.Padding(15, 15, 15, 0); 39 | conditionLabel.Name = "conditionLabel"; 40 | conditionLabel.Size = new System.Drawing.Size(60, 15); 41 | conditionLabel.TabIndex = 2; 42 | conditionLabel.Text = "Condition"; 43 | // 44 | // SkillEvolutionConditionSingle 45 | // 46 | AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); 47 | AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 48 | AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; 49 | BackColor = System.Drawing.SystemColors.ControlLight; 50 | Controls.Add(conditionLabel); 51 | Name = "SkillEvolutionConditionSingle"; 52 | Size = new System.Drawing.Size(352, 45); 53 | ResumeLayout(false); 54 | PerformLayout(); 55 | } 56 | 57 | #endregion 58 | 59 | private System.Windows.Forms.Label conditionLabel; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/CharacterInfo/SkillEvolutionConditionItem.cs: -------------------------------------------------------------------------------- 1 | using UmaMusumeData; 2 | using UmaMusumeData.Tables; 3 | using UmaMusumeExplorer.Game; 4 | 5 | namespace UmaMusumeExplorer.Controls.CharacterInfo 6 | { 7 | public partial class SkillEvolutionConditionItem : UserControl 8 | { 9 | public SkillEvolutionConditionItem(SkillUpgradeCondition condition) 10 | { 11 | InitializeComponent(); 12 | 13 | conditionLabel.Text = AssetTables.GetText(TextCategory.SkillUpgrade1, condition.Id); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/CharacterInfo/SkillEvolutionDetailsForm.cs: -------------------------------------------------------------------------------- 1 | using System.Data; 2 | using UmaMusumeData.Tables; 3 | using UmaMusumeExplorer.Game; 4 | 5 | namespace UmaMusumeExplorer.Controls.CharacterInfo 6 | { 7 | public partial class SkillEvolutionDetailsForm : Form 8 | { 9 | private readonly IEnumerable skillUpgradeConditions = AssetTables.SkillUpgradeConditions; 10 | private readonly int evolutionSkillId; 11 | 12 | public SkillEvolutionDetailsForm(SkillData skill, SkillData? evolutionSkill) 13 | { 14 | InitializeComponent(); 15 | 16 | toEvolveSkill.Skill = skill; 17 | evolvedSkill.Skill = evolutionSkill; 18 | 19 | evolutionSkillId = evolutionSkill?.Id ?? 0; 20 | } 21 | 22 | private void SkillEvolutionDetailsForm_Load(object sender, EventArgs e) 23 | { 24 | IEnumerable matchingConditions = skillUpgradeConditions.Where(s => s.DescriptionId == evolutionSkillId); 25 | 26 | int previousNum = matchingConditions.First().Num; 27 | List currentConditions = new(); 28 | foreach (var condition in matchingConditions) 29 | { 30 | if (condition.Num != previousNum) 31 | { 32 | AddConditions(currentConditions); 33 | currentConditions.Clear(); 34 | } 35 | 36 | currentConditions.Add(condition); 37 | previousNum = condition.Num; 38 | } 39 | 40 | AddConditions(currentConditions); 41 | } 42 | 43 | private void AddConditions(IEnumerable currentConditions) 44 | { 45 | SkillEvolutionConditionContainer conditionMultiple = new(currentConditions); 46 | conditionMultiple.Width = evolveConditionsPanel.Width - conditionMultiple.Margin.Horizontal - SystemInformation.VerticalScrollBarWidth; 47 | evolveConditionsPanel.Controls.Add(conditionMultiple); 48 | } 49 | 50 | private void CloseButton_Click(object sender, EventArgs e) 51 | { 52 | Close(); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/CharacterInfo/SkillLarge.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace UmaMusumeExplorer.Controls.CharacterInfo 2 | { 3 | partial class SkillLarge 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Component Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | skillDescriptionLabel = new System.Windows.Forms.Label(); 32 | skillNameLabel = new System.Windows.Forms.Label(); 33 | iconPictureBox = new Common.HighQualityPictureBox(); 34 | ((System.ComponentModel.ISupportInitialize)iconPictureBox).BeginInit(); 35 | SuspendLayout(); 36 | // 37 | // skillDescriptionLabel 38 | // 39 | skillDescriptionLabel.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right; 40 | skillDescriptionLabel.BackColor = System.Drawing.Color.Transparent; 41 | skillDescriptionLabel.Font = new System.Drawing.Font("Segoe UI", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); 42 | skillDescriptionLabel.Location = new System.Drawing.Point(120, 39); 43 | skillDescriptionLabel.Name = "skillDescriptionLabel"; 44 | skillDescriptionLabel.Size = new System.Drawing.Size(372, 75); 45 | skillDescriptionLabel.TabIndex = 4; 46 | skillDescriptionLabel.Text = "Skill description"; 47 | // 48 | // skillNameLabel 49 | // 50 | skillNameLabel.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right; 51 | skillNameLabel.BackColor = System.Drawing.Color.Transparent; 52 | skillNameLabel.Font = new System.Drawing.Font("Segoe UI", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point); 53 | skillNameLabel.Location = new System.Drawing.Point(120, 18); 54 | skillNameLabel.Name = "skillNameLabel"; 55 | skillNameLabel.Size = new System.Drawing.Size(372, 21); 56 | skillNameLabel.TabIndex = 7; 57 | skillNameLabel.Text = "Skill name"; 58 | skillNameLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; 59 | // 60 | // iconPictureBox 61 | // 62 | iconPictureBox.BackColor = System.Drawing.Color.Transparent; 63 | iconPictureBox.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom; 64 | iconPictureBox.Location = new System.Drawing.Point(18, 18); 65 | iconPictureBox.Name = "iconPictureBox"; 66 | iconPictureBox.Size = new System.Drawing.Size(96, 96); 67 | iconPictureBox.TabIndex = 3; 68 | iconPictureBox.TabStop = false; 69 | // 70 | // SkillLarge 71 | // 72 | AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); 73 | AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 74 | AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; 75 | Controls.Add(skillDescriptionLabel); 76 | Controls.Add(skillNameLabel); 77 | Controls.Add(iconPictureBox); 78 | Name = "SkillLarge"; 79 | Padding = new System.Windows.Forms.Padding(15); 80 | Size = new System.Drawing.Size(510, 132); 81 | ((System.ComponentModel.ISupportInitialize)iconPictureBox).EndInit(); 82 | ResumeLayout(false); 83 | } 84 | 85 | #endregion 86 | private System.Windows.Forms.Label skillDescriptionLabel; 87 | private System.Windows.Forms.Label skillNameLabel; 88 | private Common.HighQualityPictureBox iconPictureBox; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/CharacterInfo/SkillLarge.cs: -------------------------------------------------------------------------------- 1 | using UmaMusumeData; 2 | using UmaMusumeData.Tables; 3 | using UmaMusumeExplorer.Controls.CharacterInfo.Classes; 4 | using UmaMusumeExplorer.Game; 5 | using Color = System.Drawing.Color; 6 | using Rectangle = System.Drawing.Rectangle; 7 | 8 | namespace UmaMusumeExplorer.Controls.CharacterInfo 9 | { 10 | public partial class SkillLarge : UserControl 11 | { 12 | public SkillData? skill; 13 | public SkillBackground background; 14 | 15 | public SkillLarge() 16 | { 17 | InitializeComponent(); 18 | } 19 | 20 | public SkillData? Skill 21 | { 22 | get => skill; 23 | set 24 | { 25 | if (value is null) return; 26 | 27 | skill = value; 28 | 29 | skillNameLabel.Text = AssetTables.GetText(TextCategory.MasterSkillName, skill.Id); 30 | skillDescriptionLabel.Text = AssetTables.GetText(TextCategory.MasterSkillExplain, skill.Id) 31 | .Replace("\\n", "\n"); 32 | iconPictureBox.BackgroundImage = UnityAssets.GetSkillIcon(skill.IconId)?.Bitmap; 33 | 34 | Refresh(); 35 | } 36 | } 37 | 38 | public SkillBackground Background 39 | { 40 | get => background; 41 | set 42 | { 43 | background = value; 44 | Refresh(); 45 | } 46 | } 47 | 48 | protected override void OnPaint(PaintEventArgs e) 49 | { 50 | Brush brush = SkillColorGenerator.ColorFromType(Background, ClientRectangle, out Brush backgroundBrush); 51 | 52 | Rectangle paddedRectangle = ClientRectangle; 53 | paddedRectangle.X += 2; 54 | paddedRectangle.Y += 2; 55 | paddedRectangle.Width -= 4; 56 | paddedRectangle.Height -= 4; 57 | 58 | e.Graphics.FillRectangle(backgroundBrush, ClientRectangle); 59 | e.Graphics.FillRectangle(brush, paddedRectangle); 60 | e.Graphics.FillRectangle( 61 | new SolidBrush(Color.FromArgb(127, 255, 255, 255)), 62 | paddedRectangle); 63 | 64 | base.OnPaint(e); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/CharacterInfo/SkillSmall.cs: -------------------------------------------------------------------------------- 1 | using UmaMusumeData; 2 | using UmaMusumeData.Tables; 3 | using UmaMusumeExplorer.Controls.CharacterInfo.Classes; 4 | using UmaMusumeExplorer.Game; 5 | using Color = System.Drawing.Color; 6 | using Rectangle = System.Drawing.Rectangle; 7 | 8 | namespace UmaMusumeExplorer.Controls.CharacterInfo 9 | { 10 | public partial class SkillSmall : UserControl 11 | { 12 | private int skillLevel; 13 | private SkillBackground rarity; 14 | private SkillData? evolveSkill; 15 | 16 | public SkillSmall(SkillData skill) 17 | { 18 | InitializeComponent(); 19 | 20 | skillNameLabel.Text = AssetTables.GetText(TextCategory.MasterSkillName, skill.Id); 21 | iconPictureBox.Image = UnityAssets.GetSkillIcon(skill.IconId)?.Bitmap; 22 | 23 | Skill = skill; 24 | 25 | skillLevel = 0; 26 | rarity = SkillBackground.Rarity1; 27 | evolveSkill = null; 28 | 29 | Click += OnSkillClicked; 30 | iconPictureBox.Click += OnSkillClicked; 31 | skillNameLabel.Click += OnSkillClicked; 32 | levelLabel.Click += OnSkillClicked; 33 | } 34 | 35 | public SkillData Skill { get; } 36 | 37 | public int SkillLevel 38 | { 39 | get => skillLevel; 40 | set 41 | { 42 | if (value > 0) 43 | levelLabel.Text = $"Lv{value}"; 44 | else 45 | levelLabel.Text = ""; 46 | 47 | skillLevel = value; 48 | 49 | Invalidate(); 50 | } 51 | } 52 | 53 | public SkillBackground Background 54 | { 55 | get => rarity; 56 | set 57 | { 58 | rarity = value; 59 | Invalidate(); 60 | } 61 | } 62 | 63 | public SkillData? EvolveSkill 64 | { 65 | get => evolveSkill; 66 | set 67 | { 68 | evolutionCircle.Visible = value is not null; 69 | evolveSkill = value; 70 | Invalidate(); 71 | } 72 | } 73 | 74 | public event EventHandler? SkillClick; 75 | 76 | private void OnSkillClicked(object? sender, EventArgs e) 77 | { 78 | SkillClick?.Invoke(this, e); 79 | } 80 | 81 | protected override void OnPaint(PaintEventArgs e) 82 | { 83 | Brush mainBrush = SkillColorGenerator.ColorFromType(rarity, ClientRectangle, out Brush backgroundBrush); 84 | 85 | Rectangle paddedRectangle = ClientRectangle; 86 | paddedRectangle.X += 2; 87 | paddedRectangle.Y += 2; 88 | paddedRectangle.Width -= 4; 89 | paddedRectangle.Height -= 4; 90 | 91 | e.Graphics.FillRectangle(backgroundBrush, ClientRectangle); 92 | e.Graphics.FillRectangle(mainBrush, paddedRectangle); 93 | e.Graphics.FillRectangle( 94 | new SolidBrush(Color.FromArgb(127, 255, 255, 255)), 95 | paddedRectangle); 96 | 97 | base.OnPaint(e); 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/CharacterInfo/SongsControl.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace UmaMusumeExplorer.Controls.CharacterInfo 2 | { 3 | partial class SongsControl 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Component Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | songItemsPanel = new Common.SongItemsPanel(); 32 | SuspendLayout(); 33 | // 34 | // songItemsPanel 35 | // 36 | songItemsPanel.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right; 37 | songItemsPanel.Items = null; 38 | songItemsPanel.Location = new System.Drawing.Point(3, 3); 39 | songItemsPanel.Name = "songItemsPanel"; 40 | songItemsPanel.Size = new System.Drawing.Size(444, 545); 41 | songItemsPanel.TabIndex = 0; 42 | // 43 | // SongsControl 44 | // 45 | AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); 46 | AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 47 | Controls.Add(songItemsPanel); 48 | Name = "SongsControl"; 49 | Size = new System.Drawing.Size(450, 551); 50 | Load += SongsControl_Load; 51 | ResumeLayout(false); 52 | } 53 | 54 | #endregion 55 | 56 | private Common.SongItemsPanel songItemsPanel; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/CharacterInfo/SongsControl.cs: -------------------------------------------------------------------------------- 1 | using UmaMusumeData.Tables; 2 | using UmaMusumeExplorer.Controls.Common; 3 | using UmaMusumeExplorer.Controls.Common.Classes; 4 | using UmaMusumeExplorer.Game; 5 | 6 | namespace UmaMusumeExplorer.Controls.CharacterInfo 7 | { 8 | public partial class SongsControl : UserControl 9 | { 10 | private readonly IEnumerable liveDatas = AssetTables.LiveDatas; 11 | 12 | public SongsControl() 13 | { 14 | InitializeComponent(); 15 | 16 | songItemsPanel.Indeterminate = true; 17 | songItemsPanel.Filter = (item) => 18 | { 19 | IEnumerable livePermissionData = LivePermissionDataHelper.GetLivePermissionData(item.MusicId); 20 | return livePermissionData.FirstOrDefault(lpd => lpd.CharaId == CharaId) is not null; 21 | }; 22 | songItemsPanel.ItemClick += (s, e) => 23 | { 24 | if (s is not PictureBox pictureBox) return; 25 | if (pictureBox.Tag is not LiveData liveData) return; 26 | 27 | if (liveData is not null) 28 | { 29 | MusicManager liveManager = new(liveData); 30 | 31 | if (liveManager.SetupLive(this)) 32 | ControlHelpers.ShowFormCenter(new PlayerForm(liveManager), this); 33 | } 34 | }; 35 | } 36 | 37 | public int CharaId { get; set; } 38 | 39 | private void SongsControl_Load(object sender, EventArgs e) 40 | { 41 | if (liveDatas is not null) 42 | songItemsPanel.Items = liveDatas; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/CharacterInfo/StatusDisplayLabel.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | text/microsoft-resx 50 | 51 | 52 | 2.0 53 | 54 | 55 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 56 | 57 | 58 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 59 | 60 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/CharacterInfo/SupportCardsControl.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace UmaMusumeExplorer.Controls.CharacterInfo 2 | { 3 | partial class SupportCardsControl 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Component Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | supportCardItemsPanel = new UmaMusumeExplorer.Controls.SupportCardInfo.SupportCardItemsPanel(); 32 | SuspendLayout(); 33 | // 34 | // supportCardItemsPanel 35 | // 36 | supportCardItemsPanel.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right; 37 | supportCardItemsPanel.Indeterminate = false; 38 | supportCardItemsPanel.Items = null; 39 | supportCardItemsPanel.Location = new Point(3, 3); 40 | supportCardItemsPanel.Name = "supportCardItemsPanel"; 41 | supportCardItemsPanel.Size = new Size(432, 605); 42 | supportCardItemsPanel.TabIndex = 0; 43 | // 44 | // SupportCardsControl 45 | // 46 | AutoScaleDimensions = new SizeF(7F, 15F); 47 | AutoScaleMode = AutoScaleMode.Font; 48 | Controls.Add(supportCardItemsPanel); 49 | Name = "SupportCardsControl"; 50 | Size = new Size(438, 611); 51 | Load += SupportCardsControl_Load; 52 | ResumeLayout(false); 53 | } 54 | 55 | #endregion 56 | 57 | private SupportCardInfo.SupportCardItemsPanel supportCardItemsPanel; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/CharacterInfo/SupportCardsControl.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Data; 5 | using System.Drawing; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using System.Windows.Forms; 10 | using UmaMusumeData.Tables; 11 | using UmaMusumeExplorer.Game; 12 | 13 | namespace UmaMusumeExplorer.Controls.CharacterInfo 14 | { 15 | public partial class SupportCardsControl : UserControl 16 | { 17 | private readonly IEnumerable supportCardDatas = AssetTables.SupportCardDatas; 18 | 19 | public SupportCardsControl() 20 | { 21 | InitializeComponent(); 22 | 23 | supportCardItemsPanel.Indeterminate = true; 24 | supportCardItemsPanel.Filter = (item) => item.CharaId == CharaId; 25 | } 26 | 27 | public int CharaId { get; set; } 28 | 29 | private void SupportCardsControl_Load(object sender, EventArgs e) 30 | { 31 | supportCardItemsPanel.Items = supportCardDatas; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/Common/CharacterItemsPanel.cs: -------------------------------------------------------------------------------- 1 | using UmaMusumeData; 2 | using UmaMusumeData.Tables; 3 | using UmaMusumeExplorer.Controls.CharacterInfo; 4 | using UmaMusumeExplorer.Game; 5 | 6 | namespace UmaMusumeExplorer.Controls.Common 7 | { 8 | internal class CharacterItemsPanel : ItemsPanel 9 | { 10 | public override bool ProcessItem(CharaData charaData, ref Control? characterPictureBox) 11 | { 12 | bool playable = AssetTables.CardDatas.Any(cd => cd.CharaId == charaData.Id); 13 | characterPictureBox = new HighlightPictureBox(playable) 14 | { 15 | BackgroundImage = UnityAssets.GetCharaIcon(charaData.Id)?.Bitmap, 16 | BackgroundImageLayout = ImageLayout.Stretch, 17 | Cursor = Cursors.Hand, 18 | Height = 108, 19 | Width = 98, 20 | Tag = charaData 21 | }; 22 | 23 | ToolTip toolTip = new(); 24 | toolTip.SetToolTip(characterPictureBox, $"{charaData.Id}: {AssetTables.GetText(TextCategory.MasterCharaName, charaData.Id)}"); 25 | 26 | return true; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/Common/CharacterPositionControl.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace UmaMusumeExplorer.Controls.Common 2 | { 3 | partial class CharacterPositionControl 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Component Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | positionIndexLabel = new Label(); 32 | characterPictureBox = new HighQualityPictureBox(); 33 | ((System.ComponentModel.ISupportInitialize)characterPictureBox).BeginInit(); 34 | SuspendLayout(); 35 | // 36 | // positionIndexLabel 37 | // 38 | positionIndexLabel.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right; 39 | positionIndexLabel.Font = new Font("Segoe UI", 15.75F); 40 | positionIndexLabel.Location = new Point(3, 3); 41 | positionIndexLabel.Margin = new Padding(3); 42 | positionIndexLabel.Name = "positionIndexLabel"; 43 | positionIndexLabel.Size = new Size(109, 30); 44 | positionIndexLabel.TabIndex = 0; 45 | positionIndexLabel.Text = "0"; 46 | positionIndexLabel.TextAlign = ContentAlignment.MiddleCenter; 47 | // 48 | // characterPictureBox 49 | // 50 | characterPictureBox.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right; 51 | characterPictureBox.BackgroundImageLayout = ImageLayout.Stretch; 52 | characterPictureBox.Cursor = Cursors.Hand; 53 | characterPictureBox.Location = new Point(3, 39); 54 | characterPictureBox.Name = "characterPictureBox"; 55 | characterPictureBox.Size = new Size(109, 120); 56 | characterPictureBox.TabIndex = 1; 57 | characterPictureBox.TabStop = false; 58 | // 59 | // CharacterPositionControl 60 | // 61 | AutoScaleDimensions = new SizeF(7F, 15F); 62 | AutoScaleMode = AutoScaleMode.Font; 63 | AutoSize = true; 64 | Controls.Add(characterPictureBox); 65 | Controls.Add(positionIndexLabel); 66 | Name = "CharacterPositionControl"; 67 | Size = new Size(115, 162); 68 | ((System.ComponentModel.ISupportInitialize)characterPictureBox).EndInit(); 69 | ResumeLayout(false); 70 | } 71 | 72 | #endregion 73 | 74 | private System.Windows.Forms.Label positionIndexLabel; 75 | private Common.HighQualityPictureBox characterPictureBox; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/Common/CharacterPositionControl.cs: -------------------------------------------------------------------------------- 1 | using UmaMusumeExplorer.Game; 2 | using Image = System.Drawing.Image; 3 | 4 | namespace UmaMusumeExplorer.Controls.Common 5 | { 6 | partial class CharacterPositionControl : UserControl 7 | { 8 | private int characterPosition = 0; 9 | private int characterId = 0; 10 | private Image? characterImage; 11 | private bool disabled = false; 12 | 13 | public CharacterPositionControl(int position, EventHandler clickEventHandler, int width = -1) 14 | { 15 | InitializeComponent(); 16 | 17 | characterPosition = position; 18 | 19 | positionIndexLabel.Text = (characterPosition + 1).ToString(); 20 | characterPictureBox.BackgroundImage = UnityAssets.GetCharaIcon(0)?.Bitmap; 21 | 22 | characterPictureBox.Click += clickEventHandler; 23 | 24 | if (width > 0) 25 | { 26 | Width = width; 27 | characterPictureBox.Height = (int)(characterPictureBox.Width * 1.1F); 28 | } 29 | } 30 | 31 | public int Position 32 | { 33 | get { return characterPosition; } 34 | set 35 | { 36 | characterPosition = value; 37 | positionIndexLabel.Text = (value + 1).ToString(); 38 | 39 | Update(); 40 | } 41 | } 42 | 43 | public int CharacterId 44 | { 45 | get { return characterId; } 46 | set 47 | { 48 | characterId = value; 49 | characterPictureBox.BackgroundImage = characterImage = UnityAssets.GetCharaIcon(characterId)?.Bitmap; 50 | 51 | Update(); 52 | } 53 | } 54 | 55 | public float FontSize 56 | { 57 | get => positionIndexLabel.Font.Size; 58 | set 59 | { 60 | positionIndexLabel.Font = new Font(positionIndexLabel.Font.Name, value); 61 | } 62 | } 63 | 64 | public bool Disabled 65 | { 66 | get => disabled; 67 | set 68 | { 69 | disabled = value; 70 | 71 | characterPictureBox.BackgroundImage = disabled ? null : characterImage; 72 | } 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/Common/CharacterSelectForm.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace UmaMusumeExplorer.Controls.Common 2 | { 3 | partial class CharacterSelectForm 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(CharacterSelectForm)); 32 | characterItemsPanel = new Common.CharacterItemsPanel(); 33 | SuspendLayout(); 34 | // 35 | // characterItemsPanel 36 | // 37 | resources.ApplyResources(characterItemsPanel, "characterItemsPanel"); 38 | characterItemsPanel.Items = null; 39 | characterItemsPanel.Name = "characterItemsPanel"; 40 | // 41 | // CharacterSelectForm 42 | // 43 | resources.ApplyResources(this, "$this"); 44 | AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 45 | Controls.Add(characterItemsPanel); 46 | Name = "CharacterSelectForm"; 47 | Load += CharacterSelectForm_Load; 48 | ResumeLayout(false); 49 | } 50 | 51 | #endregion 52 | 53 | private Common.CharacterItemsPanel characterItemsPanel; 54 | } 55 | } -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/Common/CharacterSelectForm.cs: -------------------------------------------------------------------------------- 1 | using System.Net.Security; 2 | using UmaMusumeData.Tables; 3 | using UmaMusumeExplorer.Controls.Common.Classes; 4 | using UmaMusumeExplorer.Game; 5 | using Color = System.Drawing.Color; 6 | 7 | namespace UmaMusumeExplorer.Controls.Common 8 | { 9 | partial class CharacterSelectForm : Form 10 | { 11 | private readonly IEnumerable charaDatas = AssetTables.CharaDatas; 12 | private readonly IEnumerable livePermissionData; 13 | private readonly List allowedCharas = new(); 14 | private readonly List alreadySelected = new(); 15 | 16 | public CharacterSelectForm(IEnumerable permissionData, CharacterPosition[] characters) 17 | { 18 | InitializeComponent(); 19 | 20 | livePermissionData = permissionData; 21 | foreach (var lpd in livePermissionData) 22 | { 23 | allowedCharas.Add(lpd.CharaId); 24 | } 25 | 26 | foreach (var character in characters) 27 | { 28 | alreadySelected.Add(character.CharacterId); 29 | } 30 | 31 | characterItemsPanel.Filter = (cd) => 32 | { 33 | return allowedCharas.Contains(cd.Id); 34 | }; 35 | characterItemsPanel.LoadingFinished += (s, e) => 36 | { 37 | foreach (PictureBox charaIcon in characterItemsPanel.Controls) 38 | { 39 | if (charaIcon.Tag as CharaData is not CharaData cd) return; 40 | if (alreadySelected.Contains(cd.Id)) charaIcon.BackColor = Color.FromArgb(234, 54, 128); 41 | } 42 | }; 43 | characterItemsPanel.ItemClick += (s, e) => 44 | { 45 | if (s is not PictureBox pictureBox) return; 46 | if (pictureBox.Tag is not CharaData cd) return; 47 | SelectedCharacter = cd.Id; 48 | Close(); 49 | }; 50 | } 51 | 52 | public int SelectedCharacter { get; private set; } = 0; 53 | 54 | private void CharacterSelectForm_Load(object sender, EventArgs e) 55 | { 56 | characterItemsPanel.Items = charaDatas; 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/Common/Classes/CharacterPosition.cs: -------------------------------------------------------------------------------- 1 | namespace UmaMusumeExplorer.Controls.Common.Classes 2 | { 3 | internal struct CharacterPosition 4 | { 5 | public int CharacterId; 6 | public int Position; 7 | 8 | public CharacterPosition(int characterId, int position) 9 | { 10 | CharacterId = characterId; 11 | Position = position; 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/Common/Classes/CsvReader.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | 3 | namespace UmaMusumeExplorer.Controls.Common.Classes 4 | { 5 | internal class CsvReader : StreamReader 6 | { 7 | public CsvReader(Stream stream) : base(stream) { } 8 | 9 | public string ReadCsvLine() 10 | { 11 | StringBuilder stringBuilder = new(); 12 | bool withinQuotes = false; 13 | 14 | int read; 15 | while ((read = Read()) != -1) 16 | { 17 | char c = (char)read; 18 | 19 | if (c == '"') 20 | withinQuotes = !withinQuotes; 21 | 22 | if (c == '\n' && !withinQuotes) break; 23 | 24 | stringBuilder.Append(c); 25 | } 26 | 27 | return stringBuilder.ToString(); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/Common/Classes/ExtendedSampleProvider.cs: -------------------------------------------------------------------------------- 1 | using NAudio.Wave; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace UmaMusumeExplorer.Controls.Common.Classes 9 | { 10 | internal class ExtendedSampleProvider : IExtendedSampleProvider 11 | { 12 | private readonly WaveStream source; 13 | private readonly ISampleProvider sampleProvider; 14 | 15 | public ExtendedSampleProvider(WaveStream waveStream) 16 | { 17 | source = waveStream; 18 | sampleProvider = waveStream.ToSampleProvider(); 19 | } 20 | 21 | public WaveFormat WaveFormat => sampleProvider.WaveFormat; 22 | 23 | public long Position { get => source.Position; set => source.Position = value; } 24 | 25 | public long Length => source.Length; 26 | 27 | public TimeSpan CurrentTime => source.CurrentTime; 28 | 29 | public TimeSpan TotalTime => source.TotalTime; 30 | 31 | public int Read(float[] buffer, int offset, int count) => sampleProvider.Read(buffer, offset, count); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/Common/Classes/IExtendedSampleProvider.cs: -------------------------------------------------------------------------------- 1 | using NAudio.Wave; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace UmaMusumeExplorer.Controls.Common.Classes 9 | { 10 | internal interface IExtendedSampleProvider : ISampleProvider 11 | { 12 | public long Position { get; set; } 13 | 14 | public long Length { get; } 15 | 16 | public TimeSpan CurrentTime { get; } 17 | 18 | public TimeSpan TotalTime { get; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/Common/Classes/LiveConfigurationManager.cs: -------------------------------------------------------------------------------- 1 | namespace UmaMusumeExplorer.Controls.Common.Classes 2 | { 3 | static class LiveConfigurationManager 4 | { 5 | private static readonly Dictionary songConfigurations = new(); 6 | 7 | public static void SaveConfiguration(SongConfiguration songConfiguration) 8 | { 9 | songConfigurations.Clear(); 10 | ReadConfigurationFile(); 11 | 12 | songConfigurations[songConfiguration.SongId] = songConfiguration; 13 | WriteConfigurationFile(); 14 | } 15 | 16 | public static SongConfiguration? LoadConfiguration(int songId) 17 | { 18 | songConfigurations.Clear(); 19 | ReadConfigurationFile(); 20 | 21 | if (songConfigurations.ContainsKey(songId)) 22 | return songConfigurations[songId]; 23 | 24 | return null; 25 | } 26 | 27 | private static FileStream OpenFile() 28 | { 29 | return new("LiveConfiguration.dat", FileMode.OpenOrCreate, FileAccess.ReadWrite); 30 | } 31 | 32 | private static void ReadConfigurationFile() 33 | { 34 | FileStream configurationFile = OpenFile(); 35 | BinaryReader reader = new(configurationFile); 36 | 37 | reader.BaseStream.Position = 0; 38 | 39 | if (reader.BaseStream.Length == 0) 40 | { 41 | configurationFile.Dispose(); 42 | return; 43 | } 44 | 45 | int entryCount = reader.ReadInt16(); 46 | for (int i = 0; i < entryCount; i++) 47 | { 48 | int songId = reader.ReadInt32(); 49 | int memberCount = reader.ReadByte(); 50 | int[] members = new int[memberCount]; 51 | for (int j = 0; j < memberCount; j++) 52 | { 53 | members[j] = reader.ReadInt32(); 54 | } 55 | bool sfx = reader.ReadBoolean(); 56 | 57 | SongConfiguration songConfiguration = new(songId, members, sfx); 58 | songConfigurations[songId] = songConfiguration; 59 | } 60 | 61 | configurationFile.Dispose(); 62 | } 63 | 64 | private static void WriteConfigurationFile() 65 | { 66 | FileStream configurationFile = OpenFile(); 67 | BinaryWriter writer = new(configurationFile); 68 | writer.BaseStream.Position = 0; 69 | 70 | writer.Write((short)songConfigurations.Count); 71 | foreach (var songConfiguration in songConfigurations) 72 | { 73 | writer.Write(songConfiguration.Value.SongId); 74 | writer.Write((byte)songConfiguration.Value.Members.Length); 75 | foreach (var member in songConfiguration.Value.Members) 76 | { 77 | writer.Write(member); 78 | } 79 | writer.Write(songConfiguration.Value.Sfx); 80 | } 81 | 82 | configurationFile.Dispose(); 83 | } 84 | } 85 | 86 | record SongConfiguration(int SongId, int[] Members, bool Sfx); 87 | } 88 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/Common/Classes/LivePermissionDataHelper.cs: -------------------------------------------------------------------------------- 1 | using UmaMusumeData; 2 | using UmaMusumeData.Tables; 3 | using UmaMusumeExplorer.Game; 4 | 5 | namespace UmaMusumeExplorer.Controls.Common.Classes 6 | { 7 | static class LivePermissionDataHelper 8 | { 9 | public static IEnumerable GetLivePermissionData(int musicId) 10 | { 11 | List livePermissionData = AssetTables.LivePermissionDatas.Where(lpd => lpd.MusicId == musicId).ToList(); 12 | 13 | var matches = UmaDataHelper.GetManifestEntries(ga => ga.BaseName.StartsWith($"snd_bgm_live_{musicId}_chara_") && ga.BaseName.EndsWith(".awb")); 14 | foreach (var audioAsset in matches) 15 | { 16 | int charaId = int.Parse(audioAsset.BaseName.Remove(0, $"snd_bgm_live_{musicId}_chara_".Length)[..4]); 17 | 18 | if (livePermissionData is not List list) continue; 19 | list.Add(new LivePermissionData() { MusicId = musicId, CharaId = charaId }); 20 | } 21 | 22 | return livePermissionData; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/Common/Classes/LyricsTrigger.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | 3 | namespace UmaMusumeExplorer.Controls.Common.Classes 4 | { 5 | class LyricsTrigger 6 | { 7 | public int TimeMs { get; } 8 | 9 | public string Lyrics { get; } 10 | 11 | public LyricsTrigger(string lyricsCsvLine) 12 | { 13 | string[] columns = Split(lyricsCsvLine, ','); 14 | TimeMs = int.Parse(columns[0]); 15 | Lyrics = columns[1] 16 | .Replace("[COMMA]", ",") 17 | .Replace("&&", "&") 18 | .Replace("\\n", "\n"); 19 | } 20 | 21 | private string[] Split(string toSplit, char splitChar) 22 | { 23 | List splitStrings = new(); 24 | StringBuilder splitStringBuilder = new(); 25 | 26 | bool withinQuotes = false; 27 | 28 | for (int i = 0; i < toSplit.Length; i++) 29 | { 30 | char c = toSplit[i]; 31 | 32 | if (c == '"') withinQuotes = !withinQuotes; 33 | 34 | if (!withinQuotes && c == splitChar) 35 | { 36 | splitStrings.Add(splitStringBuilder.ToString()); 37 | splitStringBuilder.Clear(); 38 | } 39 | else 40 | splitStringBuilder.Append(c); 41 | } 42 | 43 | splitStrings.Add(splitStringBuilder.ToString()); 44 | return splitStrings.ToArray(); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/Common/Classes/PanSampleProvider.cs: -------------------------------------------------------------------------------- 1 | using NAudio.Wave; 2 | 3 | namespace UmaMusumeExplorer.Controls.Common.Classes 4 | { 5 | class PanSampleProvider : ISampleProvider 6 | { 7 | private readonly ISampleProvider sampleProvider; 8 | 9 | public PanSampleProvider(ISampleProvider source) 10 | { 11 | sampleProvider = source; 12 | 13 | if (source.WaveFormat.Channels != 2) 14 | throw new Exception("Must be stereo."); 15 | } 16 | 17 | public WaveFormat WaveFormat => sampleProvider.WaveFormat; 18 | 19 | public float Pan { get; set; } 20 | 21 | public int Read(float[] buffer, int offset, int count) 22 | { 23 | int read = sampleProvider.Read(buffer, offset, count); 24 | 25 | float left; 26 | float right; 27 | 28 | int bufferIndex = 0; 29 | for (int i = offset; i < count / 2; i++) 30 | { 31 | left = Pan <= 0 ? 1.0F : (1.0F - Pan) / 2.0F; 32 | right = Pan >= 0 ? 1.0F : (Pan + 1.0F) / 2.0F; 33 | 34 | buffer[bufferIndex++] *= left; 35 | buffer[bufferIndex++] *= right; 36 | } 37 | 38 | return read; 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/Common/Classes/PartTrigger.cs: -------------------------------------------------------------------------------- 1 | namespace UmaMusumeExplorer.Controls.Common.Classes 2 | { 3 | class PartTrigger 4 | { 5 | public int TimeMs { get; } 6 | 7 | public int[] MemberTracks { get; } 8 | 9 | public float[] MemberVolumes { get; } 10 | 11 | public float[] MemberPans { get; } 12 | 13 | public float VolumeRate { get; } 14 | 15 | public PartTrigger(string partCsvLine, bool hasVolumeRate) 16 | { 17 | string[] columns = partCsvLine.Split(','); 18 | 19 | int activeMembers; 20 | 21 | int ignoreColumns = hasVolumeRate ? 2 : 1; 22 | 23 | if (columns.Length - ignoreColumns > 5) 24 | activeMembers = (columns.Length - ignoreColumns) / 3; 25 | else 26 | activeMembers = columns.Length - ignoreColumns; 27 | 28 | MemberTracks = new int[activeMembers]; 29 | MemberVolumes = new float[activeMembers]; 30 | MemberPans = new float[activeMembers]; 31 | 32 | int currentIndex = 0; 33 | TimeMs = int.Parse(columns[currentIndex++]); 34 | 35 | int pivot = activeMembers / 2; 36 | 37 | for (int i = 0; i < activeMembers; i++) 38 | { 39 | MemberTracks[PositionToIndex(i, pivot)] = int.Parse(columns[currentIndex++]); 40 | } 41 | 42 | if (columns.Length - 1 > 5) 43 | { 44 | for (int i = 0; i < activeMembers; i++) 45 | { 46 | MemberVolumes[PositionToIndex(i, pivot)] = float.Parse(columns[currentIndex++]); 47 | } 48 | for (int i = 0; i < activeMembers; i++) 49 | { 50 | MemberPans[PositionToIndex(i, pivot)] = float.Parse(columns[currentIndex++]); 51 | } 52 | } 53 | else 54 | { 55 | for (int i = 0; i < activeMembers; i++) 56 | { 57 | MemberVolumes[i] = 1.0F; 58 | MemberPans[i] = 999; 59 | } 60 | } 61 | 62 | if (hasVolumeRate) 63 | VolumeRate = float.Parse(columns[currentIndex++]); 64 | } 65 | 66 | private static int PositionToIndex(int position, int pivot) 67 | { 68 | int distance = Math.Abs(pivot - position); 69 | int multiply = distance * 2; 70 | if (position < pivot) multiply -= 1; 71 | return multiply; 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/Common/Classes/SongLength.cs: -------------------------------------------------------------------------------- 1 | namespace UmaMusumeExplorer.Controls.Common.Classes 2 | { 3 | public enum SongLength 4 | { 5 | ShortVersion, 6 | GameSizeVersion 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/Common/HighQualityPictureBox.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing.Drawing2D; 2 | 3 | namespace UmaMusumeExplorer.Controls.Common 4 | { 5 | internal class HighQualityPictureBox : PictureBox 6 | { 7 | protected override void OnPaint(PaintEventArgs pe) 8 | { 9 | pe.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; 10 | pe.Graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; 11 | pe.Graphics.SmoothingMode = SmoothingMode.AntiAlias; 12 | base.OnPaint(pe); 13 | } 14 | 15 | protected override void OnPaintBackground(PaintEventArgs pe) 16 | { 17 | pe.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; 18 | pe.Graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; 19 | pe.Graphics.SmoothingMode = SmoothingMode.AntiAlias; 20 | base.OnPaintBackground(pe); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/Common/HighlightPictureBox.cs: -------------------------------------------------------------------------------- 1 | using Color = System.Drawing.Color; 2 | 3 | namespace UmaMusumeExplorer.Controls.Common 4 | { 5 | internal class HighlightPictureBox : HighQualityPictureBox 6 | { 7 | private bool highlight = false; 8 | private readonly bool marked; 9 | private System.Drawing.Image? image; 10 | 11 | public HighlightPictureBox(bool isMarked) 12 | { 13 | marked = isMarked; 14 | image = Image; 15 | } 16 | 17 | public bool ShowHighlight 18 | { 19 | get => highlight; 20 | set 21 | { 22 | if (marked && value) 23 | { 24 | BackColor = Color.LightGreen; 25 | Image = null; 26 | } 27 | else 28 | { 29 | BackColor = Color.FromKnownColor(KnownColor.Transparent); 30 | Image = image; 31 | } 32 | 33 | highlight = value; 34 | } 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/Common/SongItemsPanel.cs: -------------------------------------------------------------------------------- 1 | using UmaMusumeData; 2 | using UmaMusumeData.Tables; 3 | using UmaMusumeExplorer.Game; 4 | 5 | namespace UmaMusumeExplorer.Controls.Common 6 | { 7 | internal class SongItemsPanel : ItemsPanel 8 | { 9 | public override bool ProcessItem(LiveData liveData, ref Control? jacket) 10 | { 11 | if (liveData.HasLive == 0) return false; 12 | 13 | jacket = new PictureBox() 14 | { 15 | BackgroundImage = UnityAssets.GetJacket(liveData.MusicId, 'l')?.Bitmap, 16 | BackgroundImageLayout = ImageLayout.Zoom, 17 | Cursor = Cursors.Hand, 18 | Height = 128, 19 | Width = 128, 20 | Tag = liveData 21 | }; 22 | 23 | ToolTip toolTip = new(); 24 | toolTip.SetToolTip(jacket, $"{liveData.MusicId}: {AssetTables.GetText(TextCategory.MasterLiveTitle, liveData.MusicId)}"); 25 | 26 | return true; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/Common/UnitSetupForm.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace UmaMusumeExplorer.Controls.Common 2 | { 3 | partial class UnitSetupForm 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(UnitSetupForm)); 32 | singersPanel = new System.Windows.Forms.FlowLayoutPanel(); 33 | tableLayoutPanel = new System.Windows.Forms.TableLayoutPanel(); 34 | confirmButton = new System.Windows.Forms.Button(); 35 | sfxCheckBox = new System.Windows.Forms.CheckBox(); 36 | tableLayoutPanel.SuspendLayout(); 37 | SuspendLayout(); 38 | // 39 | // singersPanel 40 | // 41 | resources.ApplyResources(singersPanel, "singersPanel"); 42 | singersPanel.Name = "singersPanel"; 43 | // 44 | // tableLayoutPanel 45 | // 46 | resources.ApplyResources(tableLayoutPanel, "tableLayoutPanel"); 47 | tableLayoutPanel.Controls.Add(singersPanel, 0, 0); 48 | tableLayoutPanel.Controls.Add(confirmButton, 0, 1); 49 | tableLayoutPanel.Controls.Add(sfxCheckBox, 0, 2); 50 | tableLayoutPanel.GrowStyle = System.Windows.Forms.TableLayoutPanelGrowStyle.FixedSize; 51 | tableLayoutPanel.Name = "tableLayoutPanel"; 52 | // 53 | // confirmButton 54 | // 55 | resources.ApplyResources(confirmButton, "confirmButton"); 56 | confirmButton.Name = "confirmButton"; 57 | confirmButton.UseVisualStyleBackColor = true; 58 | confirmButton.Click += ConfirmButton_Click; 59 | // 60 | // sfxCheckBox 61 | // 62 | resources.ApplyResources(sfxCheckBox, "sfxCheckBox"); 63 | sfxCheckBox.Checked = true; 64 | sfxCheckBox.CheckState = System.Windows.Forms.CheckState.Checked; 65 | sfxCheckBox.Name = "sfxCheckBox"; 66 | sfxCheckBox.UseVisualStyleBackColor = true; 67 | // 68 | // UnitSetupForm 69 | // 70 | AcceptButton = confirmButton; 71 | resources.ApplyResources(this, "$this"); 72 | AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 73 | Controls.Add(tableLayoutPanel); 74 | MaximizeBox = false; 75 | Name = "UnitSetupForm"; 76 | tableLayoutPanel.ResumeLayout(false); 77 | tableLayoutPanel.PerformLayout(); 78 | ResumeLayout(false); 79 | PerformLayout(); 80 | } 81 | 82 | #endregion 83 | 84 | private System.Windows.Forms.FlowLayoutPanel singersPanel; 85 | private System.Windows.Forms.TableLayoutPanel tableLayoutPanel; 86 | private System.Windows.Forms.Button confirmButton; 87 | private System.Windows.Forms.CheckBox sfxCheckBox; 88 | } 89 | } -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/ControlHelpers.cs: -------------------------------------------------------------------------------- 1 | namespace UmaMusumeExplorer.Controls 2 | { 3 | static class ControlHelpers 4 | { 5 | private static List
OpenedForms { get; } = new(); 6 | 7 | public static void CloseAllForms() 8 | { 9 | OpenedForms.ForEach(form => 10 | { 11 | form.FormClosed -= FormClosed; 12 | form.Close(); 13 | }); 14 | 15 | OpenedForms.Clear(); 16 | } 17 | 18 | public static DialogResult ShowFormDialogCenter(Form form, Control source) 19 | { 20 | SetNewLocation(form, source); 21 | Form parentForm = GetParentForm(source); 22 | form.Icon = parentForm.Icon; 23 | return form.ShowDialog(parentForm); 24 | } 25 | 26 | public static void ShowFormCenter(Form form, Control source) 27 | { 28 | SetNewLocation(form, source); 29 | form.Icon = GetParentForm(source).Icon; 30 | form.FormClosed += FormClosed; 31 | form.Show(); 32 | OpenedForms.Add(form); 33 | } 34 | 35 | private static void SetNewLocation(Form form, Control source) 36 | { 37 | Form parentForm = GetParentForm(source); 38 | 39 | int left = parentForm.Left; 40 | int top = parentForm.Top; 41 | 42 | left += (parentForm.Width / 2) - (form.Width / 2); 43 | top += (parentForm.Height / 2) - (form.Height / 2); 44 | 45 | form.Left = left; 46 | form.Top = top; 47 | } 48 | 49 | public static Form GetParentForm(Control? control) 50 | { 51 | if (control is Form parentForm) 52 | { 53 | return parentForm; 54 | } 55 | else return GetParentForm(control?.Parent); 56 | } 57 | 58 | private static void FormClosed(object? sender, FormClosedEventArgs e) 59 | { 60 | if (sender is not Form form) return; 61 | OpenedForms.Remove(form); 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/Jukebox/JukeboxControl.cs: -------------------------------------------------------------------------------- 1 | using UmaMusumeData.Tables; 2 | using UmaMusumeExplorer.Controls.Common.Classes; 3 | using UmaMusumeExplorer.Game; 4 | 5 | namespace UmaMusumeExplorer.Controls.Jukebox 6 | { 7 | partial class JukeboxControl : UserControl 8 | { 9 | private readonly IEnumerable? jukeboxMusicDatas = AssetTables.JukeboxMusicDatas?.OrderBy(l => l.Sort); 10 | 11 | public JukeboxControl() 12 | { 13 | InitializeComponent(); 14 | 15 | shortVersionRadioButton.Checked = true; 16 | shortVersionRadioButton.Tag = SongLength.ShortVersion; 17 | gameSizeVersionRadioButton.Tag = SongLength.GameSizeVersion; 18 | } 19 | 20 | private void LiveMusicPlayerSongSelectControl_Load(object sender, EventArgs e) 21 | { 22 | jukeboxItemsPanel.Items = jukeboxMusicDatas; 23 | } 24 | 25 | private void RadioBuiton_CheckedChanegd(object sender, EventArgs e) 26 | { 27 | if (sender is not RadioButton radioButton) return; 28 | if (radioButton.Tag is not null) 29 | { 30 | if (radioButton.Checked) 31 | jukeboxItemsPanel.CurrentSongLength = (SongLength)radioButton.Tag; 32 | } 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/Jukebox/JukeboxItemsPanel.cs: -------------------------------------------------------------------------------- 1 | using UmaMusumeData; 2 | using UmaMusumeData.Tables; 3 | using UmaMusumeExplorer.Controls.Common; 4 | using UmaMusumeExplorer.Controls.Common.Classes; 5 | using UmaMusumeExplorer.Game; 6 | 7 | namespace UmaMusumeExplorer.Controls.Jukebox 8 | { 9 | internal class JukeboxItemsPanel : ItemsPanel 10 | { 11 | public SongLength CurrentSongLength { get; set; } 12 | 13 | public override bool ProcessItem(JukeboxMusicData jukeboxMusicData, ref Control? jacket) 14 | { 15 | jacket = new PictureBox() 16 | { 17 | BackgroundImage = UnityAssets.GetJacket(jukeboxMusicData.MusicId, 'l')?.Bitmap, 18 | BackgroundImageLayout = ImageLayout.Zoom, 19 | Cursor = Cursors.Hand, 20 | Height = 128, 21 | Width = 128, 22 | Tag = jukeboxMusicData 23 | }; 24 | 25 | jacket.Click += (s, e) => 26 | { 27 | if (s is not PictureBox pictureBox) return; 28 | if (pictureBox.Tag is not JukeboxMusicData jukeBoxData) return; 29 | if (jukeBoxData is not null) 30 | { 31 | MusicManager jukeBoxManager = new(jukeBoxData); 32 | 33 | if (jukeBoxManager.SetupJukeBoxMusic(CurrentSongLength)) 34 | ControlHelpers.ShowFormCenter(new PlayerForm(jukeBoxManager), this); 35 | } 36 | }; 37 | 38 | ToolTip toolTip = new(); 39 | toolTip.SetToolTip(jacket, $"{jukeboxMusicData.MusicId}: {AssetTables.GetText(TextCategory.MasterLiveTitle, jukeboxMusicData.MusicId)}"); 40 | 41 | return true; 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/LiveMusicPlayer/LiveMusicPlayerControl.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace UmaMusumeExplorer.Controls.LiveMusicPlayer 2 | { 3 | partial class LiveMusicPlayerControl 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Component Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | songItemsPanel = new Common.SongItemsPanel(); 32 | linkLabelDownload = new LinkLabel(); 33 | SuspendLayout(); 34 | // 35 | // songItemsPanel 36 | // 37 | songItemsPanel.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right; 38 | songItemsPanel.Indeterminate = false; 39 | songItemsPanel.Items = null; 40 | songItemsPanel.Location = new Point(3, 18); 41 | songItemsPanel.Name = "songItemsPanel"; 42 | songItemsPanel.Size = new Size(815, 507); 43 | songItemsPanel.TabIndex = 0; 44 | // 45 | // linkLabelDownload 46 | // 47 | linkLabelDownload.AutoSize = true; 48 | linkLabelDownload.Location = new Point(3, 0); 49 | linkLabelDownload.Name = "linkLabelDownload"; 50 | linkLabelDownload.Size = new Size(143, 15); 51 | linkLabelDownload.TabIndex = 2; 52 | linkLabelDownload.TabStop = true; 53 | linkLabelDownload.Text = "Live audio data download"; 54 | linkLabelDownload.LinkClicked += LinkLabelDownload_LinkClicked; 55 | // 56 | // LiveMusicPlayerControl 57 | // 58 | AutoScaleMode = AutoScaleMode.Inherit; 59 | Controls.Add(linkLabelDownload); 60 | Controls.Add(songItemsPanel); 61 | Name = "LiveMusicPlayerControl"; 62 | Size = new Size(821, 528); 63 | Load += LiveMusicPlayerSongSelectControl_Load; 64 | ResumeLayout(false); 65 | PerformLayout(); 66 | } 67 | 68 | #endregion 69 | 70 | private Common.SongItemsPanel songItemsPanel; 71 | private LinkLabel linkLabelDownload; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/LiveMusicPlayer/LiveMusicPlayerControl.cs: -------------------------------------------------------------------------------- 1 | using UmaMusumeData.Tables; 2 | using UmaMusumeExplorer.Controls.Common; 3 | using UmaMusumeExplorer.Controls.Common.Classes; 4 | using UmaMusumeExplorer.Game; 5 | 6 | namespace UmaMusumeExplorer.Controls.LiveMusicPlayer 7 | { 8 | partial class LiveMusicPlayerControl : UserControl 9 | { 10 | private readonly IEnumerable? liveDatas = AssetTables.LiveDatas?.OrderBy(l => l.Sort); 11 | 12 | public LiveMusicPlayerControl() 13 | { 14 | InitializeComponent(); 15 | 16 | songItemsPanel.ItemClick += (s, e) => 17 | { 18 | if (s is not PictureBox pictureBox) return; 19 | if (pictureBox.Tag is not LiveData liveData) return; 20 | 21 | if (liveData is not null) 22 | { 23 | MusicManager liveManager = new(liveData); 24 | 25 | if (liveManager.SetupLive(this)) 26 | ControlHelpers.ShowFormCenter(new PlayerForm(liveManager), this); 27 | } 28 | }; 29 | } 30 | 31 | private void LiveMusicPlayerSongSelectControl_Load(object sender, EventArgs e) 32 | { 33 | songItemsPanel.Items = liveDatas; 34 | } 35 | 36 | private void LinkLabelDownload_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) 37 | { 38 | ControlHelpers.ShowFormCenter(new DownloadWorkaroundForm(), this); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/LoadingProgress.cs: -------------------------------------------------------------------------------- 1 | namespace UmaMusumeExplorer.Controls 2 | { 3 | class LoadingProgress : IProgress 4 | { 5 | private readonly Action reportProgress; 6 | 7 | public LoadingProgress(Action action) 8 | { 9 | reportProgress = action; 10 | } 11 | 12 | public void Report(int value) 13 | { 14 | reportProgress.Invoke(value); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/RaceMusicPlayer/Classes/Bgm.cs: -------------------------------------------------------------------------------- 1 | using CriWareLibrary; 2 | using UmaMusumeAudio; 3 | using UmaMusumeData; 4 | 5 | namespace UmaMusumeExplorer.Controls.RaceMusicPlayer.Classes 6 | { 7 | public class Bgm : IDisposable 8 | { 9 | private readonly AwbReader awbReader; 10 | 11 | public Bgm(IEnumerable entryList, string cuesheetName, string cueName) 12 | { 13 | string lower = cuesheetName.ToLower(); 14 | string awbPath = UmaDataHelper.GetPath(entryList, lower + ".awb"); 15 | string acbPath = UmaDataHelper.GetPath(entryList, lower + ".acb"); 16 | 17 | awbReader = new(File.OpenRead(awbPath)); 18 | 19 | AcbReader acbReader = new(File.OpenRead(acbPath)); 20 | 21 | int targetWaveId = -1; 22 | foreach (var wave in awbReader.Waves) 23 | { 24 | string waveName = acbReader.GetWaveName(wave.WaveId, 0, false); 25 | 26 | if (waveName.Contains(cueName)) 27 | { 28 | targetWaveId = wave.WaveId; 29 | break; 30 | } 31 | } 32 | 33 | acbReader.Dispose(); 34 | 35 | UmaWaveStream = new UmaWaveStream(awbReader, targetWaveId); 36 | } 37 | 38 | public UmaWaveStream UmaWaveStream { get; } 39 | 40 | public void Dispose() 41 | { 42 | GC.SuppressFinalize(this); 43 | awbReader.Dispose(); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/RaceMusicPlayer/Classes/BgmComboBoxItem.cs: -------------------------------------------------------------------------------- 1 | using UmaMusumeData.Tables; 2 | 3 | namespace UmaMusumeExplorer.Controls.RaceMusicPlayer.Classes 4 | { 5 | public class BgmComboBoxItem 6 | { 7 | public RaceBgm? RaceBgm { get; set; } 8 | 9 | public override string ToString() 10 | { 11 | return RaceBgm?.Id.ToString() ?? ""; 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/RaceMusicPlayer/Classes/IEventSampleProvider.cs: -------------------------------------------------------------------------------- 1 | using NAudio.Wave; 2 | 3 | namespace UmaMusumeExplorer.Controls.RaceMusicPlayer.Classes 4 | { 5 | // Sample provider interface that uses events to signal the end of sample modification (fades, delays, etc.) 6 | interface IEventSampleProvider : ISampleProvider 7 | { 8 | public delegate void SampleProvideEventHandler(ISampleProvider source); 9 | public event SampleProvideEventHandler OnSampleProviderEvent; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/RaceMusicPlayer/Classes/Pattern.cs: -------------------------------------------------------------------------------- 1 | namespace UmaMusumeExplorer.Controls.RaceMusicPlayer.Classes 2 | { 3 | public class Pattern 4 | { 5 | public int BgmTime { get; set; } 6 | 7 | public string BgmCueName { get; set; } = ""; 8 | 9 | public string BgmCuesheetName { get; set; } = ""; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/RaceMusicPlayer/Classes/TestRunningBgmSampleProvider.cs: -------------------------------------------------------------------------------- 1 | using NAudio.Wave; 2 | using NAudio.Wave.SampleProviders; 3 | 4 | namespace UmaMusumeExplorer.Controls.RaceMusicPlayer.Classes 5 | { 6 | public class TestRunningBgmSampleProvider : ISampleProvider 7 | { 8 | private readonly FadeInOutSampleProvider first; 9 | private readonly ISampleProvider second; 10 | private readonly int fadeSampleCount; 11 | 12 | private bool lastSpurtTriggered = false; 13 | private int fadePosition = 0; 14 | 15 | public TestRunningBgmSampleProvider(Bgm firstPattern, Bgm secondPattern) 16 | { 17 | first = new(firstPattern.UmaWaveStream.ToSampleProvider()); 18 | second = secondPattern.UmaWaveStream.ToSampleProvider(); 19 | 20 | fadeSampleCount = 1000 * (WaveFormat.SampleRate / 1000); 21 | } 22 | 23 | public WaveFormat WaveFormat => first.WaveFormat; 24 | 25 | public void LastSpurt() 26 | { 27 | first.BeginFadeOut(500); 28 | lastSpurtTriggered = true; 29 | } 30 | 31 | public int Read(float[] buffer, int offset, int count) 32 | { 33 | first.Read(buffer, offset, count); 34 | 35 | if (fadePosition >= fadeSampleCount) 36 | { 37 | float[] buffer2 = new float[count]; 38 | second.Read(buffer2, 0, count); 39 | 40 | for (int i = 0; i < count; i++) 41 | { 42 | buffer[i] += buffer2[i]; 43 | } 44 | } 45 | 46 | if (lastSpurtTriggered && fadePosition < fadeSampleCount) 47 | { 48 | fadePosition += count; 49 | } 50 | 51 | return count; 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/SupportCardInfo/SupportCardInfoControl.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace UmaMusumeExplorer.Controls.SupportCardInfo 2 | { 3 | partial class SupportCardInfoControl 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Component Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | supportCardItemsPanel = new SupportCardItemsPanel(); 32 | markLimitedCheckBox = new CheckBox(); 33 | SuspendLayout(); 34 | // 35 | // supportCardItemsPanel 36 | // 37 | supportCardItemsPanel.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right; 38 | supportCardItemsPanel.Indeterminate = false; 39 | supportCardItemsPanel.Items = null; 40 | supportCardItemsPanel.Location = new Point(3, 28); 41 | supportCardItemsPanel.Name = "supportCardItemsPanel"; 42 | supportCardItemsPanel.Size = new Size(732, 306); 43 | supportCardItemsPanel.TabIndex = 0; 44 | // 45 | // markLimitedCheckBox 46 | // 47 | markLimitedCheckBox.Anchor = AnchorStyles.Top | AnchorStyles.Right; 48 | markLimitedCheckBox.AutoSize = true; 49 | markLimitedCheckBox.Location = new Point(612, 3); 50 | markLimitedCheckBox.Name = "markLimitedCheckBox"; 51 | markLimitedCheckBox.Size = new Size(123, 19); 52 | markLimitedCheckBox.TabIndex = 1; 53 | markLimitedCheckBox.Text = "Mark special cards"; 54 | markLimitedCheckBox.UseVisualStyleBackColor = true; 55 | markLimitedCheckBox.CheckedChanged += MarkLimitedCheckBox_CheckedChanged; 56 | // 57 | // SupportCardInfoControl 58 | // 59 | AutoScaleDimensions = new SizeF(7F, 15F); 60 | AutoScaleMode = AutoScaleMode.Font; 61 | Controls.Add(markLimitedCheckBox); 62 | Controls.Add(supportCardItemsPanel); 63 | Name = "SupportCardInfoControl"; 64 | Size = new Size(738, 337); 65 | Load += SupportCardInfoControl_Load; 66 | ResumeLayout(false); 67 | PerformLayout(); 68 | } 69 | 70 | #endregion 71 | 72 | private SupportCardItemsPanel supportCardItemsPanel; 73 | private CheckBox markLimitedCheckBox; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/SupportCardInfo/SupportCardInfoControl.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Data; 5 | using System.Drawing; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using System.Windows.Forms; 10 | using UmaMusumeData.Tables; 11 | using UmaMusumeExplorer.Controls.Common; 12 | using UmaMusumeExplorer.Game; 13 | 14 | namespace UmaMusumeExplorer.Controls.SupportCardInfo 15 | { 16 | public partial class SupportCardInfoControl : UserControl 17 | { 18 | private readonly IEnumerable supportCardDatas = AssetTables.SupportCardDatas; 19 | 20 | public SupportCardInfoControl() 21 | { 22 | InitializeComponent(); 23 | } 24 | 25 | private void SupportCardInfoControl_Load(object sender, EventArgs e) 26 | { 27 | supportCardItemsPanel.Items = supportCardDatas; 28 | } 29 | 30 | private void MarkLimitedCheckBox_CheckedChanged(object sender, EventArgs e) 31 | { 32 | foreach (HighlightPictureBox hpb in supportCardItemsPanel.Controls) 33 | { 34 | hpb.ShowHighlight = markLimitedCheckBox.Checked; 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Controls/SupportCardInfo/SupportCardItemsPanel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using UmaMusumeData; 7 | using UmaMusumeData.Tables; 8 | using UmaMusumeExplorer.Controls.CharacterInfo; 9 | using UmaMusumeExplorer.Controls.Common; 10 | using UmaMusumeExplorer.Game; 11 | 12 | namespace UmaMusumeExplorer.Controls.SupportCardInfo 13 | { 14 | internal class SupportCardItemsPanel : ItemsPanel 15 | { 16 | public override bool ProcessItem(SupportCardData supportCardData, ref Control? supportCardPictureBox) 17 | { 18 | bool limited = !AssetTables.GachaAvailables.Any(ga => ga.CardType == 2 && ga.CardId == supportCardData.Id); 19 | supportCardPictureBox = new HighlightPictureBox(limited) 20 | { 21 | BackgroundImage = UnityAssets.GetSupportCardIcon(supportCardData.Id)?.Bitmap, 22 | BackgroundImageLayout = ImageLayout.Stretch, 23 | Cursor = Cursors.Hand, 24 | Height = 166, 25 | Width = 127, 26 | Tag = supportCardData 27 | }; 28 | 29 | ToolTip toolTip = new(); 30 | toolTip.SetToolTip(supportCardPictureBox, $"{supportCardData.Id}: {AssetTables.GetText(TextCategory.MasterSupportCardTitleName, supportCardData.Id)}"); 31 | 32 | return true; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Game/AssetTables.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using UmaMusumeData; 4 | using UmaMusumeData.Tables; 5 | 6 | namespace UmaMusumeExplorer.Game 7 | { 8 | static class AssetTables 9 | { 10 | public static void Initialize() 11 | { 12 | Type assetTablesType = typeof(AssetTables); 13 | IEnumerable properties = assetTablesType.GetProperties().Where(p => p.PropertyType.Name == "List`1"); 14 | 15 | Queue customLoadAction = new(); 16 | customLoadAction.Enqueue(() => { AudioAssetEntries.AddRange(UmaDataHelper.GetManifestEntries(ga => ga.Name.StartsWith("sound/"))); return "AudioAssetEntries"; }); 17 | 18 | int completed = 0; 19 | foreach (var property in properties) 20 | { 21 | Type listType = property.PropertyType.GenericTypeArguments[0]; 22 | 23 | string name = property.Name; 24 | if (name == (listType.Name + "s")) 25 | { 26 | MethodInfo? targetMethod = (typeof(UmaDataHelper).GetMethod("GetMasterDatabaseRows")?.MakeGenericMethod(listType)) ?? 27 | throw new Exception("Could not find suitable method."); 28 | property.SetValue(null, targetMethod.Invoke(null, new object?[] { null })); 29 | } 30 | else 31 | { 32 | name = customLoadAction.Dequeue().Invoke(); 33 | } 34 | 35 | UpdateProgress?.Invoke((int)((float)++completed / properties.Count() * 100), name); 36 | } 37 | } 38 | 39 | public delegate string LoadAction(); 40 | 41 | public delegate void ProgressUpdater(int progress, string loadedName); 42 | 43 | public static ProgressUpdater? UpdateProgress { get; set; } 44 | 45 | public static List AudioAssetEntries { get; private set; } = new(); 46 | 47 | public static List AvailableSkillSets { get; private set; } = new(); 48 | 49 | public static List CardDatas { get; private set; } = new(); 50 | public static List CardRarityDatas { get; private set; } = new(); 51 | public static List CharaDatas { get; private set; } = new(); 52 | 53 | public static List CharacterSystemTexts { get; private set; } = new(); 54 | 55 | public static List GachaAvailables { get; private set; } = new(); 56 | 57 | public static List JukeboxMusicDatas { get; private set; } = new(); 58 | 59 | public static List LiveDatas { get; private set; } = new(); 60 | public static List LivePermissionDatas { get; private set; } = new(); 61 | 62 | public static List RaceBgms { get; private set; } = new(); 63 | public static List RaceBgmPatterns { get; private set; } = new(); 64 | 65 | public static List SkillSets { get; private set; } = new(); 66 | public static List SkillDatas { get; private set; } = new(); 67 | 68 | public static List SingleModeSkillNeedPoints { get; private set; } = new(); 69 | 70 | public static List SkillUpgradeConditions { get; private set; } = new(); 71 | public static List SkillUpgradeDescriptions { get; private set; } = new(); 72 | 73 | public static List SupportCardDatas { get; private set; } = new(); 74 | 75 | public static List TextDatas { get; private set; } = new(); 76 | 77 | public static string GetText(TextCategory category, int index) 78 | { 79 | return TextDatas.First(td => td.Category == (int)category && td.Index == index).Text; 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Game/ImagePointerContainer.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | 3 | namespace UmaMusumeExplorer.Game 4 | { 5 | class ImagePointerContainer 6 | { 7 | public ImagePointerContainer(GCHandle imageHandle, int width, int height) 8 | { 9 | ImageHandle = imageHandle; 10 | Width = width; 11 | Height = height; 12 | } 13 | 14 | public GCHandle ImageHandle { get; } 15 | 16 | public int Width { get; } 17 | 18 | public int Height { get; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Game/LoadingForm.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace UmaMusumeExplorer.Controls.Common 2 | { 3 | partial class LoadingForm 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | loadingProgressBar = new ProgressBar(); 32 | loadingBackgroundWorker = new System.ComponentModel.BackgroundWorker(); 33 | statusLabel = new Label(); 34 | SuspendLayout(); 35 | // 36 | // loadingProgressBar 37 | // 38 | loadingProgressBar.Location = new Point(12, 60); 39 | loadingProgressBar.Name = "loadingProgressBar"; 40 | loadingProgressBar.Size = new Size(497, 25); 41 | loadingProgressBar.TabIndex = 0; 42 | // 43 | // loadingBackgroundWorker 44 | // 45 | loadingBackgroundWorker.WorkerReportsProgress = true; 46 | loadingBackgroundWorker.DoWork += LoadingBackgroundWorker_DoWork; 47 | loadingBackgroundWorker.ProgressChanged += LoadingBackgroundWorker_ProgressChanged; 48 | loadingBackgroundWorker.RunWorkerCompleted += LoadingBackgroundWorker_RunWorkerCompleted; 49 | // 50 | // statusLabel 51 | // 52 | statusLabel.AutoSize = true; 53 | statusLabel.Location = new Point(12, 9); 54 | statusLabel.Name = "statusLabel"; 55 | statusLabel.Size = new Size(132, 15); 56 | statusLabel.TabIndex = 1; 57 | statusLabel.Text = "Loading AssetBundles..."; 58 | // 59 | // LoadingForm 60 | // 61 | AutoScaleDimensions = new SizeF(7F, 15F); 62 | AutoScaleMode = AutoScaleMode.Font; 63 | ClientSize = new Size(521, 97); 64 | Controls.Add(statusLabel); 65 | Controls.Add(loadingProgressBar); 66 | FormBorderStyle = FormBorderStyle.FixedSingle; 67 | MaximizeBox = false; 68 | Name = "LoadingForm"; 69 | StartPosition = FormStartPosition.Manual; 70 | Text = "Loading..."; 71 | Load += LoadingForm_Load; 72 | ResumeLayout(false); 73 | PerformLayout(); 74 | } 75 | 76 | #endregion 77 | 78 | private ProgressBar loadingProgressBar; 79 | private System.ComponentModel.BackgroundWorker loadingBackgroundWorker; 80 | private Label statusLabel; 81 | } 82 | } -------------------------------------------------------------------------------- /UmaMusumeExplorer/Game/LoadingForm.cs: -------------------------------------------------------------------------------- 1 | using AssetsTools.NET.Extra; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.ComponentModel; 5 | using System.Data; 6 | using System.Drawing; 7 | using System.Linq; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | using System.Windows.Forms; 11 | 12 | namespace UmaMusumeExplorer.Controls.Common 13 | { 14 | public partial class LoadingForm : Form 15 | { 16 | private readonly AssetsManager assetsManager; 17 | private readonly IEnumerable filePaths; 18 | 19 | public LoadingForm(AssetsManager assetsManager, IEnumerable filePaths) 20 | { 21 | InitializeComponent(); 22 | 23 | this.assetsManager = assetsManager; 24 | this.filePaths = filePaths; 25 | } 26 | 27 | private void LoadingBackgroundWorker_DoWork(object sender, DoWorkEventArgs e) 28 | { 29 | if (sender is not BackgroundWorker worker) return; 30 | 31 | List<(BundleFileInstance bundle, string name)> filesAndBundles = new(); 32 | 33 | Invoke(() => statusLabel.Text = "Loading AssetBundles..."); 34 | int currentItem = 1; 35 | foreach (var file in filePaths) 36 | { 37 | BundleFileInstance bundle = assetsManager.LoadBundleFile(file); 38 | foreach (var assetsFile in bundle.file.GetAllFileNames()) 39 | { 40 | filesAndBundles.Add((bundle, assetsFile)); 41 | } 42 | worker.ReportProgress((int)((float)currentItem++ / filePaths.Count() * 100F)); 43 | } 44 | 45 | Invoke(() => statusLabel.Text = "Loading assets..."); 46 | currentItem = 1; 47 | foreach (var (bundle, name) in filesAndBundles) 48 | { 49 | assetsManager.LoadAssetsFileFromBundle(bundle, name); 50 | worker.ReportProgress((int)((float)currentItem++ / filesAndBundles.Count * 100F)); 51 | } 52 | } 53 | 54 | private void LoadingBackgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e) 55 | { 56 | loadingProgressBar.Value = e.ProgressPercentage; 57 | } 58 | 59 | private void LoadingBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 60 | { 61 | Close(); 62 | } 63 | 64 | private void LoadingForm_Load(object sender, EventArgs e) 65 | { 66 | loadingBackgroundWorker.RunWorkerAsync(); 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Game/PinnedBitmap.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | 3 | namespace UmaMusumeExplorer.Game 4 | { 5 | class PinnedBitmap : IDisposable 6 | { 7 | private readonly GCHandle bitmapHandle; 8 | private readonly Bitmap bitmap; 9 | 10 | public PinnedBitmap(byte[] imageBytes, int width, int height) 11 | { 12 | bitmapHandle = GCHandle.Alloc(imageBytes, GCHandleType.Pinned); 13 | bitmap = new Bitmap( 14 | width, 15 | height, 16 | width * 4, 17 | System.Drawing.Imaging.PixelFormat.Format32bppArgb, 18 | bitmapHandle.AddrOfPinnedObject()); 19 | } 20 | 21 | public PinnedBitmap(IntPtr imageDataHandle, int width, int height) 22 | { 23 | bitmap = new Bitmap( 24 | width, 25 | height, 26 | width * 4, 27 | System.Drawing.Imaging.PixelFormat.Format32bppArgb, 28 | imageDataHandle); 29 | } 30 | 31 | public Bitmap Bitmap => bitmap; 32 | 33 | public void Dispose() 34 | { 35 | bitmap.Dispose(); 36 | 37 | if (bitmapHandle.IsAllocated) 38 | bitmapHandle.Free(); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/MainForm.cs: -------------------------------------------------------------------------------- 1 | using UmaMusumeExplorer.Controls; 2 | using UmaMusumeExplorer.Game; 3 | 4 | namespace UmaMusumeExplorer 5 | { 6 | partial class MainForm : Form 7 | { 8 | public MainForm() 9 | { 10 | InitializeComponent(); 11 | } 12 | 13 | private void MainForm_FormClosing(object sender, FormClosingEventArgs e) 14 | { 15 | ControlHelpers.CloseAllForms(); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Program.cs: -------------------------------------------------------------------------------- 1 | namespace UmaMusumeExplorer 2 | { 3 | static class Program 4 | { 5 | /// 6 | /// The main entry point for the application. 7 | /// 8 | [STAThread] 9 | static void Main() 10 | { 11 | Application.SetHighDpiMode(HighDpiMode.SystemAware); 12 | Application.EnableVisualStyles(); 13 | Application.SetCompatibleTextRenderingDefault(false); 14 | Application.Run(new UmaApplicationContext()); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace UmaMusumeExplorer.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("UmaMusumeExplorer.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | 63 | /// 64 | /// Looks up a localized resource of type System.Drawing.Icon similar to (Icon). 65 | /// 66 | internal static System.Drawing.Icon FolderIcon { 67 | get { 68 | object obj = ResourceManager.GetObject("FolderIcon", resourceCulture); 69 | return ((System.Drawing.Icon)(obj)); 70 | } 71 | } 72 | 73 | /// 74 | /// Looks up a localized resource of type System.Drawing.Icon similar to (Icon). 75 | /// 76 | internal static System.Drawing.Icon ProgramIcon { 77 | get { 78 | object obj = ResourceManager.GetObject("ProgramIcon", resourceCulture); 79 | return ((System.Drawing.Icon)(obj)); 80 | } 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/Resources/FileIcon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarshmallowAndroid/UmaMusumeExplorer/52e8001492235d85a40e3731eb53143d2ca1596b/UmaMusumeExplorer/Resources/FileIcon.ico -------------------------------------------------------------------------------- /UmaMusumeExplorer/Resources/FolderIcon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarshmallowAndroid/UmaMusumeExplorer/52e8001492235d85a40e3731eb53143d2ca1596b/UmaMusumeExplorer/Resources/FolderIcon.ico -------------------------------------------------------------------------------- /UmaMusumeExplorer/Resources/ProgramIcon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarshmallowAndroid/UmaMusumeExplorer/52e8001492235d85a40e3731eb53143d2ca1596b/UmaMusumeExplorer/Resources/ProgramIcon.ico -------------------------------------------------------------------------------- /UmaMusumeExplorer/SplashForm.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace UmaMusumeExplorer 2 | { 3 | partial class SplashForm 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | titleLabel = new Label(); 32 | loadingLabel = new Label(); 33 | loadingProgressBar = new ProgressBar(); 34 | SuspendLayout(); 35 | // 36 | // titleLabel 37 | // 38 | titleLabel.AutoSize = true; 39 | titleLabel.Font = new Font("Segoe UI", 24F, FontStyle.Bold, GraphicsUnit.Point); 40 | titleLabel.Location = new Point(111, 34); 41 | titleLabel.Name = "titleLabel"; 42 | titleLabel.Size = new Size(363, 45); 43 | titleLabel.TabIndex = 0; 44 | titleLabel.Text = "Uma Musume Explorer"; 45 | // 46 | // loadingLabel 47 | // 48 | loadingLabel.Font = new Font("Segoe UI", 15.75F, FontStyle.Regular, GraphicsUnit.Point); 49 | loadingLabel.Location = new Point(12, 79); 50 | loadingLabel.Name = "loadingLabel"; 51 | loadingLabel.Size = new Size(561, 30); 52 | loadingLabel.TabIndex = 1; 53 | loadingLabel.Text = "Reading tables..."; 54 | loadingLabel.TextAlign = ContentAlignment.MiddleCenter; 55 | // 56 | // loadingProgressBar 57 | // 58 | loadingProgressBar.Location = new Point(111, 112); 59 | loadingProgressBar.Name = "loadingProgressBar"; 60 | loadingProgressBar.Size = new Size(363, 23); 61 | loadingProgressBar.TabIndex = 2; 62 | // 63 | // SplashForm 64 | // 65 | AutoScaleDimensions = new SizeF(7F, 15F); 66 | AutoScaleMode = AutoScaleMode.Font; 67 | ClientSize = new Size(585, 169); 68 | Controls.Add(loadingProgressBar); 69 | Controls.Add(loadingLabel); 70 | Controls.Add(titleLabel); 71 | FormBorderStyle = FormBorderStyle.None; 72 | Name = "SplashForm"; 73 | ShowInTaskbar = false; 74 | StartPosition = FormStartPosition.CenterScreen; 75 | Text = "SplashForm"; 76 | Load += SplashForm_Load; 77 | ResumeLayout(false); 78 | PerformLayout(); 79 | } 80 | 81 | #endregion 82 | 83 | private System.Windows.Forms.Label titleLabel; 84 | private System.Windows.Forms.Label loadingLabel; 85 | private System.Windows.Forms.ProgressBar loadingProgressBar; 86 | } 87 | } -------------------------------------------------------------------------------- /UmaMusumeExplorer/SplashForm.cs: -------------------------------------------------------------------------------- 1 | using UmaMusumeExplorer.Game; 2 | 3 | namespace UmaMusumeExplorer 4 | { 5 | public partial class SplashForm : Form 6 | { 7 | private Thread? loadThread; 8 | private bool loadSuccess = false; 9 | 10 | public SplashForm() 11 | { 12 | InitializeComponent(); 13 | } 14 | 15 | public bool LoadAndClose() 16 | { 17 | loadThread = new(() => 18 | { 19 | try 20 | { 21 | AssetTables.UpdateProgress += UpdateProgress; 22 | AssetTables.Initialize(); 23 | AssetTables.UpdateProgress -= UpdateProgress; 24 | Invoke(() => Close()); 25 | loadSuccess = true; 26 | } 27 | catch (Exception e) 28 | { 29 | MessageBox.Show($"Error reading tables. Please launch the game and allow itself to repair.\n\nMessage:\n{e.InnerException?.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 30 | Application.Exit(); 31 | } 32 | }); 33 | TopMost = true; 34 | ShowDialog(); 35 | 36 | return loadSuccess; 37 | } 38 | 39 | private void UpdateProgress(int progress, string name) 40 | { 41 | Invoke(() => 42 | { 43 | loadingProgressBar.Value = progress; 44 | loadingLabel.Text = $"Loading {name}..."; 45 | }); 46 | } 47 | 48 | private void SplashForm_Load(object sender, EventArgs e) 49 | { 50 | loadThread?.Start(); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/UmaApplicationContext.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using UmaMusumeData; 7 | using UmaMusumeExplorer.Game; 8 | 9 | namespace UmaMusumeExplorer 10 | { 11 | class UmaApplicationContext : ApplicationContext 12 | { 13 | private const string pathTextFile = "UmaMusumePath.txt"; 14 | 15 | public UmaApplicationContext() 16 | { 17 | if (File.Exists(pathTextFile)) 18 | UmaDataHelper.UmaMusumeDirectory = File.ReadAllText(pathTextFile).Trim(); 19 | 20 | if (!UmaDataHelper.CheckDirectory()) 21 | { 22 | DialogResult result = MessageBox.Show( 23 | "Unable to find the required files in the default data directory.\n" + 24 | "If you have not installed, launched, or updated the game, please do so.\n\n" + 25 | "Otherwise, you must specify the directory if you have changed the installation location.\n\n" + 26 | "Would you like to continue?", 27 | "Missing files", 28 | MessageBoxButtons.YesNo, 29 | MessageBoxIcon.Information); 30 | if (result == DialogResult.Yes) 31 | { 32 | while (true) 33 | { 34 | FolderBrowserDialog browserDialog = new(); 35 | DialogResult browseResult = browserDialog.ShowDialog(); 36 | 37 | if (browseResult == DialogResult.OK) 38 | { 39 | UmaDataHelper.UmaMusumeDirectory = browserDialog.SelectedPath; 40 | 41 | if (UmaDataHelper.CheckDirectory()) 42 | { 43 | File.WriteAllText(pathTextFile, UmaDataHelper.UmaMusumeDirectory); 44 | break; 45 | } 46 | 47 | MessageBox.Show("Please select a valid data directory containing the \"dat\" folder, " + 48 | "the \"meta\" file, and the \"master\" folder with the \"master.mdb\" file.", 49 | "Missing files", 50 | MessageBoxButtons.OK, 51 | MessageBoxIcon.Information); 52 | } 53 | else 54 | { 55 | Environment.Exit(1); 56 | return; 57 | } 58 | } 59 | } 60 | else 61 | { 62 | Environment.Exit(1); 63 | return; 64 | } 65 | } 66 | 67 | SplashForm splashForm = new(); 68 | if (splashForm.LoadAndClose()) 69 | { 70 | MainForm mainForm = new(); 71 | mainForm.Show(); 72 | MainForm = mainForm; 73 | //mainForm.FormClosed += (s, e) => ExitThread(); 74 | 75 | UnityAssets.MainForm = mainForm; 76 | } 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /UmaMusumeExplorer/UmaMusumeExplorer.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | WinExe 5 | net8.0-windows 6 | enable 7 | true 8 | enable 9 | UmaMusumeExplorer.Program 10 | Resources\ProgramIcon.ico 11 | 1.3.1.0 12 | 1.3.1.0 13 | 1.2.9 14 | Uma Musume Explorer 15 | Uma Musume Explorer 16 | Jacob Tarun 17 | en-US 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | True 41 | True 42 | Resources.resx 43 | 44 | 45 | 46 | 47 | 48 | ResXFileCodeGenerator 49 | Resources.Designer.cs 50 | 51 | 52 | 53 | --------------------------------------------------------------------------------