AGIDMGen 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- AGIDMGen/IDModGenService.py +300 -0
- AGIDMGen/__init__.py +78 -0
- AGIDMGen/__main__.py +24 -0
- AGIDMGen/constants/DXGIFormats.py +35 -0
- AGIDMGen/constants/DumpDataKinds.py +41 -0
- AGIDMGen/constants/FileEncodings.py +39 -0
- AGIDMGen/constants/GIMIBuffers.py +53 -0
- AGIDMGen/constants/GIMITextureLayouts.py +58 -0
- AGIDMGen/constants/ModDownloadRepos.py +45 -0
- AGIDMGen/constants/ModLoaders.py +33 -0
- AGIDMGen/constants/WWMIBuffers.py +95 -0
- AGIDMGen/constants/__init__.py +13 -0
- AGIDMGen/data/ModDownloadData.py +4519 -0
- AGIDMGen/data/__init__.py +13 -0
- AGIDMGen/exceptions/BadAssetData.py +31 -0
- AGIDMGen/exceptions/DownloadFailed.py +39 -0
- AGIDMGen/exceptions/Error.py +25 -0
- AGIDMGen/exceptions/UnknownDXGIFormat.py +37 -0
- AGIDMGen/exceptions/__init__.py +13 -0
- AGIDMGen/main.py +272 -0
- AGIDMGen/model/IDModGenStats.py +84 -0
- AGIDMGen/model/ModDownload.py +74 -0
- AGIDMGen/model/__init__.py +13 -0
- AGIDMGen/model/files/DumpDataType.py +144 -0
- AGIDMGen/model/files/DumpElement.py +109 -0
- AGIDMGen/model/files/FmtFile.py +161 -0
- AGIDMGen/model/files/IbDumpFile.py +119 -0
- AGIDMGen/model/files/VbDumpFile.py +217 -0
- AGIDMGen/model/files/__init__.py +13 -0
- AGIDMGen/model/gimi/GIMIComponent.py +112 -0
- AGIDMGen/model/gimi/GIMIIdentityMod.py +122 -0
- AGIDMGen/model/gimi/GIMITextureSource.py +145 -0
- AGIDMGen/model/gimi/__init__.py +13 -0
- AGIDMGen/model/wwmi/WWMIBlendRemap.py +54 -0
- AGIDMGen/model/wwmi/WWMIComponent.py +235 -0
- AGIDMGen/model/wwmi/WWMIDrawRange.py +93 -0
- AGIDMGen/model/wwmi/WWMIIdentityMod.py +201 -0
- AGIDMGen/model/wwmi/WWMIMesh.py +94 -0
- AGIDMGen/model/wwmi/WWMIShapeKeys.py +101 -0
- AGIDMGen/model/wwmi/__init__.py +13 -0
- AGIDMGen/py.typed +0 -0
- AGIDMGen/tools/DumpValueTools.py +120 -0
- AGIDMGen/tools/FormatTools.py +58 -0
- AGIDMGen/tools/ModDownloader.py +300 -0
- AGIDMGen/tools/VersionTools.py +108 -0
- AGIDMGen/tools/__init__.py +13 -0
- AGIDMGen/tools/gimi/GIMIDownloadFolderBuilder.py +187 -0
- AGIDMGen/tools/gimi/GIMIIdentityModGenerator.py +553 -0
- AGIDMGen/tools/gimi/GIMIIniBuilder.py +153 -0
- AGIDMGen/tools/gimi/__init__.py +13 -0
- AGIDMGen/tools/wwmi/WWMIDownloadFolderBuilder.py +113 -0
- AGIDMGen/tools/wwmi/WWMIIdentityModGenerator.py +853 -0
- AGIDMGen/tools/wwmi/WWMIIniBuilder.py +284 -0
- AGIDMGen/tools/wwmi/__init__.py +13 -0
- agidmgen-0.1.0.dist-info/METADATA +259 -0
- agidmgen-0.1.0.dist-info/RECORD +59 -0
- agidmgen-0.1.0.dist-info/WHEEL +5 -0
- agidmgen-0.1.0.dist-info/licenses/LICENSE +21 -0
- agidmgen-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
##### Credits
|
|
2
|
+
|
|
3
|
+
# ===== Anime Game Identity Mod Generator (AGIDMGen) =====
|
|
4
|
+
# Authors: Albert Gold#2696
|
|
5
|
+
#
|
|
6
|
+
# A sub-project of Anime Game Remap (AG Remap)
|
|
7
|
+
# if you used it to make your mods pls give credit for "Albert Gold#2696"
|
|
8
|
+
|
|
9
|
+
##### EndCredits
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
##### ExtImports
|
|
13
|
+
import os
|
|
14
|
+
from typing import Any, List, Optional, Union
|
|
15
|
+
from FixRaidenBoss2 import BaseLogger, Model
|
|
16
|
+
##### EndExtImports
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
##### LocalImports
|
|
20
|
+
from .constants.ModLoaders import ModLoaders
|
|
21
|
+
from .exceptions.Error import Error
|
|
22
|
+
from .model.IDModGenStats import IDModGenStats
|
|
23
|
+
from .tools.ModDownloader import ModDownloader
|
|
24
|
+
from .tools.gimi.GIMIIdentityModGenerator import GIMIIdentityModGenerator
|
|
25
|
+
from .tools.wwmi.WWMIIdentityModGenerator import WWMIIdentityModGenerator
|
|
26
|
+
##### EndLocalImports
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
##### Script
|
|
30
|
+
class IDModGenService(Model):
|
|
31
|
+
"""
|
|
32
|
+
The library's entry point: generates the identity mods of several characters at once, from their asset
|
|
33
|
+
folders or from their download folders, and reports what it did
|
|
34
|
+
|
|
35
|
+
It is the model half, with no user interface of its own: progress and the summary go to the
|
|
36
|
+
:attr:`logger` (nothing is reported without one), and the results are in :attr:`stats`. A character that
|
|
37
|
+
cannot be generated does not stop the others: its exception is recorded in :attr:`IDModGenStats.skipped`.
|
|
38
|
+
|
|
39
|
+
.. note::
|
|
40
|
+
Like Anime Game Remap's ``RemapService``, :meth:`generate` returns nothing; read :attr:`stats` after it.
|
|
41
|
+
For one character, a generator (:class:`GIMIIdentityModGenerator` or :class:`WWMIIdentityModGenerator`)
|
|
42
|
+
can be used directly instead, and raises when it fails.
|
|
43
|
+
|
|
44
|
+
Examples
|
|
45
|
+
--------
|
|
46
|
+
.. code-block:: python
|
|
47
|
+
:linenos:
|
|
48
|
+
|
|
49
|
+
import AGIDMGen as IDMG
|
|
50
|
+
import FixRaidenBoss2 as FRB # Anime Game Remap's API: its logger serves both libraries
|
|
51
|
+
|
|
52
|
+
# every character's newest download folder, printed as it goes
|
|
53
|
+
service = IDMG.IDModGenService(IDMG.ModLoaders.GIMI, names = ["Yelan", "Ayaka"], outputFolder = "Mods", logger = FRB.Logger())
|
|
54
|
+
service.generate()
|
|
55
|
+
print(sorted(service.stats.generated), service.stats.skipped)
|
|
56
|
+
|
|
57
|
+
# from asset folders, collecting the output instead of printing it (eg. in a server)
|
|
58
|
+
logger = FRB.Logger(logTxt = True, verbose = False)
|
|
59
|
+
service = IDMG.IDModGenService(IDMG.ModLoaders.WWMI, assetsFolders = ["WWMI-Assets/PlayerCharacterData/Sanhua"], logger = logger)
|
|
60
|
+
service.generate()
|
|
61
|
+
print(logger.loggedTxt)
|
|
62
|
+
|
|
63
|
+
Parameters
|
|
64
|
+
----------
|
|
65
|
+
loader: :class:`ModLoaders`
|
|
66
|
+
The mod loader the mods are for
|
|
67
|
+
|
|
68
|
+
assetsFolders: Optional[List[:class:`str`]]
|
|
69
|
+
The characters' asset folders to generate from. If this value is ``None``, no asset folder is used :raw-html:`<br />` :raw-html:`<br />`
|
|
70
|
+
|
|
71
|
+
**Default**: ``None``
|
|
72
|
+
|
|
73
|
+
names: Optional[List[:class:`str`]]
|
|
74
|
+
The characters to generate from their download folders (see :meth:`ModDownloader.getName`). If this value is ``None``, no download folder is used :raw-html:`<br />` :raw-html:`<br />`
|
|
75
|
+
|
|
76
|
+
**Default**: ``None``
|
|
77
|
+
|
|
78
|
+
outputFolder: Optional[:class:`str`]
|
|
79
|
+
The folder each mod is written into, as ``<outputFolder>/<name>``. If this value is ``None``, the current folder is used :raw-html:`<br />` :raw-html:`<br />`
|
|
80
|
+
|
|
81
|
+
**Default**: ``None``
|
|
82
|
+
|
|
83
|
+
version: Optional[:class:`str`]
|
|
84
|
+
The game version wanted for the download folders (see :meth:`ModDownloader.find`). If this value is ``None``, the newest :raw-html:`<br />` :raw-html:`<br />`
|
|
85
|
+
|
|
86
|
+
**Default**: ``None``
|
|
87
|
+
|
|
88
|
+
downloader: Optional[:class:`ModDownloader`]
|
|
89
|
+
What downloads the download folders. If this value is ``None``, one that downloads every file :raw-html:`<br />` :raw-html:`<br />`
|
|
90
|
+
|
|
91
|
+
**Default**: ``None``
|
|
92
|
+
|
|
93
|
+
downloadFolder: Optional[:class:`str`]
|
|
94
|
+
The folder to keep the downloaded files in, as ``<downloadFolder>/<name>``. If this value is ``None``, temporary folders are used :raw-html:`<br />` :raw-html:`<br />`
|
|
95
|
+
|
|
96
|
+
**Default**: ``None``
|
|
97
|
+
|
|
98
|
+
generator: Optional[Union[:class:`GIMIIdentityModGenerator`, :class:`WWMIIdentityModGenerator`]]
|
|
99
|
+
The generator, with its options. If this value is ``None``, one for ``loader`` with its default options :raw-html:`<br />` :raw-html:`<br />`
|
|
100
|
+
|
|
101
|
+
**Default**: ``None``
|
|
102
|
+
|
|
103
|
+
modName: Optional[:class:`str`]
|
|
104
|
+
The name of the character in the mod, when there is only one character. If this value is ``None``, the generator's default :raw-html:`<br />` :raw-html:`<br />`
|
|
105
|
+
|
|
106
|
+
**Default**: ``None``
|
|
107
|
+
|
|
108
|
+
assetPrefix: Optional[:class:`str`]
|
|
109
|
+
What a GIMI asset folder's files start with, when there is only one asset folder (see :meth:`GIMIIdentityModGenerator.generate`) :raw-html:`<br />` :raw-html:`<br />`
|
|
110
|
+
|
|
111
|
+
**Default**: ``None``
|
|
112
|
+
|
|
113
|
+
handleExceptions: :class:`bool`
|
|
114
|
+
Whether a failure of the whole run (eg. options that contradict each other) is reported to the logger and :meth:`generate` returns, rather than raised :raw-html:`<br />` :raw-html:`<br />`
|
|
115
|
+
|
|
116
|
+
**Default**: ``False``
|
|
117
|
+
|
|
118
|
+
logger: Optional[:class:`BaseLogger`]
|
|
119
|
+
Where the run reports progress. If this value is ``None``, nothing is reported :raw-html:`<br />` :raw-html:`<br />`
|
|
120
|
+
|
|
121
|
+
**Default**: ``None``
|
|
122
|
+
|
|
123
|
+
Attributes
|
|
124
|
+
----------
|
|
125
|
+
loader: :class:`ModLoaders`
|
|
126
|
+
The mod loader the mods are for
|
|
127
|
+
|
|
128
|
+
assetsFolders: List[:class:`str`]
|
|
129
|
+
The characters' asset folders to generate from
|
|
130
|
+
|
|
131
|
+
names: List[:class:`str`]
|
|
132
|
+
The characters to generate from their download folders
|
|
133
|
+
|
|
134
|
+
outputFolder: :class:`str`
|
|
135
|
+
The folder each mod is written into
|
|
136
|
+
|
|
137
|
+
version: Optional[:class:`str`]
|
|
138
|
+
The game version wanted for the download folders
|
|
139
|
+
|
|
140
|
+
downloader: :class:`ModDownloader`
|
|
141
|
+
What downloads the download folders
|
|
142
|
+
|
|
143
|
+
downloadFolder: Optional[:class:`str`]
|
|
144
|
+
The folder to keep the downloaded files in
|
|
145
|
+
|
|
146
|
+
generator: Union[:class:`GIMIIdentityModGenerator`, :class:`WWMIIdentityModGenerator`]
|
|
147
|
+
The generator
|
|
148
|
+
|
|
149
|
+
modName: Optional[:class:`str`]
|
|
150
|
+
The name of the character in the mod, when there is only one character
|
|
151
|
+
|
|
152
|
+
assetPrefix: Optional[:class:`str`]
|
|
153
|
+
What a GIMI asset folder's files start with, when there is only one asset folder
|
|
154
|
+
|
|
155
|
+
handleExceptions: :class:`bool`
|
|
156
|
+
Whether a failure of the whole run is reported rather than raised
|
|
157
|
+
"""
|
|
158
|
+
|
|
159
|
+
def __init__(self, loader: ModLoaders, assetsFolders: Optional[List[str]] = None, names: Optional[List[str]] = None, outputFolder: Optional[str] = None,
|
|
160
|
+
version: Optional[str] = None, downloader: Optional[ModDownloader] = None, downloadFolder: Optional[str] = None,
|
|
161
|
+
generator: Optional[Union[GIMIIdentityModGenerator, WWMIIdentityModGenerator]] = None, modName: Optional[str] = None,
|
|
162
|
+
assetPrefix: Optional[str] = None, handleExceptions: bool = False, logger: Optional[BaseLogger] = None):
|
|
163
|
+
super().__init__(logger = logger)
|
|
164
|
+
self.loader = loader
|
|
165
|
+
self.assetsFolders = [] if (assetsFolders is None) else list(assetsFolders)
|
|
166
|
+
self.names = [] if (names is None) else list(names)
|
|
167
|
+
self.outputFolder = os.getcwd() if (outputFolder is None) else outputFolder
|
|
168
|
+
self.version = version
|
|
169
|
+
self.downloader = ModDownloader(logger = logger) if (downloader is None) else downloader
|
|
170
|
+
self.downloadFolder = downloadFolder
|
|
171
|
+
self.generator = generator
|
|
172
|
+
self.modName = modName
|
|
173
|
+
self.assetPrefix = assetPrefix
|
|
174
|
+
self.handleExceptions = handleExceptions
|
|
175
|
+
self._stats = IDModGenStats()
|
|
176
|
+
|
|
177
|
+
@property
|
|
178
|
+
def stats(self) -> IDModGenStats:
|
|
179
|
+
"""
|
|
180
|
+
What the last :meth:`generate` did
|
|
181
|
+
|
|
182
|
+
:getter: Retrieves the stats
|
|
183
|
+
:type: :class:`IDModGenStats`
|
|
184
|
+
"""
|
|
185
|
+
|
|
186
|
+
return self._stats
|
|
187
|
+
|
|
188
|
+
def _getGenerator(self) -> Union[GIMIIdentityModGenerator, WWMIIdentityModGenerator]:
|
|
189
|
+
expected = GIMIIdentityModGenerator if (self.loader == ModLoaders.GIMI) else WWMIIdentityModGenerator
|
|
190
|
+
if (self.generator is None):
|
|
191
|
+
return expected(logger = self.logger)
|
|
192
|
+
if (not isinstance(self.generator, expected)):
|
|
193
|
+
raise Error(f"a {type(self.generator).__name__} cannot generate {self.loader.value} mods")
|
|
194
|
+
if (self.generator.logger is None):
|
|
195
|
+
self.generator.logger = self.logger
|
|
196
|
+
return self.generator
|
|
197
|
+
|
|
198
|
+
def _checkOptions(self):
|
|
199
|
+
sourceCount = len(self.assetsFolders) + len(self.names)
|
|
200
|
+
if (sourceCount == 0):
|
|
201
|
+
raise Error("there is nothing to generate: give asset folders or character names")
|
|
202
|
+
if (self.modName is not None and sourceCount > 1):
|
|
203
|
+
raise Error("a mod name can only be given for one character")
|
|
204
|
+
if (self.assetPrefix is not None and (len(self.assetsFolders) != 1 or self.names)):
|
|
205
|
+
raise Error("an asset prefix can only be given for one asset folder")
|
|
206
|
+
if (self.assetPrefix is not None and self.loader != ModLoaders.GIMI):
|
|
207
|
+
raise Error("an asset prefix is only for GIMI asset folders")
|
|
208
|
+
|
|
209
|
+
def _reportException(self, error: BaseException):
|
|
210
|
+
# the library's own errors explain themselves; anything else is a bug, and gets its traceback
|
|
211
|
+
if (isinstance(error, Error)):
|
|
212
|
+
self.print("error", str(error))
|
|
213
|
+
else:
|
|
214
|
+
self.print("handleException", error)
|
|
215
|
+
|
|
216
|
+
def _generateOne(self, generator, label: str, generate) -> Optional[Any]:
|
|
217
|
+
self.print("openHeading", label, sideLen = 5)
|
|
218
|
+
try:
|
|
219
|
+
mod = generate()
|
|
220
|
+
except Exception as e:
|
|
221
|
+
self._stats.addSkipped(label, e)
|
|
222
|
+
self._reportException(e)
|
|
223
|
+
self.print("closeHeading")
|
|
224
|
+
return None
|
|
225
|
+
|
|
226
|
+
self._stats.addGenerated(label, mod)
|
|
227
|
+
for line in mod.getSummary():
|
|
228
|
+
self.print("log", line)
|
|
229
|
+
self.print("closeHeading")
|
|
230
|
+
self.print("space")
|
|
231
|
+
return mod
|
|
232
|
+
|
|
233
|
+
def generate(self):
|
|
234
|
+
"""
|
|
235
|
+
Generates the identity mods, then reports what was done
|
|
236
|
+
|
|
237
|
+
Raises
|
|
238
|
+
------
|
|
239
|
+
:class:`Error`
|
|
240
|
+
If the options contradict each other, and :attr:`handleExceptions` is ``False``
|
|
241
|
+
"""
|
|
242
|
+
|
|
243
|
+
self._stats.clear()
|
|
244
|
+
try:
|
|
245
|
+
self._checkOptions()
|
|
246
|
+
generator = self._getGenerator()
|
|
247
|
+
except Exception as e:
|
|
248
|
+
if (not self.handleExceptions):
|
|
249
|
+
raise
|
|
250
|
+
self._reportException(e)
|
|
251
|
+
return
|
|
252
|
+
|
|
253
|
+
prevPrefix = None if (self.logger is None) else self.logger.prefix
|
|
254
|
+
for assetsFolder in self.assetsFolders:
|
|
255
|
+
label = os.path.basename(os.path.normpath(assetsFolder))
|
|
256
|
+
if (self.logger is not None):
|
|
257
|
+
self.logger.prefix = label
|
|
258
|
+
|
|
259
|
+
kwargs = {"name": self.modName}
|
|
260
|
+
if (self.loader == ModLoaders.GIMI):
|
|
261
|
+
kwargs["assetPrefix"] = self.assetPrefix
|
|
262
|
+
modFolder = os.path.join(self.outputFolder, self.modName if (self.modName is not None) else label)
|
|
263
|
+
self._generateOne(generator, label, lambda: generator.generate(assetsFolder, modFolder, **kwargs))
|
|
264
|
+
|
|
265
|
+
for name in self.names:
|
|
266
|
+
if (self.logger is not None):
|
|
267
|
+
self.logger.prefix = name
|
|
268
|
+
|
|
269
|
+
modFolder = os.path.join(self.outputFolder, self.modName if (self.modName is not None) else name)
|
|
270
|
+
downloadFolder = None if (self.downloadFolder is None) else os.path.join(self.downloadFolder, name)
|
|
271
|
+
self._generateOne(generator, name, lambda: generator.generateFromRepo(name, modFolder, version = self.version, downloader = self.downloader,
|
|
272
|
+
downloadFolder = downloadFolder, modName = self.modName))
|
|
273
|
+
|
|
274
|
+
if (self.logger is not None):
|
|
275
|
+
self.logger.prefix = prevPrefix
|
|
276
|
+
self.report()
|
|
277
|
+
|
|
278
|
+
def report(self):
|
|
279
|
+
"""
|
|
280
|
+
Reports the summary of the last :meth:`generate` to the logger
|
|
281
|
+
"""
|
|
282
|
+
|
|
283
|
+
if (self.logger is None):
|
|
284
|
+
return
|
|
285
|
+
|
|
286
|
+
includePrefix = self.logger.includePrefix
|
|
287
|
+
self.logger.includePrefix = False
|
|
288
|
+
self.print("openHeading", "Summary", sideLen = 10)
|
|
289
|
+
self.print("log", f"Generated {len(self._stats.generated)} identity mod(s) into {self.outputFolder}")
|
|
290
|
+
if (self._stats.skipped):
|
|
291
|
+
self.print("log", f"Could not generate {len(self._stats.skipped)}:")
|
|
292
|
+
for name, error in self._stats.skipped.items():
|
|
293
|
+
self.print("bulletPoint", f"{name}: {error}")
|
|
294
|
+
self.print("closeHeading")
|
|
295
|
+
|
|
296
|
+
if (self._stats.noErrors):
|
|
297
|
+
self.print("space")
|
|
298
|
+
self.print("log", "ENJOY")
|
|
299
|
+
self.logger.includePrefix = includePrefix
|
|
300
|
+
##### EndScript
|
AGIDMGen/__init__.py
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
##### Credits
|
|
2
|
+
|
|
3
|
+
# ===== Anime Game Identity Mod Generator (AGIDMGen) =====
|
|
4
|
+
# Authors: Albert Gold#2696
|
|
5
|
+
#
|
|
6
|
+
# A sub-project of Anime Game Remap (AG Remap)
|
|
7
|
+
# if you used it to make your mods pls give credit for "Albert Gold#2696"
|
|
8
|
+
|
|
9
|
+
##### EndCredits
|
|
10
|
+
|
|
11
|
+
##### LocalImports
|
|
12
|
+
|
|
13
|
+
# --- Constants --------
|
|
14
|
+
from .constants.DumpDataKinds import DumpDataKinds
|
|
15
|
+
from .constants.DXGIFormats import DXGIFormats, DXGIFormatPrefix
|
|
16
|
+
from .constants.FileEncodings import FileEncodings, IniFileEncoding, ReadEncodings
|
|
17
|
+
from .constants.GIMIBuffers import GIMIBuffers, GIMISemanticBuffers, GIMIFixedStrides, GIMIHashFileSuffix
|
|
18
|
+
from .constants.GIMITextureLayouts import GIMITextureLayouts
|
|
19
|
+
from .constants.ModDownloadRepos import ModDownloadRepos, ModDownloadGameFolders
|
|
20
|
+
from .constants.ModLoaders import ModLoaders
|
|
21
|
+
|
|
22
|
+
# --- Data --------
|
|
23
|
+
from .data.ModDownloadData import ModDownloadData, ModDownloadAliases
|
|
24
|
+
from .constants.WWMIBuffers import WWMIBuffers, WWMIBlendRemapBuffers, WWMIShapeKeySlots, WWMIBlendRemapSize, WWMIBlendIndexLimit, WWMIDownloadNames, WWMIDownloadTextureSuffix
|
|
25
|
+
|
|
26
|
+
# --- Exceptions --------
|
|
27
|
+
from .exceptions.Error import Error
|
|
28
|
+
from .exceptions.BadAssetData import BadAssetData
|
|
29
|
+
from .exceptions.DownloadFailed import DownloadFailed
|
|
30
|
+
from .exceptions.UnknownDXGIFormat import UnknownDXGIFormat
|
|
31
|
+
|
|
32
|
+
# --- Model --------
|
|
33
|
+
from .model.IDModGenStats import IDModGenStats
|
|
34
|
+
from .model.ModDownload import ModDownload
|
|
35
|
+
from .model.files.DumpDataType import DumpDataType
|
|
36
|
+
from .model.files.DumpElement import DumpElement
|
|
37
|
+
from .model.files.FmtFile import FmtFile
|
|
38
|
+
from .model.files.IbDumpFile import IbDumpFile
|
|
39
|
+
from .model.files.VbDumpFile import VbDumpFile
|
|
40
|
+
from .model.gimi.GIMIComponent import GIMIComponent
|
|
41
|
+
from .model.gimi.GIMIIdentityMod import GIMIIdentityMod
|
|
42
|
+
from .model.gimi.GIMITextureSource import GIMITextureSource
|
|
43
|
+
from .model.wwmi.WWMIBlendRemap import WWMIBlendRemap
|
|
44
|
+
from .model.wwmi.WWMIComponent import WWMIComponent
|
|
45
|
+
from .model.wwmi.WWMIDrawRange import WWMIDrawRange
|
|
46
|
+
from .model.wwmi.WWMIMesh import WWMIMesh
|
|
47
|
+
from .model.wwmi.WWMIIdentityMod import WWMIIdentityMod
|
|
48
|
+
from .model.wwmi.WWMIShapeKeys import WWMIShapeKeys
|
|
49
|
+
|
|
50
|
+
# --- Tools --------
|
|
51
|
+
from .tools.DumpValueTools import DumpValueTools
|
|
52
|
+
from .tools.FormatTools import FormatTools
|
|
53
|
+
from .tools.ModDownloader import ModDownloader
|
|
54
|
+
from .tools.VersionTools import VersionTools
|
|
55
|
+
from .tools.gimi.GIMIDownloadFolderBuilder import GIMIDownloadFolderBuilder
|
|
56
|
+
from .tools.gimi.GIMIIniBuilder import GIMIIniBuilder
|
|
57
|
+
from .tools.gimi.GIMIIdentityModGenerator import GIMIIdentityModGenerator
|
|
58
|
+
from .tools.wwmi.WWMIDownloadFolderBuilder import WWMIDownloadFolderBuilder
|
|
59
|
+
from .tools.wwmi.WWMIIniBuilder import WWMIIniBuilder
|
|
60
|
+
from .tools.wwmi.WWMIIdentityModGenerator import WWMIIdentityModGenerator, WWMITexturePattern
|
|
61
|
+
|
|
62
|
+
# --- Service --------
|
|
63
|
+
from .IDModGenService import IDModGenService
|
|
64
|
+
|
|
65
|
+
##### EndLocalImports
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
__all__ = ["IDModGenService", "IDModGenStats",
|
|
69
|
+
"DumpDataKinds", "GIMIBuffers", "GIMISemanticBuffers", "GIMIFixedStrides", "GIMITextureLayouts",
|
|
70
|
+
"DumpDataType", "DumpElement", "IbDumpFile", "VbDumpFile", "GIMIComponent", "GIMIIdentityMod", "GIMITextureSource",
|
|
71
|
+
"DumpValueTools", "GIMIIniBuilder", "GIMIIdentityModGenerator", "GIMIDownloadFolderBuilder", "WWMIDownloadFolderBuilder",
|
|
72
|
+
"ModDownloadRepos", "ModDownloadGameFolders", "ModDownloadData", "ModDownloadAliases", "DownloadFailed", "ModDownload", "ModDownloader", "VersionTools",
|
|
73
|
+
"GIMIHashFileSuffix", "WWMIDownloadNames", "WWMIDownloadTextureSuffix", "WWMIDrawRange", "WWMIMesh",
|
|
74
|
+
"DXGIFormats", "DXGIFormatPrefix", "FileEncodings", "IniFileEncoding", "ReadEncodings", "ModLoaders",
|
|
75
|
+
"WWMIBuffers", "WWMIBlendRemapBuffers", "WWMIShapeKeySlots", "WWMIBlendRemapSize", "WWMIBlendIndexLimit",
|
|
76
|
+
"Error", "BadAssetData", "UnknownDXGIFormat",
|
|
77
|
+
"FmtFile", "WWMIBlendRemap", "WWMIComponent", "WWMIIdentityMod", "WWMIShapeKeys",
|
|
78
|
+
"FormatTools", "WWMIIniBuilder", "WWMIIdentityModGenerator", "WWMITexturePattern"]
|
AGIDMGen/__main__.py
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
##### Credits
|
|
2
|
+
|
|
3
|
+
# ===== Anime Game Identity Mod Generator (AGIDMGen) =====
|
|
4
|
+
# Authors: Albert Gold#2696
|
|
5
|
+
#
|
|
6
|
+
# A sub-project of Anime Game Remap (AG Remap)
|
|
7
|
+
# if you used it to make your mods pls give credit for "Albert Gold#2696"
|
|
8
|
+
|
|
9
|
+
##### EndCredits
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
##### ExtImports
|
|
13
|
+
import sys
|
|
14
|
+
##### EndExtImports
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
##### LocalImports
|
|
18
|
+
from .main import main
|
|
19
|
+
##### EndLocalImports
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
##### Script
|
|
23
|
+
sys.exit(main())
|
|
24
|
+
##### EndScript
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
##### Credits
|
|
2
|
+
|
|
3
|
+
# ===== Anime Game Identity Mod Generator (AGIDMGen) =====
|
|
4
|
+
# Authors: Albert Gold#2696
|
|
5
|
+
#
|
|
6
|
+
# A sub-project of Anime Game Remap (AG Remap)
|
|
7
|
+
# if you used it to make your mods pls give credit for "Albert Gold#2696"
|
|
8
|
+
|
|
9
|
+
##### EndCredits
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
##### ExtImports
|
|
13
|
+
from typing import Dict, Tuple
|
|
14
|
+
##### EndExtImports
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
##### Script
|
|
18
|
+
#: The prefix of the full name of a DXGI format
|
|
19
|
+
DXGIFormatPrefix = "DXGI_FORMAT_"
|
|
20
|
+
|
|
21
|
+
# The DXGI formats a buffer element may be declared with, and how each one is decoded: the numpy dtype
|
|
22
|
+
# of one channel and the number of channels.
|
|
23
|
+
#
|
|
24
|
+
# note: this is a dict and not an Enum on purpose -- several formats decode the same way
|
|
25
|
+
# (R8G8B8A8_UINT and R8G8B8A8_UNORM), and an Enum would make those aliases of one member
|
|
26
|
+
|
|
27
|
+
#: The DXGI formats a buffer element can be decoded from (without the ``DXGI_FORMAT_`` prefix), each with the numpy dtype of one channel and the number of channels
|
|
28
|
+
DXGIFormats: Dict[str, Tuple[str, int]] = {
|
|
29
|
+
"R32G32B32A32_FLOAT": ("<f4", 4), "R32G32B32_FLOAT": ("<f4", 3), "R32G32_FLOAT": ("<f4", 2), "R32_FLOAT": ("<f4", 1),
|
|
30
|
+
"R16G16B16A16_FLOAT": ("<f2", 4), "R16G16B16_FLOAT": ("<f2", 3), "R16G16_FLOAT": ("<f2", 2), "R16_FLOAT": ("<f2", 1),
|
|
31
|
+
"R8G8B8A8_UINT": ("u1", 4), "R8G8B8A8_UNORM": ("u1", 4), "R8G8B8A8_SNORM": ("i1", 4), "R8G8B8_SNORM": ("i1", 3), "R8_SNORM": ("i1", 1), "R8_UINT": ("u1", 1), "R8_UNORM": ("u1", 1),
|
|
32
|
+
"R16G16B16A16_UINT": ("<u2", 4), "R16G16B16A16_UNORM": ("<u2", 4), "R16G16_UNORM": ("<u2", 2), "R16_UINT": ("<u2", 1),
|
|
33
|
+
"R32G32B32A32_UINT": ("<u4", 4), "R32_UINT": ("<u4", 1),
|
|
34
|
+
}
|
|
35
|
+
##### EndScript
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
##### Credits
|
|
2
|
+
|
|
3
|
+
# ===== Anime Game Identity Mod Generator (AGIDMGen) =====
|
|
4
|
+
# Authors: Albert Gold#2696
|
|
5
|
+
#
|
|
6
|
+
# A sub-project of Anime Game Remap (AG Remap)
|
|
7
|
+
# if you used it to make your mods pls give credit for "Albert Gold#2696"
|
|
8
|
+
|
|
9
|
+
##### EndCredits
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
##### ExtImports
|
|
13
|
+
from enum import Enum
|
|
14
|
+
##### EndExtImports
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
##### Script
|
|
18
|
+
class DumpDataKinds(Enum):
|
|
19
|
+
"""
|
|
20
|
+
The kinds of value one channel of a buffer element can hold, as named by the suffix of its DXGI format
|
|
21
|
+
|
|
22
|
+
Attributes
|
|
23
|
+
----------
|
|
24
|
+
Float: :class:`str`
|
|
25
|
+
A floating point number (``FLOAT``)
|
|
26
|
+
|
|
27
|
+
SignedInt: :class:`str`
|
|
28
|
+
A signed integer (``SINT``)
|
|
29
|
+
|
|
30
|
+
UnsignedInt: :class:`str`
|
|
31
|
+
An unsigned integer (``UINT``)
|
|
32
|
+
|
|
33
|
+
Unorm: :class:`str`
|
|
34
|
+
An unsigned number from 0 to 1, stored as an unsigned integer scaled to its largest value (``UNORM``)
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
Float = "FLOAT"
|
|
38
|
+
SignedInt = "SINT"
|
|
39
|
+
UnsignedInt = "UINT"
|
|
40
|
+
Unorm = "UNORM"
|
|
41
|
+
##### EndScript
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
##### Credits
|
|
2
|
+
|
|
3
|
+
# ===== Anime Game Identity Mod Generator (AGIDMGen) =====
|
|
4
|
+
# Authors: Albert Gold#2696
|
|
5
|
+
#
|
|
6
|
+
# A sub-project of Anime Game Remap (AG Remap)
|
|
7
|
+
# if you used it to make your mods pls give credit for "Albert Gold#2696"
|
|
8
|
+
|
|
9
|
+
##### EndCredits
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
##### ExtImports
|
|
13
|
+
from enum import Enum
|
|
14
|
+
##### EndExtImports
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
##### Script
|
|
18
|
+
class FileEncodings(Enum):
|
|
19
|
+
"""
|
|
20
|
+
The text encodings used when reading and writing the files of a mod
|
|
21
|
+
|
|
22
|
+
Attributes
|
|
23
|
+
----------
|
|
24
|
+
UTF8: :class:`str`
|
|
25
|
+
The `utf-8` encoding
|
|
26
|
+
|
|
27
|
+
Latin1: :class:`str`
|
|
28
|
+
The `latin1` encoding
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
UTF8 = "utf-8"
|
|
32
|
+
Latin1 = "latin1"
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
#: The encoding a ``.ini`` file is written in
|
|
36
|
+
IniFileEncoding = FileEncodings.UTF8.value
|
|
37
|
+
#: The encodings tried, in order, when reading a text file
|
|
38
|
+
ReadEncodings = [IniFileEncoding, FileEncodings.Latin1.value]
|
|
39
|
+
##### EndScript
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
##### Credits
|
|
2
|
+
|
|
3
|
+
# ===== Anime Game Identity Mod Generator (AGIDMGen) =====
|
|
4
|
+
# Authors: Albert Gold#2696
|
|
5
|
+
#
|
|
6
|
+
# A sub-project of Anime Game Remap (AG Remap)
|
|
7
|
+
# if you used it to make your mods pls give credit for "Albert Gold#2696"
|
|
8
|
+
|
|
9
|
+
##### EndCredits
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
##### ExtImports
|
|
13
|
+
from enum import Enum
|
|
14
|
+
from typing import Dict
|
|
15
|
+
##### EndExtImports
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
##### Script
|
|
19
|
+
class GIMIBuffers(Enum):
|
|
20
|
+
"""
|
|
21
|
+
The vertex buffers of one component of a GIMI mod, in the order GIMI lays a vertex out. Each one is
|
|
22
|
+
written to ``<name><component><buffer>.buf``
|
|
23
|
+
|
|
24
|
+
Attributes
|
|
25
|
+
----------
|
|
26
|
+
Position: :class:`str`
|
|
27
|
+
The ``POSITION``, ``NORMAL`` and ``TANGENT`` of the vertices
|
|
28
|
+
|
|
29
|
+
Blend: :class:`str`
|
|
30
|
+
The ``BLENDWEIGHT(S)`` and ``BLENDINDICES`` of the vertices
|
|
31
|
+
|
|
32
|
+
Texcoord: :class:`str`
|
|
33
|
+
The ``COLOR`` and ``TEXCOORD`` (``TEXCOORD1``, ...) of the vertices
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
Position = "Position"
|
|
37
|
+
Blend = "Blend"
|
|
38
|
+
Texcoord = "Texcoord"
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
#: The buffer each element of a dumped vertex belongs to, by its semantic name
|
|
42
|
+
GIMISemanticBuffers: Dict[str, GIMIBuffers] = {
|
|
43
|
+
"POSITION": GIMIBuffers.Position, "NORMAL": GIMIBuffers.Position, "TANGENT": GIMIBuffers.Position,
|
|
44
|
+
"BLENDWEIGHT": GIMIBuffers.Blend, "BLENDWEIGHTS": GIMIBuffers.Blend, "BLENDINDICES": GIMIBuffers.Blend,
|
|
45
|
+
"COLOR": GIMIBuffers.Texcoord, "TEXCOORD": GIMIBuffers.Texcoord
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
#: The number of bytes per vertex GIMI fixes for a buffer. The Texcoord buffer's is not fixed: it is 20 with a second UV set and 12 without, and can differ between the components of one character
|
|
49
|
+
GIMIFixedStrides: Dict[GIMIBuffers, int] = {GIMIBuffers.Position: 40, GIMIBuffers.Blend: 32}
|
|
50
|
+
|
|
51
|
+
#: What the name of a download folder's copy of the asset folder's ``hash.json`` ends with: ``<prefix>Hash.json``
|
|
52
|
+
GIMIHashFileSuffix = "Hash.json"
|
|
53
|
+
##### EndScript
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
##### Credits
|
|
2
|
+
|
|
3
|
+
# ===== Anime Game Identity Mod Generator (AGIDMGen) =====
|
|
4
|
+
# Authors: Albert Gold#2696
|
|
5
|
+
#
|
|
6
|
+
# A sub-project of Anime Game Remap (AG Remap)
|
|
7
|
+
# if you used it to make your mods pls give credit for "Albert Gold#2696"
|
|
8
|
+
|
|
9
|
+
##### EndCredits
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
##### ExtImports
|
|
13
|
+
from enum import Enum
|
|
14
|
+
from typing import Tuple
|
|
15
|
+
##### EndExtImports
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
##### Script
|
|
19
|
+
class GIMITextureLayouts(Enum):
|
|
20
|
+
"""
|
|
21
|
+
The two layouts a GIMI mod binds an object's textures in, chosen by whether the object's shader reads a
|
|
22
|
+
normal map. Each value is the (register, texture kind) pairs of the layout, and the command list of
|
|
23
|
+
``ORFix`` that moves the textures to the registers the shader actually reads
|
|
24
|
+
|
|
25
|
+
Attributes
|
|
26
|
+
----------
|
|
27
|
+
NormalMap: Tuple[Tuple[Tuple[:class:`str`, :class:`str`], ...], :class:`str`]
|
|
28
|
+
``ps-t0`` normal map, ``ps-t1`` diffuse and ``ps-t2`` light map, fixed by ``ORFix``
|
|
29
|
+
|
|
30
|
+
Plain: Tuple[Tuple[Tuple[:class:`str`, :class:`str`], ...], :class:`str`]
|
|
31
|
+
``ps-t0`` diffuse and ``ps-t1`` light map, fixed by ``NNFix``
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
NormalMap = ((("ps-t0", "NormalMap"), ("ps-t1", "Diffuse"), ("ps-t2", "LightMap")), "CommandList\\global\\ORFix\\ORFix")
|
|
35
|
+
Plain = ((("ps-t0", "Diffuse"), ("ps-t1", "LightMap")), "CommandList\\global\\ORFix\\NNFix")
|
|
36
|
+
|
|
37
|
+
@property
|
|
38
|
+
def registers(self) -> Tuple[Tuple[str, str], ...]:
|
|
39
|
+
"""
|
|
40
|
+
The (register, texture kind) pairs of the layout
|
|
41
|
+
|
|
42
|
+
:getter: Retrieves the registers
|
|
43
|
+
:type: Tuple[Tuple[:class:`str`, :class:`str`], ...]
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
return self.value[0]
|
|
47
|
+
|
|
48
|
+
@property
|
|
49
|
+
def fixCommand(self) -> str:
|
|
50
|
+
"""
|
|
51
|
+
The command list that moves the layout's textures to the registers the shader reads
|
|
52
|
+
|
|
53
|
+
:getter: Retrieves the command list
|
|
54
|
+
:type: :class:`str`
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
return self.value[1]
|
|
58
|
+
##### EndScript
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
##### Credits
|
|
2
|
+
|
|
3
|
+
# ===== Anime Game Identity Mod Generator (AGIDMGen) =====
|
|
4
|
+
# Authors: Albert Gold#2696
|
|
5
|
+
#
|
|
6
|
+
# A sub-project of Anime Game Remap (AG Remap)
|
|
7
|
+
# if you used it to make your mods pls give credit for "Albert Gold#2696"
|
|
8
|
+
|
|
9
|
+
##### EndCredits
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
##### ExtImports
|
|
13
|
+
from enum import Enum
|
|
14
|
+
from typing import Dict
|
|
15
|
+
##### EndExtImports
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
##### LocalImports
|
|
19
|
+
from .ModLoaders import ModLoaders
|
|
20
|
+
##### EndLocalImports
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
##### Script
|
|
24
|
+
class ModDownloadRepos(Enum):
|
|
25
|
+
"""
|
|
26
|
+
The repositories that hold characters' download folders, in the order they are searched: a file Anime
|
|
27
|
+
Game Remap has is taken from Anime Game Remap, so it is never kept twice. Each value is the address of
|
|
28
|
+
the repository's ``Data/Mod Downloads`` folder
|
|
29
|
+
|
|
30
|
+
Attributes
|
|
31
|
+
----------
|
|
32
|
+
AGRemap: :class:`str`
|
|
33
|
+
`Anime Game Remap <https://github.com/nhok0169/Anime-Game-Remap>`_'s download folders
|
|
34
|
+
|
|
35
|
+
AGIDMGen: :class:`str`
|
|
36
|
+
This library's own download folders, for what Anime Game Remap does not have
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
AGRemap = "https://github.com/nhok0169/Anime-Game-Remap/raw/master/Data/Mod%20Downloads"
|
|
40
|
+
AGIDMGen = "https://github.com/Alex-Au1/Anime-Game-Identity-Mod-Generator/raw/main/Data/Mod%20Downloads"
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
#: The folder of each mod loader's game in ``Data/Mod Downloads``
|
|
44
|
+
ModDownloadGameFolders: Dict[ModLoaders, str] = {ModLoaders.GIMI: "GI", ModLoaders.WWMI: "WuWa"}
|
|
45
|
+
##### EndScript
|