sourcepp 2024.11.5.dev1__tar.gz
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.
- sourcepp-2024.11.5.dev1/.gitignore +9 -0
- sourcepp-2024.11.5.dev1/CMakeLists.txt +39 -0
- sourcepp-2024.11.5.dev1/PKG-INFO +345 -0
- sourcepp-2024.11.5.dev1/pyproject.toml +52 -0
- sourcepp-2024.11.5.dev1/src/gamepp.h +31 -0
- sourcepp-2024.11.5.dev1/src/sourcepp/__init__.py +5 -0
- sourcepp-2024.11.5.dev1/src/sourcepp.cpp +47 -0
- sourcepp-2024.11.5.dev1/src/sourcepp.h +84 -0
- sourcepp-2024.11.5.dev1/src/steampp.h +36 -0
- sourcepp-2024.11.5.dev1/src/vcryptpp.h +90 -0
- sourcepp-2024.11.5.dev1/src/vtfpp.h +436 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Load this to build the sourcepp Python package
|
|
2
|
+
|
|
3
|
+
cmake_minimum_required(VERSION 3.25 FATAL_ERROR)
|
|
4
|
+
set(CMAKE_OSX_ARCHITECTURES "arm64" CACHE INTERNAL "" FORCE)
|
|
5
|
+
project(sourcepp_python)
|
|
6
|
+
|
|
7
|
+
if (NOT SKBUILD)
|
|
8
|
+
message(WARNING "\
|
|
9
|
+
This CMake file is meant to be executed using 'scikit-build-core'.
|
|
10
|
+
Running it directly will almost certainly not produce the desired
|
|
11
|
+
result. If you are a user trying to install this package, use the
|
|
12
|
+
command below, which will install all necessary build dependencies,
|
|
13
|
+
compile the package in an isolated environment, and then install it.
|
|
14
|
+
=====================================================================
|
|
15
|
+
$ pip install .
|
|
16
|
+
=====================================================================
|
|
17
|
+
If you are a software developer, and this is your own package, then
|
|
18
|
+
it is usually much more efficient to install the build dependencies
|
|
19
|
+
in your environment once and use the following command that avoids
|
|
20
|
+
a costly creation of a new virtual environment at every compilation:
|
|
21
|
+
=====================================================================
|
|
22
|
+
$ pip install nanobind scikit-build-core[pyproject]
|
|
23
|
+
$ pip install --no-build-isolation -ve .
|
|
24
|
+
=====================================================================
|
|
25
|
+
You may optionally add -Ceditable.rebuild=true to auto-rebuild when
|
|
26
|
+
the package is imported. Otherwise, you need to rerun the above
|
|
27
|
+
after editing C++ files.")
|
|
28
|
+
endif()
|
|
29
|
+
|
|
30
|
+
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
|
31
|
+
|
|
32
|
+
# As weird as this looks, this is necessary for sdist wheel
|
|
33
|
+
include(FetchContent)
|
|
34
|
+
FetchContent_Declare(
|
|
35
|
+
sourcepp
|
|
36
|
+
GIT_REPOSITORY "https://github.com/craftablescience/sourcepp.git"
|
|
37
|
+
GIT_TAG "origin/main")
|
|
38
|
+
set(SOURCEPP_BUILD_PYTHON_WRAPPERS ON CACHE INTERNAL "" FORCE)
|
|
39
|
+
FetchContent_MakeAvailable(sourcepp)
|
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: sourcepp
|
|
3
|
+
Version: 2024.11.5.dev1
|
|
4
|
+
Summary: Several modern C++20 libraries for sanely parsing Valve formats.
|
|
5
|
+
Home-page: https://github.com/craftablescience/sourcepp
|
|
6
|
+
Author-Email: craftablescience <lauralewisdev@gmail.com>
|
|
7
|
+
Maintainer-Email: craftablescience <lauralewisdev@gmail.com>
|
|
8
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
16
|
+
Project-URL: Homepage, https://github.com/craftablescience/sourcepp
|
|
17
|
+
Project-URL: Repository, https://github.com/craftablescience/sourcepp
|
|
18
|
+
Project-URL: Issue tracker, https://github.com/craftablescience/sourcepp/issues
|
|
19
|
+
Project-URL: Funding, https://ko-fi.com/craftablescience
|
|
20
|
+
Requires-Python: >=3.9
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
|
|
23
|
+
<div>
|
|
24
|
+
<img align="left" width="101px" src="https://github.com/craftablescience/sourcepp/blob/main/branding/logo.png?raw=true" alt="The Source Pretty Parsers logo. A printer-esque device is scanning a page with hex codes and printing a picture of Cordon Freeman." />
|
|
25
|
+
<h1>Source Pretty Parsers</h1>
|
|
26
|
+
</div>
|
|
27
|
+
|
|
28
|
+

|
|
29
|
+

|
|
30
|
+

|
|
31
|
+

|
|
32
|
+
|
|
33
|
+
Several modern C++20 libraries for sanely parsing Valve formats, rolled into one big repository.
|
|
34
|
+
|
|
35
|
+
## Included Libraries
|
|
36
|
+
|
|
37
|
+
<table>
|
|
38
|
+
<tr>
|
|
39
|
+
<th>Name</th>
|
|
40
|
+
<th>Supports</th>
|
|
41
|
+
<th>Read</th>
|
|
42
|
+
<th>Write</th>
|
|
43
|
+
<th>Wrappers</th>
|
|
44
|
+
</tr>
|
|
45
|
+
<tr><!-- empty row to disable github striped bg color --></tr>
|
|
46
|
+
<tr>
|
|
47
|
+
<td rowspan="1"><code>bsppp</code><sup>*</sup></td>
|
|
48
|
+
<td><a href="https://developer.valvesoftware.com/wiki/BSP_(Source)">BSP</a> v17-27</td>
|
|
49
|
+
<td align="center">✅</td>
|
|
50
|
+
<td align="center">✅</td>
|
|
51
|
+
<td rowspan="1" align="center"></td>
|
|
52
|
+
</tr>
|
|
53
|
+
<tr><!-- empty row to disable github striped bg color --></tr>
|
|
54
|
+
<tr>
|
|
55
|
+
<td rowspan="1"><code>dmxpp</code><sup>*</sup></td>
|
|
56
|
+
<td><a href="https://developer.valvesoftware.com/wiki/DMX">DMX</a> Binary v1-5</td>
|
|
57
|
+
<td align="center">✅</td>
|
|
58
|
+
<td align="center">❌</td>
|
|
59
|
+
<td rowspan="1" align="center"></td>
|
|
60
|
+
</tr>
|
|
61
|
+
<tr><!-- empty row to disable github striped bg color --></tr>
|
|
62
|
+
<tr>
|
|
63
|
+
<td rowspan="3"><code>gamepp</code></td>
|
|
64
|
+
<td>Get Source engine instance window title/position/size</td>
|
|
65
|
+
<td align="center">✅</td>
|
|
66
|
+
<td align="center">❌</td>
|
|
67
|
+
<td rowspan="3" align="center">C<br>Python</td>
|
|
68
|
+
</tr>
|
|
69
|
+
<tr><!-- empty row to disable github striped bg color --></tr>
|
|
70
|
+
<tr>
|
|
71
|
+
<td>Run commands in a Source engine instance remotely</td>
|
|
72
|
+
<td align="center">❌</td>
|
|
73
|
+
<td align="center">✅</td>
|
|
74
|
+
</tr>
|
|
75
|
+
<tr><!-- empty row to disable github striped bg color --></tr>
|
|
76
|
+
<tr>
|
|
77
|
+
<td rowspan="1"><code>kvpp</code></td>
|
|
78
|
+
<td><a href="https://developer.valvesoftware.com/wiki/KeyValues">KeyValues</a> Text v1<sup>†</sup></td>
|
|
79
|
+
<td align="center">✅</td>
|
|
80
|
+
<td align="center">✅</td>
|
|
81
|
+
<td rowspan="1" align="center"></td>
|
|
82
|
+
</tr>
|
|
83
|
+
<tr><!-- empty row to disable github striped bg color --></tr>
|
|
84
|
+
<tr>
|
|
85
|
+
<td rowspan="5"><code>mdlpp</code><sup>*</sup></td>
|
|
86
|
+
<td><a href="https://developer.valvesoftware.com/wiki/MDL_(Source)">MDL</a> v44-49</td>
|
|
87
|
+
<td align="center">✅</td>
|
|
88
|
+
<td align="center">❌</td>
|
|
89
|
+
<td rowspan="5" align="center"></td>
|
|
90
|
+
</tr>
|
|
91
|
+
<tr><!-- empty row to disable github striped bg color --></tr>
|
|
92
|
+
<tr>
|
|
93
|
+
<td><a href="https://developer.valvesoftware.com/wiki/VTX">VTX</a> v7</td>
|
|
94
|
+
<td align="center">✅</td>
|
|
95
|
+
<td align="center">❌</td>
|
|
96
|
+
</tr>
|
|
97
|
+
<tr><!-- empty row to disable github striped bg color --></tr>
|
|
98
|
+
<tr>
|
|
99
|
+
<td><a href="https://developer.valvesoftware.com/wiki/VVD">VVD</a> v4</td>
|
|
100
|
+
<td align="center">✅</td>
|
|
101
|
+
<td align="center">❌</td>
|
|
102
|
+
</tr>
|
|
103
|
+
<tr><!-- empty row to disable github striped bg color --></tr>
|
|
104
|
+
<tr>
|
|
105
|
+
<td rowspan="3"><code>steampp</code></td>
|
|
106
|
+
<td>Find Steam install folder</td>
|
|
107
|
+
<td align="center">✅</td>
|
|
108
|
+
<td align="center">-</td>
|
|
109
|
+
<td rowspan="3" align="center">C<br>Python</td>
|
|
110
|
+
</tr>
|
|
111
|
+
<tr><!-- empty row to disable github striped bg color --></tr>
|
|
112
|
+
<tr>
|
|
113
|
+
<td>Find installed Steam games</td>
|
|
114
|
+
<td align="center">✅</td>
|
|
115
|
+
<td align="center">-</td>
|
|
116
|
+
</tr>
|
|
117
|
+
<tr><!-- empty row to disable github striped bg color --></tr>
|
|
118
|
+
<tr>
|
|
119
|
+
<td rowspan="3"><code>toolpp</code></td>
|
|
120
|
+
<td>
|
|
121
|
+
<a href="https://developer.valvesoftware.com/wiki/FGD">FGD (Source 1)</a>
|
|
122
|
+
<br> • <a href="https://ficool2.github.io/HammerPlusPlus-Website">Hammer++</a> modifications
|
|
123
|
+
<br> • <a href="https://stratasource.org">Strata Source</a> modifications
|
|
124
|
+
</td>
|
|
125
|
+
<td align="center">✅</td>
|
|
126
|
+
<td align="center">✅</td>
|
|
127
|
+
<td rowspan="3" align="center"></td>
|
|
128
|
+
</tr>
|
|
129
|
+
<tr><!-- empty row to disable github striped bg color --></tr>
|
|
130
|
+
<tr>
|
|
131
|
+
<td>
|
|
132
|
+
<a href="https://developer.valvesoftware.com/wiki/Command_Sequences">WC</a> (CmdSeq) v0.1-0.2
|
|
133
|
+
<br> • <a href="https://stratasource.org">Strata Source</a> modifications
|
|
134
|
+
</td>
|
|
135
|
+
<td align="center">✅</td>
|
|
136
|
+
<td align="center">✅</td>
|
|
137
|
+
</tr>
|
|
138
|
+
<tr><!-- empty row to disable github striped bg color --></tr>
|
|
139
|
+
<tr>
|
|
140
|
+
<td rowspan="3"><code>vcryptpp</code></td>
|
|
141
|
+
<td><a href="https://developer.valvesoftware.com/wiki/VICE">VICE</a> encrypted files</td>
|
|
142
|
+
<td align="center">✅</td>
|
|
143
|
+
<td align="center">✅</td>
|
|
144
|
+
<td rowspan="3" align="center">C<br>C#<br>Python</td>
|
|
145
|
+
</tr>
|
|
146
|
+
<tr><!-- empty row to disable github striped bg color --></tr>
|
|
147
|
+
<tr>
|
|
148
|
+
<td><a href="https://developer.valvesoftware.com/wiki/Vfont">VFONT</a> encrypted fonts</td>
|
|
149
|
+
<td align="center">✅</td>
|
|
150
|
+
<td align="center">❌</td>
|
|
151
|
+
</tr>
|
|
152
|
+
<tr><!-- empty row to disable github striped bg color --></tr>
|
|
153
|
+
<tr>
|
|
154
|
+
<td rowspan="25"><code>vpkpp</code></td>
|
|
155
|
+
<td><a href="https://developer.valvesoftware.com/wiki/Bonus_Maps">BMZ</a></td>
|
|
156
|
+
<td align="center">✅</td>
|
|
157
|
+
<td align="center">✅</td>
|
|
158
|
+
<td rowspan="25" align="center">C<br>C#</td>
|
|
159
|
+
</tr>
|
|
160
|
+
<tr><!-- empty row to disable github striped bg color --></tr>
|
|
161
|
+
<tr>
|
|
162
|
+
<td><a href="https://developer.valvesoftware.com/wiki/BSP_(Source)">BSP</a> v17-27</td>
|
|
163
|
+
<td align="center">✅</td>
|
|
164
|
+
<td align="center">✅</td>
|
|
165
|
+
</tr>
|
|
166
|
+
<tr><!-- empty row to disable github striped bg color --></tr>
|
|
167
|
+
<tr>
|
|
168
|
+
<td>FPX v10 (Tactical Intervention)</td>
|
|
169
|
+
<td align="center">✅</td>
|
|
170
|
+
<td align="center">✅</td>
|
|
171
|
+
</tr>
|
|
172
|
+
<tr><!-- empty row to disable github striped bg color --></tr>
|
|
173
|
+
<tr>
|
|
174
|
+
<td><a href="https://developer.valvesoftware.com/wiki/GCF_archive">GCF</a> v6</td>
|
|
175
|
+
<td align="center">✅</td>
|
|
176
|
+
<td align="center">❌</td>
|
|
177
|
+
</tr>
|
|
178
|
+
<tr><!-- empty row to disable github striped bg color --></tr>
|
|
179
|
+
<tr>
|
|
180
|
+
<td>GMA v1-3 (Garry's Mod)</td>
|
|
181
|
+
<td align="center">✅</td>
|
|
182
|
+
<td align="center">✅</td>
|
|
183
|
+
</tr>
|
|
184
|
+
<tr><!-- empty row to disable github striped bg color --></tr>
|
|
185
|
+
<tr>
|
|
186
|
+
<td><a href="https://quakewiki.org/wiki/.pak">PAK</a> (Quake, WON Half-Life)</td>
|
|
187
|
+
<td align="center">✅</td>
|
|
188
|
+
<td align="center">✅</td>
|
|
189
|
+
</tr>
|
|
190
|
+
<tr><!-- empty row to disable github striped bg color --></tr>
|
|
191
|
+
<tr>
|
|
192
|
+
<td><a href="https://docs.godotengine.org/en/stable/tutorials/export/exporting_pcks.html">PCK</a> v1-2 (Godot Engine)</td>
|
|
193
|
+
<td align="center">✅</td>
|
|
194
|
+
<td align="center">✅</td>
|
|
195
|
+
</tr>
|
|
196
|
+
<tr><!-- empty row to disable github striped bg color --></tr>
|
|
197
|
+
<tr>
|
|
198
|
+
<td><a href="https://doomwiki.org/wiki/PK3">PK3</a> (Quake III)</td>
|
|
199
|
+
<td align="center">✅</td>
|
|
200
|
+
<td align="center">✅</td>
|
|
201
|
+
</tr>
|
|
202
|
+
<tr><!-- empty row to disable github striped bg color --></tr>
|
|
203
|
+
<tr>
|
|
204
|
+
<td><a href="https://doomwiki.org/wiki/PK4">PK4</a> (Quake IV, Doom 3)</td>
|
|
205
|
+
<td align="center">✅</td>
|
|
206
|
+
<td align="center">✅</td>
|
|
207
|
+
</tr>
|
|
208
|
+
<tr><!-- empty row to disable github striped bg color --></tr>
|
|
209
|
+
<tr>
|
|
210
|
+
<td>
|
|
211
|
+
<a href="https://developer.valvesoftware.com/wiki/VPK">VPK</a> pre-v1, v1-2, v54
|
|
212
|
+
<br> • <a href="https://www.counter-strike.net/cs2">Counter-Strike: 2</a> modifications
|
|
213
|
+
<br> • <a href="https://clientmod.ru">Counter-Strike: Source ClientMod</a> modifications
|
|
214
|
+
</td>
|
|
215
|
+
<td align="center">✅</td>
|
|
216
|
+
<td align="center">✅</td>
|
|
217
|
+
</tr>
|
|
218
|
+
<tr><!-- empty row to disable github striped bg color --></tr>
|
|
219
|
+
<tr>
|
|
220
|
+
<td>VPK (Vampire: The Masquerade - Bloodlines)</td>
|
|
221
|
+
<td align="center">✅</td>
|
|
222
|
+
<td align="center">✅</td>
|
|
223
|
+
</tr>
|
|
224
|
+
<tr><!-- empty row to disable github striped bg color --></tr>
|
|
225
|
+
<tr>
|
|
226
|
+
<td>WAD v3</td>
|
|
227
|
+
<td align="center">✅</td>
|
|
228
|
+
<td align="center">✅</td>
|
|
229
|
+
</tr>
|
|
230
|
+
<tr><!-- empty row to disable github striped bg color --></tr>
|
|
231
|
+
<tr>
|
|
232
|
+
<td>ZIP</td>
|
|
233
|
+
<td align="center">✅</td>
|
|
234
|
+
<td align="center">✅</td>
|
|
235
|
+
</tr>
|
|
236
|
+
<tr><!-- empty row to disable github striped bg color --></tr>
|
|
237
|
+
<tr>
|
|
238
|
+
<td rowspan="23"><code>vtfpp</code></td>
|
|
239
|
+
<td><a href="https://en.wikipedia.org/wiki/BMP_file_format">BMP</a></td>
|
|
240
|
+
<td align="center">✅</td>
|
|
241
|
+
<td align="center">✅</td>
|
|
242
|
+
<td rowspan="23" align="center">Python</td>
|
|
243
|
+
</tr>
|
|
244
|
+
<tr><!-- empty row to disable github striped bg color --></tr>
|
|
245
|
+
<tr>
|
|
246
|
+
<td><a href="https://openexr.com">EXR</a> v1</td>
|
|
247
|
+
<td align="center">✅</td>
|
|
248
|
+
<td align="center">✅</td>
|
|
249
|
+
</tr>
|
|
250
|
+
<tr><!-- empty row to disable github striped bg color --></tr>
|
|
251
|
+
<tr>
|
|
252
|
+
<td><a href="https://en.wikipedia.org/wiki/GIF">GIF</a></td>
|
|
253
|
+
<td align="center">✅</td>
|
|
254
|
+
<td align="center">❌</td>
|
|
255
|
+
</tr>
|
|
256
|
+
<tr><!-- empty row to disable github striped bg color --></tr>
|
|
257
|
+
<tr>
|
|
258
|
+
<td><a href="https://en.wikipedia.org/wiki/RGBE_image_format">HDR</a></td>
|
|
259
|
+
<td align="center">✅</td>
|
|
260
|
+
<td align="center">✅</td>
|
|
261
|
+
</tr>
|
|
262
|
+
<tr><!-- empty row to disable github striped bg color --></tr>
|
|
263
|
+
<tr>
|
|
264
|
+
<td><a href="https://en.wikipedia.org/wiki/JPEG">JPEG</a></td>
|
|
265
|
+
<td align="center">✅</td>
|
|
266
|
+
<td align="center">✅</td>
|
|
267
|
+
</tr>
|
|
268
|
+
<tr><!-- empty row to disable github striped bg color --></tr>
|
|
269
|
+
<tr>
|
|
270
|
+
<td>PIC</td>
|
|
271
|
+
<td align="center">✅</td>
|
|
272
|
+
<td align="center">❌</td>
|
|
273
|
+
</tr>
|
|
274
|
+
<tr><!-- empty row to disable github striped bg color --></tr>
|
|
275
|
+
<tr>
|
|
276
|
+
<td><a href="https://en.wikipedia.org/wiki/PNG">PNG</a></td>
|
|
277
|
+
<td align="center">✅</td>
|
|
278
|
+
<td align="center">✅</td>
|
|
279
|
+
</tr>
|
|
280
|
+
<tr><!-- empty row to disable github striped bg color --></tr>
|
|
281
|
+
<tr>
|
|
282
|
+
<td><a href="https://netpbm.sourceforge.net/doc/pnm.html">PNM</a> (PGM, PPM)</td>
|
|
283
|
+
<td align="center">✅</td>
|
|
284
|
+
<td align="center">❌</td>
|
|
285
|
+
</tr>
|
|
286
|
+
<tr><!-- empty row to disable github striped bg color --></tr>
|
|
287
|
+
<tr>
|
|
288
|
+
<td><a href="https://developer.valvesoftware.com/wiki/PPL">PPL</a> v0</td>
|
|
289
|
+
<td align="center">✅</td>
|
|
290
|
+
<td align="center">✅</td>
|
|
291
|
+
</tr>
|
|
292
|
+
<tr><!-- empty row to disable github striped bg color --></tr>
|
|
293
|
+
<tr>
|
|
294
|
+
<td><a href="https://www.adobe.com/creativecloud/file-types/image/raster/psd-file.html">PSD</a></td>
|
|
295
|
+
<td align="center">✅</td>
|
|
296
|
+
<td align="center">❌</td>
|
|
297
|
+
</tr>
|
|
298
|
+
<tr><!-- empty row to disable github striped bg color --></tr>
|
|
299
|
+
<tr>
|
|
300
|
+
<td><a href="https://en.wikipedia.org/wiki/Truevision_TGA">TGA</a></td>
|
|
301
|
+
<td align="center">✅</td>
|
|
302
|
+
<td align="center">✅</td>
|
|
303
|
+
</tr>
|
|
304
|
+
<tr><!-- empty row to disable github striped bg color --></tr>
|
|
305
|
+
<tr>
|
|
306
|
+
<td>
|
|
307
|
+
<a href="https://developer.valvesoftware.com/wiki/VTF_(Valve_Texture_Format)">VTF</a> v7.0-7.6
|
|
308
|
+
<br> • <a href="https://stratasource.org">Strata Source</a> modifications
|
|
309
|
+
</td>
|
|
310
|
+
<td align="center">✅</td>
|
|
311
|
+
<td align="center">✅</td>
|
|
312
|
+
</tr>
|
|
313
|
+
</table>
|
|
314
|
+
|
|
315
|
+
(\*) These libraries are incomplete and still in development. Their interfaces are unstable and will likely change in the future.
|
|
316
|
+
Libraries not starred should be considered stable, and their existing interfaces will not change much if at all. Note that wrappers
|
|
317
|
+
only exist for stable libraries.
|
|
318
|
+
|
|
319
|
+
(†) Many text-based formats in Source are close to (if not identical to) KeyValues v1, such as [VMT](https://developer.valvesoftware.com/wiki/VMT) and [VMF](https://developer.valvesoftware.com/wiki/VMF_(Valve_Map_Format)).
|
|
320
|
+
|
|
321
|
+
## Wrappers
|
|
322
|
+
|
|
323
|
+
Wrappers for libraries considered complete exist for C, C#, and/or Python, depending on the library. The Python wrappers can be
|
|
324
|
+
found on PyPI in the `sourcepp` package.
|
|
325
|
+
|
|
326
|
+
## Special Thanks
|
|
327
|
+
|
|
328
|
+
- `steampp` is based on the [SteamAppPathProvider](https://github.com/Trico-Everfire/SteamAppPathProvider) library by [@Trico Everfire](https://github.com/Trico-Everfire) and [Momentum Mod](https://momentum-mod.org) contributors.
|
|
329
|
+
- `vpkpp`'s GCF parser was contributed by [@bt](https://github.com/caatge) and [@ymgve](https://github.com/ymgve).
|
|
330
|
+
- `vpkpp`'s WAD3 parser was contributed by [@ozxybox](https://github.com/ozxybox).
|
|
331
|
+
- `vtfpp`'s write support is based on work by [@Trico Everfire](https://github.com/Trico-Everfire).
|
|
332
|
+
|
|
333
|
+
## Gallery
|
|
334
|
+
|
|
335
|
+
A list of projects using the `sourcepp` parser set. If you'd like to see your project here, make a PR!
|
|
336
|
+
|
|
337
|
+
- [VPKEdit](https://github.com/craftablescience/VPKEdit): An open source MIT-licensed tool that can create, extract from,
|
|
338
|
+
preview the contents of and write to several pack file formats. A CLI application is bundled with the program which replicates
|
|
339
|
+
the functionality of Valve's `vpk.exe`.
|
|
340
|
+
- [GodotSource](https://github.com/craftablescience/godotsource): A work-in-progress set of bindings to connect the `sourcepp`
|
|
341
|
+
libraries to Godot. Allows GDScript to work with the libraries, and allows Godot to directly load Source engine assets from
|
|
342
|
+
a user project or from installed Source games.
|
|
343
|
+
- [Verifier](https://github.com/StrataSource/verifier): A small program that can build an index of a game's files, and validate
|
|
344
|
+
existing files based on that index. Think Steam's "Verify integrity of game files" option, but without actually overwriting any
|
|
345
|
+
files. `sourcepp` is used to parse Steam depot configs, as well as enable indexing the contents of VPKs.
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["scikit-build-core >=0.10.7", "nanobind >=1.3.2"]
|
|
3
|
+
build-backend = "scikit_build_core.build"
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
[project]
|
|
7
|
+
name = "sourcepp"
|
|
8
|
+
version = "2024.11.5dev1" # change __init__.py when this is updated
|
|
9
|
+
authors = [{ name = "craftablescience", email = "lauralewisdev@gmail.com" }]
|
|
10
|
+
maintainers = [{ name = "craftablescience", email = "lauralewisdev@gmail.com" }]
|
|
11
|
+
description = "Several modern C++20 libraries for sanely parsing Valve formats."
|
|
12
|
+
readme = "../../README.md"
|
|
13
|
+
requires-python = ">=3.9"
|
|
14
|
+
classifiers = [
|
|
15
|
+
"License :: OSI Approved :: MIT License",
|
|
16
|
+
"Intended Audience :: Developers",
|
|
17
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
18
|
+
"Programming Language :: Python :: 3.9",
|
|
19
|
+
"Programming Language :: Python :: 3.10",
|
|
20
|
+
"Programming Language :: Python :: 3.11",
|
|
21
|
+
"Programming Language :: Python :: 3.12",
|
|
22
|
+
"Programming Language :: Python :: 3.13",
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
[project.urls]
|
|
26
|
+
"homepage" = "https://github.com/craftablescience/sourcepp"
|
|
27
|
+
"repository" = "https://github.com/craftablescience/sourcepp"
|
|
28
|
+
"issue tracker" = "https://github.com/craftablescience/sourcepp/issues"
|
|
29
|
+
"funding" = "https://ko-fi.com/craftablescience"
|
|
30
|
+
|
|
31
|
+
[tool.scikit-build]
|
|
32
|
+
minimum-version = "build-system.requires"
|
|
33
|
+
build-dir = "build/{wheel_tag}"
|
|
34
|
+
build.targets = ["sourcepp_python_all"]
|
|
35
|
+
sdist.reproducible = true
|
|
36
|
+
wheel.py-api = "cp312"
|
|
37
|
+
wheel.license-files = ["../../LICENSE", "../../THIRDPARTY_LEGAL_NOTICES.txt"]
|
|
38
|
+
build.verbose = true
|
|
39
|
+
logging.level = "INFO"
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
[tool.cibuildwheel]
|
|
43
|
+
archs = ["auto64"]
|
|
44
|
+
build-verbosity = 1
|
|
45
|
+
#test-command = "pytest {project}/test"
|
|
46
|
+
#test-requires = "pytest"
|
|
47
|
+
|
|
48
|
+
[tool.cibuildwheel.macos]
|
|
49
|
+
archs = ["arm64"]
|
|
50
|
+
|
|
51
|
+
[tool.cibuildwheel.macos.environment]
|
|
52
|
+
MACOSX_DEPLOYMENT_TARGET = "14.7"
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <nanobind/nanobind.h>
|
|
4
|
+
#include <nanobind/stl/optional.h>
|
|
5
|
+
#include <nanobind/stl/string.h>
|
|
6
|
+
#include <nanobind/stl/string_view.h>
|
|
7
|
+
|
|
8
|
+
namespace py = nanobind;
|
|
9
|
+
|
|
10
|
+
#include <gamepp/gamepp.h>
|
|
11
|
+
|
|
12
|
+
namespace gamepp {
|
|
13
|
+
|
|
14
|
+
inline void register_python(py::module_& m) {
|
|
15
|
+
auto gamepp = m.def_submodule("gamepp");
|
|
16
|
+
using namespace gamepp;
|
|
17
|
+
|
|
18
|
+
py::class_<GameInstance>(gamepp, "GameInstance")
|
|
19
|
+
.def_static("find", &GameInstance::find, py::arg("window_name_override") = "")
|
|
20
|
+
.def_prop_ro("window_title", &GameInstance::getWindowTitle)
|
|
21
|
+
.def_prop_ro("window_pos", &GameInstance::getWindowPos)
|
|
22
|
+
.def_prop_ro("window_size", &GameInstance::getWindowSize)
|
|
23
|
+
.def("command", &GameInstance::command, py::arg("command"))
|
|
24
|
+
.def("input_begin", &GameInstance::inputBegin, py::arg("input"))
|
|
25
|
+
.def("input_end", &GameInstance::inputEnd, py::arg("input"))
|
|
26
|
+
.def("input_once", &GameInstance::inputOnce, py::arg("input"))
|
|
27
|
+
.def("input_hold", &GameInstance::inputHold, py::arg("input"), py::arg("sec"))
|
|
28
|
+
.def("wait", &GameInstance::wait, py::arg("sec"));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
} // namespace gamepp
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
from ._sourcepp_impl import __doc__, gamepp, sourcepp, steampp, vcryptpp, vtfpp
|
|
2
|
+
|
|
3
|
+
__author__ = "craftablescience"
|
|
4
|
+
__version__ = "2024.11.5dev1" # change pyproject.toml version when this is updated
|
|
5
|
+
__all__ = ['__author__', '__doc__', '__version__', 'gamepp', 'sourcepp', 'steampp', 'vcryptpp', 'vtfpp']
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
#include "sourcepp.h"
|
|
2
|
+
|
|
3
|
+
#ifdef GAMEPP
|
|
4
|
+
#include "gamepp.h"
|
|
5
|
+
#endif
|
|
6
|
+
|
|
7
|
+
#ifdef STEAMPP
|
|
8
|
+
#include "steampp.h"
|
|
9
|
+
#endif
|
|
10
|
+
|
|
11
|
+
#ifdef VCRYPTPP
|
|
12
|
+
#include "vcryptpp.h"
|
|
13
|
+
#endif
|
|
14
|
+
|
|
15
|
+
#ifdef VTFPP
|
|
16
|
+
#include "vtfpp.h"
|
|
17
|
+
#endif
|
|
18
|
+
|
|
19
|
+
NB_MODULE(_sourcepp_impl, m) {
|
|
20
|
+
m.doc() = "SourcePP: A Python wrapper around several modern C++20 libraries for sanely parsing Valve's formats.";
|
|
21
|
+
|
|
22
|
+
sourcepp::register_python(m);
|
|
23
|
+
|
|
24
|
+
#ifdef GAMEPP
|
|
25
|
+
gamepp::register_python(m);
|
|
26
|
+
#else
|
|
27
|
+
m.def_submodule("gamepp");
|
|
28
|
+
#endif
|
|
29
|
+
|
|
30
|
+
#ifdef STEAMPP
|
|
31
|
+
steampp::register_python(m);
|
|
32
|
+
#else
|
|
33
|
+
m.def_submodule("steampp");
|
|
34
|
+
#endif
|
|
35
|
+
|
|
36
|
+
#ifdef VCRYPTPP
|
|
37
|
+
vcryptpp::register_python(m);
|
|
38
|
+
#else
|
|
39
|
+
m.def_submodule("vcryptpp");
|
|
40
|
+
#endif
|
|
41
|
+
|
|
42
|
+
#ifdef VTFPP
|
|
43
|
+
vtfpp::register_python(m);
|
|
44
|
+
#else
|
|
45
|
+
m.def_submodule("vtfpp");
|
|
46
|
+
#endif
|
|
47
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <string_view>
|
|
4
|
+
|
|
5
|
+
#include <nanobind/nanobind.h>
|
|
6
|
+
#include <nanobind/operators.h>
|
|
7
|
+
|
|
8
|
+
namespace py = nanobind;
|
|
9
|
+
|
|
10
|
+
#include <sourcepp/Math.h>
|
|
11
|
+
|
|
12
|
+
namespace sourcepp {
|
|
13
|
+
|
|
14
|
+
inline void register_python(py::module_& m) {
|
|
15
|
+
auto sourcepp = m.def_submodule("sourcepp");
|
|
16
|
+
using namespace sourcepp;
|
|
17
|
+
|
|
18
|
+
{
|
|
19
|
+
auto math = sourcepp.def_submodule("math");
|
|
20
|
+
using namespace math;
|
|
21
|
+
|
|
22
|
+
const auto registerVecType = [&math]<typename V>(std::string_view name) {
|
|
23
|
+
py::class_<V>(math, name.data())
|
|
24
|
+
.def("__len__", &V::size)
|
|
25
|
+
.def("__setitem__", [](V& self, uint8_t index, typename V::value_type val) { self[index] = val; })
|
|
26
|
+
.def("__getitem__", [](V& self, uint8_t index) { return self[index]; })
|
|
27
|
+
.def_static("zero", &V::zero)
|
|
28
|
+
.def("is_zero", &V::isZero);
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
registerVecType.operator()<Vec2i8>("Vec2i8");
|
|
32
|
+
registerVecType.operator()<Vec2i16>("Vec2i16");
|
|
33
|
+
registerVecType.operator()<Vec2i32>("Vec2i32");
|
|
34
|
+
registerVecType.operator()<Vec2i64>("Vec2i64");
|
|
35
|
+
//registerVecType.operator()<Vec2i>("Vec2i");
|
|
36
|
+
|
|
37
|
+
registerVecType.operator()<Vec2ui8>("Vec2ui8");
|
|
38
|
+
registerVecType.operator()<Vec2ui16>("Vec2ui16");
|
|
39
|
+
registerVecType.operator()<Vec2ui32>("Vec2ui32");
|
|
40
|
+
registerVecType.operator()<Vec2ui64>("Vec2ui64");
|
|
41
|
+
//registerVecType.operator()<Vec2ui>("Vec2ui");
|
|
42
|
+
|
|
43
|
+
//registerVecType.operator()<Vec2f16>("Vec2f16");
|
|
44
|
+
registerVecType.operator()<Vec2f32>("Vec2f32");
|
|
45
|
+
registerVecType.operator()<Vec2f64>("Vec2f64");
|
|
46
|
+
//registerVecType.operator()<Vec2f>("Vec2f");
|
|
47
|
+
|
|
48
|
+
registerVecType.operator()<Vec3i8>("Vec3i8");
|
|
49
|
+
registerVecType.operator()<Vec3i16>("Vec3i16");
|
|
50
|
+
registerVecType.operator()<Vec3i32>("Vec3i32");
|
|
51
|
+
registerVecType.operator()<Vec3i64>("Vec3i64");
|
|
52
|
+
//registerVecType.operator()<Vec3i>("Vec3i");
|
|
53
|
+
|
|
54
|
+
registerVecType.operator()<Vec3ui8>("Vec3ui8");
|
|
55
|
+
registerVecType.operator()<Vec3ui16>("Vec3ui16");
|
|
56
|
+
registerVecType.operator()<Vec3ui32>("Vec3ui32");
|
|
57
|
+
registerVecType.operator()<Vec3ui64>("Vec3ui64");
|
|
58
|
+
//registerVecType.operator()<Vec3ui>("Vec3ui");
|
|
59
|
+
|
|
60
|
+
//registerVecType.operator()<Vec3f16>("Vec3f16");
|
|
61
|
+
registerVecType.operator()<Vec3f32>("Vec3f32");
|
|
62
|
+
registerVecType.operator()<Vec3f64>("Vec3f64");
|
|
63
|
+
//registerVecType.operator()<Vec3f>("Vec3f");
|
|
64
|
+
|
|
65
|
+
registerVecType.operator()<Vec4i8>("Vec4i8");
|
|
66
|
+
registerVecType.operator()<Vec4i16>("Vec4i16");
|
|
67
|
+
registerVecType.operator()<Vec4i32>("Vec4i32");
|
|
68
|
+
registerVecType.operator()<Vec4i64>("Vec4i64");
|
|
69
|
+
//registerVecType.operator()<Vec4i>("Vec4i");
|
|
70
|
+
|
|
71
|
+
registerVecType.operator()<Vec4ui8>("Vec4ui8");
|
|
72
|
+
registerVecType.operator()<Vec4ui16>("Vec4ui16");
|
|
73
|
+
registerVecType.operator()<Vec4ui32>("Vec4ui32");
|
|
74
|
+
registerVecType.operator()<Vec4ui64>("Vec4ui64");
|
|
75
|
+
//registerVecType.operator()<Vec4ui>("Vec4ui");
|
|
76
|
+
|
|
77
|
+
//registerVecType.operator()<Vec4f16>("Vec4f16");
|
|
78
|
+
registerVecType.operator()<Vec4f32>("Vec4f32");
|
|
79
|
+
registerVecType.operator()<Vec4f64>("Vec4f64");
|
|
80
|
+
//registerVecType.operator()<Vec4f>("Vec4f");
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
} // namespace sourcepp
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <nanobind/nanobind.h>
|
|
4
|
+
#include <nanobind/stl/string_view.h>
|
|
5
|
+
#include <nanobind/stl/string.h>
|
|
6
|
+
#include <nanobind/stl/vector.h>
|
|
7
|
+
|
|
8
|
+
namespace py = nanobind;
|
|
9
|
+
|
|
10
|
+
#include <steampp/steampp.h>
|
|
11
|
+
|
|
12
|
+
namespace steampp {
|
|
13
|
+
|
|
14
|
+
inline void register_python(py::module_& m) {
|
|
15
|
+
auto steampp = m.def_submodule("steampp");
|
|
16
|
+
using namespace steampp;
|
|
17
|
+
|
|
18
|
+
py::class_<Steam>(steampp, "Steam")
|
|
19
|
+
.def(py::init<>())
|
|
20
|
+
.def_prop_ro("install_dir", &Steam::getInstallDir)
|
|
21
|
+
.def_prop_ro("library_dirs", &Steam::getLibraryDirs)
|
|
22
|
+
.def_prop_ro("sourcemod_dir", &Steam::getSourceModDir)
|
|
23
|
+
.def_prop_ro("installed_apps", &Steam::getInstalledApps)
|
|
24
|
+
.def("is_app_installed", &Steam::isAppInstalled, py::arg("appID"))
|
|
25
|
+
.def("get_app_name", &Steam::getAppName, py::arg("appID"))
|
|
26
|
+
.def("get_app_install_dir", &Steam::getAppInstallDir, py::arg("appID"))
|
|
27
|
+
.def("get_app_icon_path", &Steam::getAppIconPath, py::arg("appID"))
|
|
28
|
+
.def("get_app_logo_path", &Steam::getAppLogoPath, py::arg("appID"))
|
|
29
|
+
.def("get_app_box_art_path", &Steam::getAppBoxArtPath, py::arg("appID"))
|
|
30
|
+
.def("get_app_store_art_path", &Steam::getAppStoreArtPath, py::arg("appID"))
|
|
31
|
+
.def("is_app_using_source_engine", &Steam::isAppUsingSourceEngine, py::arg("appID"))
|
|
32
|
+
.def("is_app_using_source_2_engine", &Steam::isAppUsingSource2Engine, py::arg("appID"))
|
|
33
|
+
.def_prop_ro("__bool__", &Steam::operator bool, py::is_operator());
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
} // namespace steampp
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <nanobind/nanobind.h>
|
|
4
|
+
#include <nanobind/stl/string_view.h>
|
|
5
|
+
|
|
6
|
+
namespace py = nanobind;
|
|
7
|
+
|
|
8
|
+
#include <vcryptpp/vcryptpp.h>
|
|
9
|
+
|
|
10
|
+
namespace vcryptpp {
|
|
11
|
+
|
|
12
|
+
inline void register_python(py::module_& m) {
|
|
13
|
+
auto vcryptpp = m.def_submodule("vcryptpp");
|
|
14
|
+
using namespace vcryptpp;
|
|
15
|
+
|
|
16
|
+
{
|
|
17
|
+
auto VFONT = vcryptpp.def_submodule("VFONT");
|
|
18
|
+
using namespace VFONT;
|
|
19
|
+
|
|
20
|
+
VFONT.attr("IDENTIFIER") = IDENTIFIER;
|
|
21
|
+
|
|
22
|
+
VFONT.attr("MAGIC") = MAGIC;
|
|
23
|
+
|
|
24
|
+
VFONT.def("decrypt_bytes", [](const py::bytes& data) {
|
|
25
|
+
const auto d = decrypt({reinterpret_cast<const std::byte*>(data.data()), data.size()});
|
|
26
|
+
return py::bytes{d.data(), d.size()};
|
|
27
|
+
}, py::arg("data"));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
{
|
|
31
|
+
auto VICE = vcryptpp.def_submodule("VICE");
|
|
32
|
+
using namespace VICE;
|
|
33
|
+
|
|
34
|
+
{
|
|
35
|
+
auto KnownCodes = VICE.def_submodule("KnownCodes");
|
|
36
|
+
using namespace KnownCodes;
|
|
37
|
+
|
|
38
|
+
KnownCodes.attr("DEFAULT") = DEFAULT;
|
|
39
|
+
KnownCodes.attr("CONTAGION_WEAPONS") = CONTAGION_WEAPONS;
|
|
40
|
+
KnownCodes.attr("CONTAGION_SCRIPTS") = CONTAGION_SCRIPTS;
|
|
41
|
+
KnownCodes.attr("COUNTER_STRIKE_SOURCE") = COUNTER_STRIKE_SOURCE;
|
|
42
|
+
KnownCodes.attr("COUNTER_STRIKE_GLOBAL_OFFENSIVE") = COUNTER_STRIKE_GLOBAL_OFFENSIVE;
|
|
43
|
+
KnownCodes.attr("COUNTER_STRIKE_2") = COUNTER_STRIKE_2;
|
|
44
|
+
KnownCodes.attr("COUNTER_STRIKE_PROMOD") = COUNTER_STRIKE_PROMOD;
|
|
45
|
+
KnownCodes.attr("DAY_OF_DEFEAT_SOURCE") = DAY_OF_DEFEAT_SOURCE;
|
|
46
|
+
KnownCodes.attr("DYSTOPIA_1_2") = DYSTOPIA_1_2;
|
|
47
|
+
KnownCodes.attr("DYSTOPIA_1_3") = DYSTOPIA_1_3;
|
|
48
|
+
KnownCodes.attr("GOLDEN_EYE_SOURCE") = GOLDEN_EYE_SOURCE;
|
|
49
|
+
KnownCodes.attr("HALF_LIFE_2_CTF") = HALF_LIFE_2_CTF;
|
|
50
|
+
KnownCodes.attr("HALF_LIFE_2_DM") = HALF_LIFE_2_DM;
|
|
51
|
+
KnownCodes.attr("INSURGENCY") = INSURGENCY;
|
|
52
|
+
KnownCodes.attr("LEFT_4_DEAD_2") = LEFT_4_DEAD_2;
|
|
53
|
+
KnownCodes.attr("NO_MORE_ROOM_IN_HELL") = NO_MORE_ROOM_IN_HELL;
|
|
54
|
+
KnownCodes.attr("NUCLEAR_DAWN") = NUCLEAR_DAWN;
|
|
55
|
+
KnownCodes.attr("TACTICAL_INTERVENTION") = TACTICAL_INTERVENTION;
|
|
56
|
+
KnownCodes.attr("TEAM_FORTRESS_2") = TEAM_FORTRESS_2;
|
|
57
|
+
KnownCodes.attr("TEAM_FORTRESS_2_ITEMS") = TEAM_FORTRESS_2_ITEMS;
|
|
58
|
+
KnownCodes.attr("THE_SHIP") = THE_SHIP;
|
|
59
|
+
KnownCodes.attr("ZOMBIE_PANIC_SOURCE") = ZOMBIE_PANIC_SOURCE;
|
|
60
|
+
|
|
61
|
+
KnownCodes.attr("EKV_GPU_DEFAULT") = EKV_GPU_DEFAULT;
|
|
62
|
+
KnownCodes.attr("EKV_GPU_ALIEN_SWARM") = EKV_GPU_ALIEN_SWARM;
|
|
63
|
+
KnownCodes.attr("EKV_GPU_LEFT_4_DEAD_1") = EKV_GPU_LEFT_4_DEAD_1;
|
|
64
|
+
KnownCodes.attr("EKV_GPU_LEFT_4_DEAD_2") = EKV_GPU_LEFT_4_DEAD_2;
|
|
65
|
+
KnownCodes.attr("EKV_GPU_PORTAL_2") = EKV_GPU_PORTAL_2;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
VICE.def("decrypt_bytes", [](const py::bytes& data, std::string_view code = KnownCodes::DEFAULT) {
|
|
69
|
+
const auto d = decrypt({reinterpret_cast<const std::byte*>(data.data()), data.size()}, code);
|
|
70
|
+
return py::bytes{d.data(), d.size()};
|
|
71
|
+
}, py::arg("data"), py::arg("code") = KnownCodes::DEFAULT);
|
|
72
|
+
|
|
73
|
+
VICE.def("decrypt_str", [](std::string_view data, std::string_view code = KnownCodes::DEFAULT) -> std::string {
|
|
74
|
+
const auto d = decrypt({reinterpret_cast<const std::byte*>(data.data()), data.size()}, code);
|
|
75
|
+
return {reinterpret_cast<const char*>(d.data()), d.size()};
|
|
76
|
+
}, py::arg("data"), py::arg("code") = KnownCodes::DEFAULT);
|
|
77
|
+
|
|
78
|
+
VICE.def("encrypt_bytes", [](const py::bytes& data, std::string_view code = KnownCodes::DEFAULT) {
|
|
79
|
+
const auto d = encrypt({reinterpret_cast<const std::byte*>(data.data()), data.size()}, code);
|
|
80
|
+
return py::bytes{d.data(), d.size()};
|
|
81
|
+
}, py::arg("data"), py::arg("code") = KnownCodes::DEFAULT);
|
|
82
|
+
|
|
83
|
+
VICE.def("encrypt_str", [](std::string_view data, std::string_view code = KnownCodes::DEFAULT) -> std::string {
|
|
84
|
+
const auto d = encrypt({reinterpret_cast<const std::byte*>(data.data()), data.size()}, code);
|
|
85
|
+
return {reinterpret_cast<const char*>(d.data()), d.size()};
|
|
86
|
+
}, py::arg("data"), py::arg("code") = KnownCodes::DEFAULT);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
} // namespace vcryptpp
|
|
@@ -0,0 +1,436 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <tuple>
|
|
4
|
+
|
|
5
|
+
#include <nanobind/nanobind.h>
|
|
6
|
+
#include <nanobind/stl/pair.h>
|
|
7
|
+
#include <nanobind/stl/string.h>
|
|
8
|
+
#include <nanobind/stl/string_view.h>
|
|
9
|
+
#include <nanobind/stl/tuple.h>
|
|
10
|
+
|
|
11
|
+
namespace py = nanobind;
|
|
12
|
+
|
|
13
|
+
#include <vtfpp/vtfpp.h>
|
|
14
|
+
|
|
15
|
+
namespace vtfpp {
|
|
16
|
+
|
|
17
|
+
void register_python(py::module_& m) {
|
|
18
|
+
using namespace vtfpp;
|
|
19
|
+
auto vtfpp = m.def_submodule("vtfpp");
|
|
20
|
+
|
|
21
|
+
py::enum_<ImageFormat>(vtfpp, "ImageFormat")
|
|
22
|
+
.value("RGBA8888", ImageFormat::RGBA8888)
|
|
23
|
+
.value("ABGR8888", ImageFormat::ABGR8888)
|
|
24
|
+
.value("RGB888", ImageFormat::RGB888)
|
|
25
|
+
.value("BGR888", ImageFormat::BGR888)
|
|
26
|
+
.value("RGB565", ImageFormat::RGB565)
|
|
27
|
+
.value("I8", ImageFormat::I8)
|
|
28
|
+
.value("IA88", ImageFormat::IA88)
|
|
29
|
+
.value("P8", ImageFormat::P8)
|
|
30
|
+
.value("A8", ImageFormat::A8)
|
|
31
|
+
.value("RGB888_BLUESCREEN", ImageFormat::RGB888_BLUESCREEN)
|
|
32
|
+
.value("BGR888_BLUESCREEN", ImageFormat::BGR888_BLUESCREEN)
|
|
33
|
+
.value("ARGB8888", ImageFormat::ARGB8888)
|
|
34
|
+
.value("BGRA8888", ImageFormat::BGRA8888)
|
|
35
|
+
.value("DXT1", ImageFormat::DXT1)
|
|
36
|
+
.value("DXT3", ImageFormat::DXT3)
|
|
37
|
+
.value("DXT5", ImageFormat::DXT5)
|
|
38
|
+
.value("BGRX8888", ImageFormat::BGRX8888)
|
|
39
|
+
.value("BGR565", ImageFormat::BGR565)
|
|
40
|
+
.value("BGRX5551", ImageFormat::BGRX5551)
|
|
41
|
+
.value("BGRA4444", ImageFormat::BGRA4444)
|
|
42
|
+
.value("DXT1_ONE_BIT_ALPHA", ImageFormat::DXT1_ONE_BIT_ALPHA)
|
|
43
|
+
.value("BGRA5551", ImageFormat::BGRA5551)
|
|
44
|
+
.value("UV88", ImageFormat::UV88)
|
|
45
|
+
.value("UVWQ8888", ImageFormat::UVWQ8888)
|
|
46
|
+
.value("RGBA16161616F", ImageFormat::RGBA16161616F)
|
|
47
|
+
.value("RGBA16161616", ImageFormat::RGBA16161616)
|
|
48
|
+
.value("UVLX8888", ImageFormat::UVLX8888)
|
|
49
|
+
.value("R32F", ImageFormat::R32F)
|
|
50
|
+
.value("RGB323232F", ImageFormat::RGB323232F)
|
|
51
|
+
.value("RGBA32323232F", ImageFormat::RGBA32323232F)
|
|
52
|
+
.value("RG1616F", ImageFormat::RG1616F)
|
|
53
|
+
.value("RG3232F", ImageFormat::RG3232F)
|
|
54
|
+
.value("RGBX8888", ImageFormat::RGBX8888)
|
|
55
|
+
.value("EMPTY", ImageFormat::EMPTY)
|
|
56
|
+
.value("ATI2N", ImageFormat::ATI2N)
|
|
57
|
+
.value("ATI1N", ImageFormat::ATI1N)
|
|
58
|
+
.value("RGBA1010102", ImageFormat::RGBA1010102)
|
|
59
|
+
.value("BGRA1010102", ImageFormat::BGRA1010102)
|
|
60
|
+
.value("R16F", ImageFormat::R16F)
|
|
61
|
+
.value("R8", ImageFormat::R8)
|
|
62
|
+
.value("BC7", ImageFormat::BC7)
|
|
63
|
+
.value("BC6H", ImageFormat::BC6H)
|
|
64
|
+
.export_values();
|
|
65
|
+
|
|
66
|
+
{
|
|
67
|
+
using namespace ImageFormatDetails;
|
|
68
|
+
auto ImageFormatDetails = vtfpp.def_submodule("ImageFormatDetails");
|
|
69
|
+
|
|
70
|
+
ImageFormatDetails.def("red", &red, py::arg("format"));
|
|
71
|
+
ImageFormatDetails.def("decompressedRed", &decompressedRed, py::arg("format"));
|
|
72
|
+
ImageFormatDetails.def("green", &green, py::arg("format"));
|
|
73
|
+
ImageFormatDetails.def("decompressedGreen", &decompressedGreen, py::arg("format"));
|
|
74
|
+
ImageFormatDetails.def("blue", &blue, py::arg("format"));
|
|
75
|
+
ImageFormatDetails.def("decompressedBlue", &decompressedBlue, py::arg("format"));
|
|
76
|
+
ImageFormatDetails.def("alpha", &alpha, py::arg("format"));
|
|
77
|
+
ImageFormatDetails.def("decompressedAlpha", &decompressedAlpha, py::arg("format"));
|
|
78
|
+
ImageFormatDetails.def("bpp", &bpp, py::arg("format"));
|
|
79
|
+
ImageFormatDetails.def("containerFormat", &containerFormat, py::arg("format"));
|
|
80
|
+
ImageFormatDetails.def("large", &large, py::arg("format"));
|
|
81
|
+
ImageFormatDetails.def("decimal", &decimal, py::arg("format"));
|
|
82
|
+
ImageFormatDetails.def("compressed", &compressed, py::arg("format"));
|
|
83
|
+
ImageFormatDetails.def("transparent", &transparent, py::arg("format"));
|
|
84
|
+
ImageFormatDetails.def("opaque", &opaque, py::arg("format"));
|
|
85
|
+
|
|
86
|
+
ImageFormatDetails.def("get_data_length", py::overload_cast<ImageFormat, uint16_t, uint16_t, uint16_t>(&getDataLength), py::arg("format"), py::arg("width"), py::arg("height"), py::arg("slice_count") = 1);
|
|
87
|
+
ImageFormatDetails.def("get_data_length_extended", py::overload_cast<ImageFormat, uint8_t, uint16_t, uint8_t, uint16_t, uint16_t, uint16_t>(&getDataLength), py::arg("format"), py::arg("mip_count"), py::arg("frame_count"), py::arg("face_count"), py::arg("width"), py::arg("height"), py::arg("slice_count"));
|
|
88
|
+
ImageFormatDetails.def("get_data_position", [](ImageFormat format, uint8_t mip, uint8_t mipCount, uint16_t frame, uint16_t frameCount, uint8_t face, uint8_t faceCount, uint16_t width, uint16_t height, uint16_t slice = 0, uint16_t sliceCount = 1) -> std::pair<uint32_t, uint32_t> {
|
|
89
|
+
uint32_t offset, length;
|
|
90
|
+
if (getDataPosition(offset, length, format, mip, mipCount, frame, frameCount, face, faceCount, width, height, slice, sliceCount)) {
|
|
91
|
+
return {offset, length};
|
|
92
|
+
}
|
|
93
|
+
return {0, 0};
|
|
94
|
+
}, py::arg("format"), py::arg("mip"), py::arg("mip_count"), py::arg("frame"), py::arg("frame_count"), py::arg("face"), py::arg("face_count"), py::arg("width"), py::arg("height"), py::arg("slice") = 0, py::arg("slice_count") = 1);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
{
|
|
98
|
+
using namespace ImageDimensions;
|
|
99
|
+
auto ImageDimensions = vtfpp.def_submodule("ImageDimensions");
|
|
100
|
+
|
|
101
|
+
ImageDimensions.def("get_mip_dim", &getMipDim, py::arg("mip"), py::arg("dim"));
|
|
102
|
+
ImageDimensions.def("get_recommended_mip_count_for_dims", &getRecommendedMipCountForDims, py::arg("format"), py::arg("width"), py::arg("height"));
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Skip ImagePixel, difficult to bind
|
|
106
|
+
|
|
107
|
+
{
|
|
108
|
+
using namespace ImageConversion;
|
|
109
|
+
auto ImageConversion = vtfpp.def_submodule("ImageConversion");
|
|
110
|
+
|
|
111
|
+
// todo(python): still need to bind the following:
|
|
112
|
+
ImageConversion.def("convert_image_data_to_format", [](const py::bytes& imageData, ImageFormat oldFormat, ImageFormat newFormat, uint16_t width, uint16_t height) {
|
|
113
|
+
const auto d = convertImageDataToFormat({reinterpret_cast<const std::byte*>(imageData.data()), imageData.size()}, oldFormat, newFormat, width, height);
|
|
114
|
+
return py::bytes{d.data(), d.size()};
|
|
115
|
+
}, py::arg("image_data"), py::arg("old_format"), py::arg("new_format"), py::arg("width"), py::arg("height"));
|
|
116
|
+
|
|
117
|
+
ImageConversion.def("convert_several_image_data_to_format", [](const py::bytes& imageData, ImageFormat oldFormat, ImageFormat newFormat, uint8_t mipCount, uint16_t frameCount, uint16_t faceCount, uint16_t width, uint16_t height, uint16_t sliceCount) {
|
|
118
|
+
const auto d = convertSeveralImageDataToFormat({reinterpret_cast<const std::byte*>(imageData.data()), imageData.size()}, oldFormat, newFormat, mipCount, frameCount, faceCount, width, height, sliceCount);
|
|
119
|
+
return py::bytes{d.data(), d.size()};
|
|
120
|
+
}, py::arg("image_data"), py::arg("old_format"), py::arg("new_format"), py::arg("mip_count"), py::arg("frame_count"), py::arg("face_count"), py::arg("width"), py::arg("height"), py::arg("slice_count"));
|
|
121
|
+
|
|
122
|
+
py::enum_<FileFormat>(ImageConversion, "FileFormat")
|
|
123
|
+
.value("DEFAULT", FileFormat::DEFAULT)
|
|
124
|
+
.value("PNG", FileFormat::PNG)
|
|
125
|
+
.value("JPEG", FileFormat::JPEG)
|
|
126
|
+
.value("BMP", FileFormat::BMP)
|
|
127
|
+
.value("TGA", FileFormat::TGA)
|
|
128
|
+
.value("HDR", FileFormat::HDR)
|
|
129
|
+
.export_values();
|
|
130
|
+
|
|
131
|
+
ImageConversion.def("get_default_file_format_for_image_format", &getDefaultFileFormatForImageFormat, py::arg("format"));
|
|
132
|
+
|
|
133
|
+
ImageConversion.def("convert_image_data_to_file", [](const py::bytes& imageData, ImageFormat format, uint16_t width, uint16_t height, FileFormat fileFormat = FileFormat::DEFAULT) {
|
|
134
|
+
const auto d = convertImageDataToFile({reinterpret_cast<const std::byte*>(imageData.data()), imageData.size()}, format, width, height, fileFormat);
|
|
135
|
+
return py::bytes{d.data(), d.size()};
|
|
136
|
+
}, py::arg("image_data"), py::arg("format"), py::arg("width"), py::arg("height"), py::arg("file_format") = FileFormat::DEFAULT);
|
|
137
|
+
|
|
138
|
+
ImageConversion.def("convert_file_to_image_data", [](const py::bytes& fileData) -> std::tuple<py::bytes, ImageFormat, int, int, int> {
|
|
139
|
+
ImageFormat format;
|
|
140
|
+
int width, height, frame;
|
|
141
|
+
const auto d = convertFileToImageData({reinterpret_cast<const std::byte*>(fileData.data()), fileData.size()}, format, width, height, frame);
|
|
142
|
+
return {py::bytes{d.data(), d.size()}, format, width, height, frame};
|
|
143
|
+
}, py::arg("file_data"));
|
|
144
|
+
|
|
145
|
+
py::enum_<ResizeEdge>(ImageConversion, "ResizeEdge")
|
|
146
|
+
.value("CLAMP", ResizeEdge::CLAMP)
|
|
147
|
+
.value("REFLECT", ResizeEdge::REFLECT)
|
|
148
|
+
.value("WRAP", ResizeEdge::WRAP)
|
|
149
|
+
.value("ZERO", ResizeEdge::ZERO)
|
|
150
|
+
.export_values();
|
|
151
|
+
|
|
152
|
+
py::enum_<ResizeFilter>(ImageConversion, "ResizeFilter")
|
|
153
|
+
.value("DEFAULT", ResizeFilter::DEFAULT)
|
|
154
|
+
.value("BOX", ResizeFilter::BOX)
|
|
155
|
+
.value("BILINEAR", ResizeFilter::BILINEAR)
|
|
156
|
+
.value("CUBIC_BSPLINE", ResizeFilter::CUBIC_BSPLINE)
|
|
157
|
+
.value("CATMULLROM", ResizeFilter::CATMULLROM)
|
|
158
|
+
.value("MITCHELL", ResizeFilter::MITCHELL)
|
|
159
|
+
.export_values();
|
|
160
|
+
|
|
161
|
+
py::enum_<ResizeMethod>(ImageConversion, "ResizeMethod")
|
|
162
|
+
.value("NONE", ResizeMethod::NONE)
|
|
163
|
+
.value("POWER_OF_TWO_BIGGER", ResizeMethod::POWER_OF_TWO_BIGGER)
|
|
164
|
+
.value("POWER_OF_TWO_SMALLER", ResizeMethod::POWER_OF_TWO_SMALLER)
|
|
165
|
+
.value("POWER_OF_TWO_NEAREST", ResizeMethod::POWER_OF_TWO_NEAREST)
|
|
166
|
+
.export_values();
|
|
167
|
+
|
|
168
|
+
ImageConversion.def("get_resized_dim", &getResizedDim, py::arg("n"), py::arg("resize_method"));
|
|
169
|
+
ImageConversion.def("get_resized_dims", [](uint16_t width, ResizeMethod widthResize, uint16_t height, ResizeMethod heightResize) -> std::pair<uint16_t, uint16_t> {
|
|
170
|
+
setResizedDims(width, widthResize, height, heightResize);
|
|
171
|
+
return {width, height};
|
|
172
|
+
}, py::arg("width"), py::arg("resize_width"), py::arg("height"), py::arg("resize_height"));
|
|
173
|
+
|
|
174
|
+
ImageConversion.def("resize_image_data", [](const py::bytes& imageData, ImageFormat format, uint16_t width, uint16_t newWidth, uint16_t height, uint16_t newHeight, bool srgb, ResizeFilter filter, ResizeEdge edge = ResizeEdge::CLAMP) {
|
|
175
|
+
const auto d = resizeImageData({reinterpret_cast<const std::byte*>(imageData.data()), imageData.size()}, format, width, newWidth, height, newHeight, srgb, filter, edge);
|
|
176
|
+
return py::bytes{d.data(), d.size()};
|
|
177
|
+
}, py::arg("image_data"), py::arg("format"), py::arg("width"), py::arg("new_width"), py::arg("height"), py::arg("new_height"), py::arg("srgb"), py::arg("filter"), py::arg("edge") = ResizeEdge::CLAMP);
|
|
178
|
+
|
|
179
|
+
ImageConversion.def("resize_image_data_strict", [](const py::bytes& imageData, ImageFormat format, uint16_t width, uint16_t newWidth, ResizeMethod widthResize, uint16_t height, uint16_t newHeight, ResizeMethod heightResize, bool srgb, ResizeFilter filter, ResizeEdge edge = ResizeEdge::CLAMP) -> std::tuple<py::bytes, int, int> {
|
|
180
|
+
uint16_t widthOut, heightOut;
|
|
181
|
+
const auto d = resizeImageDataStrict({reinterpret_cast<const std::byte*>(imageData.data()), imageData.size()}, format, width, newWidth, widthOut, widthResize, height, newHeight, heightOut, heightResize, srgb, filter, edge);
|
|
182
|
+
return {py::bytes{d.data(), d.size()}, widthOut, heightOut};
|
|
183
|
+
}, py::arg("image_data"), py::arg("format"), py::arg("width"), py::arg("new_width"), py::arg("width_resize"), py::arg("height"), py::arg("new_height"), py::arg("height_resize"), py::arg("srgb"), py::arg("filter"), py::arg("edge") = ResizeEdge::CLAMP);
|
|
184
|
+
|
|
185
|
+
// Skip extractChannelFromImageData, difficult to bind
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
py::class_<PPL::Image>(vtfpp, "PPLImage")
|
|
189
|
+
.def_ro("width", &PPL::Image::width)
|
|
190
|
+
.def_ro("height", &PPL::Image::height)
|
|
191
|
+
.def_prop_ro("data", [](const PPL::Image& self) {
|
|
192
|
+
return py::bytes{self.data.data(), self.data.size()};
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
py::class_<PPL>(vtfpp, "PPL")
|
|
196
|
+
.def(py::init<uint32_t, ImageFormat, uint32_t>(), py::arg("checksum"), py::arg("format") = ImageFormat::RGB888, py::arg("version") = 0)
|
|
197
|
+
.def("__init__", [](PPL* self, const py::bytes& pplData) {
|
|
198
|
+
return new(self) PPL{{reinterpret_cast<const std::byte*>(pplData.data()), pplData.size()}};
|
|
199
|
+
}, py::arg("ppl_data"))
|
|
200
|
+
.def(py::init<const std::string&>(), py::arg("path"))
|
|
201
|
+
.def("__bool__", &PPL::operator bool, py::is_operator())
|
|
202
|
+
.def_prop_rw("version", &PPL::getVersion, &PPL::setVersion)
|
|
203
|
+
.def_prop_rw("checksum", &PPL::getChecksum, &PPL::setChecksum)
|
|
204
|
+
.def_prop_rw("format", &PPL::getFormat, &PPL::setFormat)
|
|
205
|
+
.def("has_image_for_lod", &PPL::hasImageForLOD, py::arg("lod"))
|
|
206
|
+
.def_prop_ro("image_lods", &PPL::getImageLODs)
|
|
207
|
+
.def("get_image_raw", [](const PPL& self, uint32_t lod = 0) -> std::optional<PPL::Image> {
|
|
208
|
+
const auto* image = self.getImageRaw(lod);
|
|
209
|
+
if (!image) {
|
|
210
|
+
return std::nullopt;
|
|
211
|
+
}
|
|
212
|
+
return *image;
|
|
213
|
+
}, py::arg("lod"))
|
|
214
|
+
.def("get_image_as", &PPL::getImageAs, py::arg("new_format"), py::arg("lod"))
|
|
215
|
+
.def("get_image_as_rgb888", &PPL::getImageAsRGB888, py::arg("lod"))
|
|
216
|
+
.def("set_image", [](PPL& self, const py::bytes& imageData, ImageFormat format, uint32_t width, uint32_t height, uint32_t lod = 0) {
|
|
217
|
+
self.setImage({reinterpret_cast<const std::byte*>(imageData.data()), imageData.size()}, format, width, height, lod);
|
|
218
|
+
}, py::arg("imageData"), py::arg("format"), py::arg("width"), py::arg("height"), py::arg("lod") = 0)
|
|
219
|
+
.def("set_image_resized", [](PPL& self, const py::bytes& imageData, ImageFormat format, uint32_t width, uint32_t height, uint32_t resizedWidth, uint32_t resizedHeight, uint32_t lod = 0, ImageConversion::ResizeFilter filter = ImageConversion::ResizeFilter::BILINEAR) {
|
|
220
|
+
self.setImage({reinterpret_cast<const std::byte*>(imageData.data()), imageData.size()}, format, width, height, resizedWidth, resizedHeight, lod, filter);
|
|
221
|
+
}, py::arg("imageData"), py::arg("format"), py::arg("width"), py::arg("height"), py::arg("resized_width"), py::arg("resized_height"), py::arg("lod") = 0, py::arg("filter") = ImageConversion::ResizeFilter::BILINEAR)
|
|
222
|
+
.def("set_image_from_file", py::overload_cast<const std::string&, uint32_t>(&PPL::setImage), py::arg("image_path"), py::arg("lod") = 0)
|
|
223
|
+
.def("set_image_resized_from_file", py::overload_cast<const std::string&, uint32_t, uint32_t, uint32_t, ImageConversion::ResizeFilter>(&PPL::setImage), py::arg("image_path"), py::arg("resized_width"), py::arg("resized_height"), py::arg("lod") = 0, py::arg("filter") = ImageConversion::ResizeFilter::BILINEAR)
|
|
224
|
+
.def("save_image", [](const PPL& self, uint32_t lod = 0, ImageConversion::FileFormat fileFormat = ImageConversion::FileFormat::DEFAULT) {
|
|
225
|
+
const auto d = self.saveImageToFile(lod, fileFormat);
|
|
226
|
+
return py::bytes{d.data(), d.size()};
|
|
227
|
+
}, py::arg("lod") = 0, py::arg("file_format") = ImageConversion::FileFormat::DEFAULT)
|
|
228
|
+
.def("save_image_to_file", py::overload_cast<const std::string&, uint32_t, ImageConversion::FileFormat>(&PPL::saveImageToFile, py::const_), py::arg("image_path"), py::arg("lod") = 0, py::arg("file_format") = ImageConversion::FileFormat::DEFAULT)
|
|
229
|
+
.def("bake", [](PPL& self) {
|
|
230
|
+
const auto d = self.bake();
|
|
231
|
+
return py::bytes{d.data(), d.size()};
|
|
232
|
+
})
|
|
233
|
+
.def("bake_to_file", py::overload_cast<const std::string&>(&PPL::bake), py::arg("ppl_path"));
|
|
234
|
+
|
|
235
|
+
vtfpp.attr("VTF_SIGNATURE") = VTF_SIGNATURE;
|
|
236
|
+
|
|
237
|
+
py::enum_<CompressionMethod>(vtfpp, "CompressionMethod")
|
|
238
|
+
.value("DEFLATE", CompressionMethod::DEFLATE)
|
|
239
|
+
.value("ZSTD", CompressionMethod::ZSTD)
|
|
240
|
+
.export_values();
|
|
241
|
+
|
|
242
|
+
py::enum_<Resource::Type>(vtfpp, "ResourceType")
|
|
243
|
+
.value("UNKNOWN", Resource::TYPE_UNKNOWN)
|
|
244
|
+
.value("THUMBNAIL_DATA", Resource::TYPE_THUMBNAIL_DATA)
|
|
245
|
+
.value("IMAGE_DATA", Resource::TYPE_IMAGE_DATA)
|
|
246
|
+
.value("PARTICLE_SHEET_DATA", Resource::TYPE_PARTICLE_SHEET_DATA)
|
|
247
|
+
.value("CRC", Resource::TYPE_CRC)
|
|
248
|
+
.value("LOD_CONTROL_INFO", Resource::TYPE_LOD_CONTROL_INFO)
|
|
249
|
+
.value("EXTENDED_FLAGS", Resource::TYPE_EXTENDED_FLAGS)
|
|
250
|
+
.value("KEYVALUES_DATA", Resource::TYPE_KEYVALUES_DATA)
|
|
251
|
+
.value("AUX_COMPRESSION", Resource::TYPE_AUX_COMPRESSION)
|
|
252
|
+
.export_values();
|
|
253
|
+
|
|
254
|
+
py::enum_<Resource::Flags>(vtfpp, "ResourceFlags")
|
|
255
|
+
.value("NONE", Resource::FLAG_NONE)
|
|
256
|
+
.value("LOCAL_DATA", Resource::FLAG_LOCAL_DATA)
|
|
257
|
+
.export_values();
|
|
258
|
+
|
|
259
|
+
// Skip Resource, mostly useless outside C++
|
|
260
|
+
|
|
261
|
+
py::enum_<VTF::Flags>(vtfpp, "VTFFlags")
|
|
262
|
+
.value("NONE", VTF::FLAG_NONE)
|
|
263
|
+
.value("POINT_SAMPLE", VTF::FLAG_POINT_SAMPLE)
|
|
264
|
+
.value("TRILINEAR", VTF::FLAG_TRILINEAR)
|
|
265
|
+
.value("CLAMP_S", VTF::FLAG_CLAMP_S)
|
|
266
|
+
.value("CLAMP_T", VTF::FLAG_CLAMP_T)
|
|
267
|
+
.value("ANISOTROPIC", VTF::FLAG_ANISOTROPIC)
|
|
268
|
+
.value("HINT_DXT5", VTF::FLAG_HINT_DXT5)
|
|
269
|
+
.value("SRGB", VTF::FLAG_SRGB)
|
|
270
|
+
.value("NO_COMPRESS", VTF::FLAG_NO_COMPRESS)
|
|
271
|
+
.value("NORMAL", VTF::FLAG_NORMAL)
|
|
272
|
+
.value("NO_MIP", VTF::FLAG_NO_MIP)
|
|
273
|
+
.value("NO_LOD", VTF::FLAG_NO_LOD)
|
|
274
|
+
.value("MIN_MIP", VTF::FLAG_MIN_MIP)
|
|
275
|
+
.value("PROCEDURAL", VTF::FLAG_PROCEDURAL)
|
|
276
|
+
.value("ONE_BIT_ALPHA", VTF::FLAG_ONE_BIT_ALPHA)
|
|
277
|
+
.value("MULTI_BIT_ALPHA", VTF::FLAG_MULTI_BIT_ALPHA)
|
|
278
|
+
.value("ENVMAP", VTF::FLAG_ENVMAP)
|
|
279
|
+
.value("RENDERTARGET", VTF::FLAG_RENDERTARGET)
|
|
280
|
+
.value("DEPTH_RENDERTARGET", VTF::FLAG_DEPTH_RENDERTARGET)
|
|
281
|
+
.value("NO_DEBUG_OVERRIDE", VTF::FLAG_NO_DEBUG_OVERRIDE)
|
|
282
|
+
.value("SINGLE_COPY", VTF::FLAG_SINGLE_COPY)
|
|
283
|
+
.value("ONE_OVER_MIP_LEVEL_IN_ALPHA", VTF::FLAG_ONE_OVER_MIP_LEVEL_IN_ALPHA)
|
|
284
|
+
.value("PREMULTIPLY_COLOR_BY_ONE_OVER_MIP_LEVEL", VTF::FLAG_PREMULTIPLY_COLOR_BY_ONE_OVER_MIP_LEVEL)
|
|
285
|
+
.value("NORMAL_TO_DUDV", VTF::FLAG_NORMAL_TO_DUDV)
|
|
286
|
+
.value("ALPHA_TEST_MIP_GENERATION", VTF::FLAG_ALPHA_TEST_MIP_GENERATION)
|
|
287
|
+
.value("NO_DEPTH_BUFFER", VTF::FLAG_NO_DEPTH_BUFFER)
|
|
288
|
+
.value("NICE_FILTERED", VTF::FLAG_NICE_FILTERED)
|
|
289
|
+
.value("CLAMP_U", VTF::FLAG_CLAMP_U)
|
|
290
|
+
.value("VERTEX_TEXTURE", VTF::FLAG_VERTEX_TEXTURE)
|
|
291
|
+
.value("SSBUMP", VTF::FLAG_SSBUMP)
|
|
292
|
+
.value("UNFILTERABLE_OK", VTF::FLAG_UNFILTERABLE_OK)
|
|
293
|
+
.value("BORDER", VTF::FLAG_BORDER)
|
|
294
|
+
.value("SPECVAR_RED", VTF::FLAG_SPECVAR_RED)
|
|
295
|
+
.value("SPECVAR_ALPHA", VTF::FLAG_SPECVAR_ALPHA)
|
|
296
|
+
.export_values();
|
|
297
|
+
|
|
298
|
+
py::class_<VTF::CreationOptions>(vtfpp, "VTFCreationOptions")
|
|
299
|
+
.def(py::init<>())
|
|
300
|
+
.def_rw("major_version", &VTF::CreationOptions::majorVersion)
|
|
301
|
+
.def_rw("minor_version", &VTF::CreationOptions::minorVersion)
|
|
302
|
+
.def_rw("output_format", &VTF::CreationOptions::outputFormat)
|
|
303
|
+
.def_rw("width_resize_method", &VTF::CreationOptions::widthResizeMethod)
|
|
304
|
+
.def_rw("height_resize_method", &VTF::CreationOptions::heightResizeMethod)
|
|
305
|
+
.def_rw("filter", &VTF::CreationOptions::filter)
|
|
306
|
+
.def_rw("flags", &VTF::CreationOptions::flags)
|
|
307
|
+
.def_rw("initial_frame_count", &VTF::CreationOptions::initialFrameCount)
|
|
308
|
+
.def_rw("start_frame", &VTF::CreationOptions::startFrame)
|
|
309
|
+
.def_rw("is_cubemap", &VTF::CreationOptions::isCubeMap)
|
|
310
|
+
.def_rw("has_spheremap", &VTF::CreationOptions::hasSphereMap)
|
|
311
|
+
.def_rw("initial_slice_count", &VTF::CreationOptions::initialSliceCount)
|
|
312
|
+
.def_rw("create_mips", &VTF::CreationOptions::createMips)
|
|
313
|
+
.def_rw("create_thumbnail", &VTF::CreationOptions::createThumbnail)
|
|
314
|
+
.def_rw("create_reflectivity", &VTF::CreationOptions::createReflectivity)
|
|
315
|
+
.def_rw("compression_level", &VTF::CreationOptions::compressionLevel)
|
|
316
|
+
.def_rw("compression_method", &VTF::CreationOptions::compressionMethod)
|
|
317
|
+
.def_rw("bumpmap_scale", &VTF::CreationOptions::bumpMapScale);
|
|
318
|
+
|
|
319
|
+
py::class_<VTF>(vtfpp, "VTF")
|
|
320
|
+
.def_ro_static("FLAG_MASK_GENERATED", &VTF::FLAG_MASK_GENERATED)
|
|
321
|
+
.def_ro_static("FORMAT_UNCHANGED", &VTF::FORMAT_UNCHANGED)
|
|
322
|
+
.def_ro_static("FORMAT_DEFAULT", &VTF::FORMAT_DEFAULT)
|
|
323
|
+
.def_ro_static("MAX_RESOURCES", &VTF::MAX_RESOURCES)
|
|
324
|
+
.def(py::init<>())
|
|
325
|
+
.def("__init__", [](VTF* self, const py::bytes& vtfData, bool parseHeaderOnly = false) {
|
|
326
|
+
return new(self) VTF{std::span{reinterpret_cast<const std::byte*>(vtfData.data()), vtfData.size()}, parseHeaderOnly};
|
|
327
|
+
}, py::arg("vtf_data"), py::arg("parse_header_only") = false)
|
|
328
|
+
.def(py::init<const std::string&, bool>(), py::arg("vtf_path"), py::arg("parse_header_only") = false)
|
|
329
|
+
.def("__bool__", &VTF::operator bool, py::is_operator())
|
|
330
|
+
.def_static("create_and_bake", [](const py::bytes& imageData, ImageFormat format, uint16_t width, uint16_t height, const std::string& vtfPath, VTF::CreationOptions options) {
|
|
331
|
+
VTF::create({reinterpret_cast<const std::byte*>(imageData.data()), imageData.size()}, format, width, height, vtfPath, options);
|
|
332
|
+
}, py::arg("image_data"), py::arg("format"), py::arg("width"), py::arg("height"), py::arg("vtf_path"), py::arg("creation_options") = VTF::CreationOptions{})
|
|
333
|
+
.def_static("create_blank_and_bake", py::overload_cast<ImageFormat, uint16_t, uint16_t, const std::string&, VTF::CreationOptions>(&VTF::create), py::arg("format"), py::arg("width"), py::arg("height"), py::arg("vtf_path"), py::arg("creation_options") = VTF::CreationOptions{})
|
|
334
|
+
.def_static("create", [](const py::bytes& imageData, ImageFormat format, uint16_t width, uint16_t height, VTF::CreationOptions options) {
|
|
335
|
+
return VTF::create({reinterpret_cast<const std::byte*>(imageData.data()), imageData.size()}, format, width, height, options);
|
|
336
|
+
}, py::arg("image_data"), py::arg("format"), py::arg("width"), py::arg("height"), py::arg("creation_options") = VTF::CreationOptions{})
|
|
337
|
+
.def_static("create_blank", py::overload_cast<ImageFormat, uint16_t, uint16_t, VTF::CreationOptions>(&VTF::create), py::arg("format"), py::arg("width"), py::arg("height"), py::arg("creation_options") = VTF::CreationOptions{})
|
|
338
|
+
.def_static("create_from_file_and_bake", py::overload_cast<const std::string&, const std::string&, VTF::CreationOptions>(&VTF::create), py::arg("image_path"), py::arg("vtf_path"), py::arg("creation_options") = VTF::CreationOptions{})
|
|
339
|
+
.def_static("create_from_file", py::overload_cast<const std::string&, VTF::CreationOptions>(&VTF::create), py::arg("image_path"), py::arg("creation_options") = VTF::CreationOptions{})
|
|
340
|
+
.def_prop_rw("version_major", &VTF::getMajorVersion, &VTF::setMajorVersion)
|
|
341
|
+
.def_prop_rw("version_minor", &VTF::getMinorVersion, &VTF::setMinorVersion)
|
|
342
|
+
.def_prop_rw("image_width_resize_method", &VTF::getImageWidthResizeMethod, &VTF::setImageWidthResizeMethod)
|
|
343
|
+
.def_prop_rw("image_height_resize_method", &VTF::getImageHeightResizeMethod, &VTF::setImageHeightResizeMethod)
|
|
344
|
+
.def_prop_ro("width", &VTF::getWidth)
|
|
345
|
+
.def("width_for_mip", [](const VTF& self, uint8_t mip = 0) { return self.getWidth(mip); }, py::arg("mip") = 0)
|
|
346
|
+
.def_prop_ro("height", &VTF::getHeight)
|
|
347
|
+
.def("height_for_mip", [](const VTF& self, uint8_t mip = 0) { return self.getHeight(mip); }, py::arg("mip") = 0)
|
|
348
|
+
.def("set_size", &VTF::setSize, py::arg("width"), py::arg("height"), py::arg("filter"))
|
|
349
|
+
.def_prop_rw("flags", &VTF::getFlags, &VTF::setFlags)
|
|
350
|
+
.def("add_flags", &VTF::addFlags, py::arg("flags"))
|
|
351
|
+
.def("remove_flags", &VTF::removeFlags, py::arg("flags"))
|
|
352
|
+
.def_prop_ro("format", &VTF::getFormat)
|
|
353
|
+
.def("set_format", &VTF::setFormat, py::arg("new_format"), py::arg("filter") = ImageConversion::ResizeFilter::BILINEAR)
|
|
354
|
+
.def_prop_rw("mip_count", &VTF::getMipCount, &VTF::setMipCount)
|
|
355
|
+
.def("set_recommended_mip_count", &VTF::setRecommendedMipCount)
|
|
356
|
+
.def("compute_mips", &VTF::computeMips, py::arg("filter") = ImageConversion::ResizeFilter::BILINEAR)
|
|
357
|
+
.def_prop_rw("frame_count", &VTF::getFrameCount, &VTF::setFrameCount)
|
|
358
|
+
.def_prop_ro("face_count", &VTF::getFaceCount)
|
|
359
|
+
.def("set_face_count", &VTF::setFaceCount, py::arg("is_cubemap"), py::arg("has_spheremap") = false)
|
|
360
|
+
.def_prop_rw("slice_count", &VTF::getSliceCount, &VTF::setSliceCount)
|
|
361
|
+
.def("set_frame_face_and_slice_count", &VTF::setFrameFaceAndSliceCount, py::arg("new_frame_count"), py::arg("is_cubemap"), py::arg("has_spheremap") = false, py::arg("new_slice_count") = 1)
|
|
362
|
+
.def_prop_rw("start_frame", &VTF::getStartFrame, &VTF::setStartFrame)
|
|
363
|
+
.def_prop_rw("reflectivity", &VTF::getReflectivity, &VTF::setReflectivity)
|
|
364
|
+
.def("compute_reflectivity", &VTF::computeReflectivity)
|
|
365
|
+
.def_prop_rw("bumpmap_scale", &VTF::getBumpMapScale, &VTF::setBumpMapScale)
|
|
366
|
+
.def_prop_ro("thumbnail_format", &VTF::getThumbnailFormat)
|
|
367
|
+
.def_prop_ro("thumbnail_width", &VTF::getThumbnailWidth)
|
|
368
|
+
.def_prop_ro("thumbnail_height", &VTF::getThumbnailHeight)
|
|
369
|
+
// Skip getResources
|
|
370
|
+
// Skip getResource
|
|
371
|
+
.def("set_particle_sheet_resource", [](VTF& self, const py::bytes& value) { return self.setParticleSheetResource({reinterpret_cast<const std::byte*>(value.data()), value.size()}); }, py::arg("value"))
|
|
372
|
+
.def("remove_particle_sheet_resource", &VTF::removeParticleSheetResource)
|
|
373
|
+
.def("set_crc_resource", &VTF::setCRCResource, py::arg("value"))
|
|
374
|
+
.def("remove_crc_resource", &VTF::removeCRCResource)
|
|
375
|
+
.def("set_lod_resource", &VTF::setLODResource, py::arg("u"), py::arg("v"))
|
|
376
|
+
.def("remove_lod_resource", &VTF::removeLODResource)
|
|
377
|
+
.def("set_extended_flags_resource", &VTF::setExtendedFlagsResource, py::arg("value"))
|
|
378
|
+
.def("remove_extended_flags_resource", &VTF::removeExtendedFlagsResource)
|
|
379
|
+
.def("set_keyvalues_data_resource", &VTF::setKeyValuesDataResource, py::arg("value"))
|
|
380
|
+
.def("remove_keyvalues_data_resource", &VTF::removeKeyValuesDataResource)
|
|
381
|
+
.def_prop_rw("compression_level", &VTF::getCompressionLevel, &VTF::setCompressionLevel)
|
|
382
|
+
.def_prop_rw("compression_method", &VTF::getCompressionMethod, &VTF::setCompressionMethod)
|
|
383
|
+
.def("has_image_data", &VTF::hasImageData)
|
|
384
|
+
.def("image_data_is_srgb", &VTF::imageDataIsSRGB)
|
|
385
|
+
.def("get_image_data_raw", [](const VTF& self, uint8_t mip = 0, uint16_t frame = 0, uint8_t face = 0, uint16_t slice = 0) {
|
|
386
|
+
const auto d = self.getImageDataRaw(mip, frame, face, slice);
|
|
387
|
+
return py::bytes{d.data(), d.size()};
|
|
388
|
+
}, py::arg("mip") = 0, py::arg("frame") = 0, py::arg("face") = 0, py::arg("slice") = 0)
|
|
389
|
+
.def("get_image_data_as", [](const VTF& self, ImageFormat newFormat, uint8_t mip = 0, uint16_t frame = 0, uint8_t face = 0, uint16_t slice = 0) {
|
|
390
|
+
const auto d = self.getImageDataAs(newFormat, mip, frame, face, slice);
|
|
391
|
+
return py::bytes{d.data(), d.size()};
|
|
392
|
+
}, py::arg("new_format"), py::arg("mip") = 0, py::arg("frame") = 0, py::arg("face") = 0, py::arg("slice") = 0)
|
|
393
|
+
.def("get_image_data_as_rgba8888", [](const VTF& self, uint8_t mip = 0, uint16_t frame = 0, uint8_t face = 0, uint16_t slice = 0) {
|
|
394
|
+
const auto d = self.getImageDataAsRGBA8888(mip, frame, face, slice);
|
|
395
|
+
return py::bytes{d.data(), d.size()};
|
|
396
|
+
}, py::arg("mip") = 0, py::arg("frame") = 0, py::arg("face") = 0, py::arg("slice") = 0)
|
|
397
|
+
.def("set_image", [](VTF& self, const py::bytes& imageData, ImageFormat format, uint16_t width, uint16_t height, ImageConversion::ResizeFilter filter = ImageConversion::ResizeFilter::BILINEAR, uint8_t mip = 0, uint16_t frame = 0, uint8_t face = 0, uint16_t slice = 0) {
|
|
398
|
+
return self.setImage({reinterpret_cast<const std::byte*>(imageData.data()), imageData.size()}, format, width, height, filter, mip, frame, face, slice);
|
|
399
|
+
}, py::arg("image_data"), py::arg("format"), py::arg("width"), py::arg("height"), py::arg("filter"), py::arg("mip") = 0, py::arg("frame") = 0, py::arg("face") = 0, py::arg("slice") = 0)
|
|
400
|
+
.def("set_image_from_file", py::overload_cast<const std::string&, ImageConversion::ResizeFilter, uint8_t, uint16_t, uint8_t, uint16_t>(&VTF::setImage), py::arg("image_path"), py::arg("filter") = ImageConversion::ResizeFilter::BILINEAR, py::arg("mip") = 0, py::arg("frame") = 0, py::arg("face") = 0, py::arg("slice") = 0)
|
|
401
|
+
.def("save_image", [](const VTF& self, uint8_t mip = 0, uint16_t frame = 0, uint8_t face = 0, uint16_t slice = 0, ImageConversion::FileFormat fileFormat = ImageConversion::FileFormat::DEFAULT) {
|
|
402
|
+
const auto d = self.saveImageToFile(mip, frame, face, slice, fileFormat);
|
|
403
|
+
return py::bytes{d.data(), d.size()};
|
|
404
|
+
}, py::arg("mip") = 0, py::arg("frame") = 0, py::arg("face") = 0, py::arg("slice") = 0, py::arg("file_format") = ImageConversion::FileFormat::DEFAULT)
|
|
405
|
+
.def("save_image_to_file", py::overload_cast<const std::string&, uint8_t, uint16_t, uint8_t, uint16_t, ImageConversion::FileFormat>(&VTF::saveImageToFile, py::const_), py::arg("image_path"), py::arg("mip") = 0, py::arg("frame") = 0, py::arg("face") = 0, py::arg("slice") = 0, py::arg("file_format") = ImageConversion::FileFormat::DEFAULT)
|
|
406
|
+
.def("has_thumbnail_data", &VTF::hasThumbnailData)
|
|
407
|
+
.def("get_thumbnail_data_raw", [](const VTF& self) {
|
|
408
|
+
const auto d = self.getThumbnailDataRaw();
|
|
409
|
+
return py::bytes{d.data(), d.size()};
|
|
410
|
+
})
|
|
411
|
+
.def("get_thumbnail_data_as", [](const VTF& self, ImageFormat newFormat) {
|
|
412
|
+
const auto d = self.getThumbnailDataAs(newFormat);
|
|
413
|
+
return py::bytes{d.data(), d.size()};
|
|
414
|
+
}, py::arg("new_format"))
|
|
415
|
+
.def("get_thumbnail_data_as_rgba8888", [](const VTF& self) {
|
|
416
|
+
const auto d = self.getThumbnailDataAsRGBA8888();
|
|
417
|
+
return py::bytes{d.data(), d.size()};
|
|
418
|
+
})
|
|
419
|
+
.def("set_thumbnail", [](VTF& self, const py::bytes& imageData, ImageFormat format, uint16_t width, uint16_t height) {
|
|
420
|
+
return self.setThumbnail({reinterpret_cast<const std::byte*>(imageData.data()), imageData.size()}, format, width, height);
|
|
421
|
+
}, py::arg("image_data"), py::arg("format"), py::arg("width"), py::arg("height"))
|
|
422
|
+
.def("compute_thumbnail", &VTF::computeThumbnail, py::arg("filter") = ImageConversion::ResizeFilter::BILINEAR)
|
|
423
|
+
.def("remove_thumbnail", &VTF::removeThumbnail)
|
|
424
|
+
.def("save_thumbnail", [](const VTF& self, ImageConversion::FileFormat fileFormat = ImageConversion::FileFormat::DEFAULT) {
|
|
425
|
+
const auto d = self.saveThumbnailToFile(fileFormat);
|
|
426
|
+
return py::bytes{d.data(), d.size()};
|
|
427
|
+
}, py::arg("file_format") = ImageConversion::FileFormat::DEFAULT)
|
|
428
|
+
.def("save_thumbnail_to_file", py::overload_cast<const std::string&, ImageConversion::FileFormat>(&VTF::saveThumbnailToFile, py::const_), py::arg("image_path"), py::arg("file_format") = ImageConversion::FileFormat::DEFAULT)
|
|
429
|
+
.def("bake", [](const VTF& self) {
|
|
430
|
+
const auto d = self.bake();
|
|
431
|
+
return py::bytes{d.data(), d.size()};
|
|
432
|
+
})
|
|
433
|
+
.def("bake_to_file", py::overload_cast<const std::string&>(&VTF::bake, py::const_), py::arg("vtf_path"));
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
} // namespace vtfpp
|