sourcepp 2025.1.26.dev1__tar.gz → 2025.2.12.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.
@@ -30,7 +30,7 @@ endif()
30
30
  set(CMAKE_POSITION_INDEPENDENT_CODE ON)
31
31
 
32
32
  set(SOURCEPP_BUILD_PYTHON_WRAPPERS ON CACHE INTERNAL "" FORCE)
33
- set(SOURCEPP_PYTHON_VERSION "2025.01.26dev1")
33
+ set(SOURCEPP_VERSION "2025.2.12dev1")
34
34
 
35
35
  # As weird as this looks, this is necessary for sdist wheel
36
36
  set(SOURCEPP_PYTHON_IS_SUBDIR OFF)
@@ -41,6 +41,6 @@ else()
41
41
  FetchContent_Declare(
42
42
  sourcepp
43
43
  GIT_REPOSITORY "https://github.com/craftablescience/sourcepp.git"
44
- GIT_TAG "353aee7fa8f9760938a2ed3b92b7ee2d41386f77")
44
+ GIT_TAG "109a8cd7348af99447f9675c340df66cae2bf1b5")
45
45
  FetchContent_MakeAvailable(sourcepp)
46
46
  endif()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sourcepp
3
- Version: 2025.1.26.dev1
3
+ Version: 2025.2.12.dev1
4
4
  Summary: Several modern C++20 libraries for sanely parsing Valve formats.
5
5
  Home-page: https://github.com/craftablescience/sourcepp
6
6
  Author-Email: craftablescience <lauralewisdev@gmail.com>
@@ -46,10 +46,15 @@ Several modern C++20 libraries for sanely parsing Valve formats, rolled into one
46
46
  <tr><!-- empty row to disable github striped bg color --></tr>
47
47
  <tr>
48
48
  <td rowspan="1"><code>bsppp</code><sup>*</sup></td>
49
- <td><a href="https://developer.valvesoftware.com/wiki/BSP_(Source)">BSP</a> v17-27</td>
49
+ <td>
50
+ <a href="https://developer.valvesoftware.com/wiki/BSP_(Source)">BSP</a> v17-27
51
+ <br> &bull; Console modifications
52
+ <br> &bull; Left 4 Dead 2 modifications
53
+ <br> &bull; <a href="https://stratasource.org">Strata Source</a> modifications
54
+ </td>
50
55
  <td align="center">✅</td>
51
56
  <td align="center">✅</td>
52
- <td rowspan="1" align="center"></td>
57
+ <td rowspan="1" align="center">Python</td>
53
58
  </tr>
54
59
  <tr><!-- empty row to disable github striped bg color --></tr>
55
60
  <tr>
@@ -62,7 +67,7 @@ Several modern C++20 libraries for sanely parsing Valve formats, rolled into one
62
67
  <tr><!-- empty row to disable github striped bg color --></tr>
63
68
  <tr>
64
69
  <td rowspan="1"><code>fspp</code><sup>*</sup></td>
65
- <td>(WIP) Source 1 filesystem accessor</td>
70
+ <td>Source 1 filesystem accessor</td>
66
71
  <td align="center">✅</td>
67
72
  <td align="center">✅</td>
68
73
  <td rowspan="1" align="center"></td>
@@ -110,6 +115,20 @@ Several modern C++20 libraries for sanely parsing Valve formats, rolled into one
110
115
  <td align="center">❌</td>
111
116
  </tr>
112
117
  <tr><!-- empty row to disable github striped bg color --></tr>
118
+ <tr>
119
+ <td rowspan="3"><code>sndpp</code><sup>*</sup></td>
120
+ <td>WAV</td>
121
+ <td align="center">✅</td>
122
+ <td align="center">❌</td>
123
+ <td rowspan="3" align="center"></td>
124
+ </tr>
125
+ <tr><!-- empty row to disable github striped bg color --></tr>
126
+ <tr>
127
+ <td>XWV v4</td>
128
+ <td align="center">✅</td>
129
+ <td align="center">❌</td>
130
+ </tr>
131
+ <tr><!-- empty row to disable github striped bg color --></tr>
113
132
  <tr>
114
133
  <td rowspan="3"><code>steampp</code></td>
115
134
  <td>Find Steam install folder</td>
@@ -385,9 +404,11 @@ found on PyPI in the [sourcepp](https://pypi.org/project/sourcepp) package.
385
404
 
386
405
  A list of projects using the `sourcepp` parser set. If you'd like to see your project here, make a PR!
387
406
 
388
- - [VPKEdit](https://github.com/craftablescience/VPKEdit): An open source MIT-licensed tool that can create, extract from,
389
- preview the contents of and write to several pack file formats. A CLI application is bundled with the program which replicates
407
+ - [VPKEdit](https://github.com/craftablescience/VPKEdit): An open source MIT-licensed GUI tool that can create, extract from,
408
+ preview the contents of and write to several pack file formats. A CLI tool is bundled with the program which replicates
390
409
  the functionality of Valve's `vpk.exe`.
410
+ - [MareTF](https://github.com/craftablescience/MareTF): An open source MIT-licensed CLI tool that can create VTFs, with more
411
+ features and a companion GUI tool planned. Replicates the functionality of Valve's `vtex.exe`.
391
412
  - [GodotSource](https://github.com/craftablescience/godotsource): A work-in-progress set of bindings to connect the `sourcepp`
392
413
  libraries to Godot. Allows GDScript to work with the libraries, and allows Godot to directly load Source engine assets from
393
414
  a user project or from installed Source games.
@@ -23,10 +23,15 @@ Several modern C++20 libraries for sanely parsing Valve formats, rolled into one
23
23
  <tr><!-- empty row to disable github striped bg color --></tr>
24
24
  <tr>
25
25
  <td rowspan="1"><code>bsppp</code><sup>*</sup></td>
26
- <td><a href="https://developer.valvesoftware.com/wiki/BSP_(Source)">BSP</a> v17-27</td>
26
+ <td>
27
+ <a href="https://developer.valvesoftware.com/wiki/BSP_(Source)">BSP</a> v17-27
28
+ <br> &bull; Console modifications
29
+ <br> &bull; Left 4 Dead 2 modifications
30
+ <br> &bull; <a href="https://stratasource.org">Strata Source</a> modifications
31
+ </td>
27
32
  <td align="center">✅</td>
28
33
  <td align="center">✅</td>
29
- <td rowspan="1" align="center"></td>
34
+ <td rowspan="1" align="center">Python</td>
30
35
  </tr>
31
36
  <tr><!-- empty row to disable github striped bg color --></tr>
32
37
  <tr>
@@ -39,7 +44,7 @@ Several modern C++20 libraries for sanely parsing Valve formats, rolled into one
39
44
  <tr><!-- empty row to disable github striped bg color --></tr>
40
45
  <tr>
41
46
  <td rowspan="1"><code>fspp</code><sup>*</sup></td>
42
- <td>(WIP) Source 1 filesystem accessor</td>
47
+ <td>Source 1 filesystem accessor</td>
43
48
  <td align="center">✅</td>
44
49
  <td align="center">✅</td>
45
50
  <td rowspan="1" align="center"></td>
@@ -87,6 +92,20 @@ Several modern C++20 libraries for sanely parsing Valve formats, rolled into one
87
92
  <td align="center">❌</td>
88
93
  </tr>
89
94
  <tr><!-- empty row to disable github striped bg color --></tr>
95
+ <tr>
96
+ <td rowspan="3"><code>sndpp</code><sup>*</sup></td>
97
+ <td>WAV</td>
98
+ <td align="center">✅</td>
99
+ <td align="center">❌</td>
100
+ <td rowspan="3" align="center"></td>
101
+ </tr>
102
+ <tr><!-- empty row to disable github striped bg color --></tr>
103
+ <tr>
104
+ <td>XWV v4</td>
105
+ <td align="center">✅</td>
106
+ <td align="center">❌</td>
107
+ </tr>
108
+ <tr><!-- empty row to disable github striped bg color --></tr>
90
109
  <tr>
91
110
  <td rowspan="3"><code>steampp</code></td>
92
111
  <td>Find Steam install folder</td>
@@ -362,9 +381,11 @@ found on PyPI in the [sourcepp](https://pypi.org/project/sourcepp) package.
362
381
 
363
382
  A list of projects using the `sourcepp` parser set. If you'd like to see your project here, make a PR!
364
383
 
365
- - [VPKEdit](https://github.com/craftablescience/VPKEdit): An open source MIT-licensed tool that can create, extract from,
366
- preview the contents of and write to several pack file formats. A CLI application is bundled with the program which replicates
384
+ - [VPKEdit](https://github.com/craftablescience/VPKEdit): An open source MIT-licensed GUI tool that can create, extract from,
385
+ preview the contents of and write to several pack file formats. A CLI tool is bundled with the program which replicates
367
386
  the functionality of Valve's `vpk.exe`.
387
+ - [MareTF](https://github.com/craftablescience/MareTF): An open source MIT-licensed CLI tool that can create VTFs, with more
388
+ features and a companion GUI tool planned. Replicates the functionality of Valve's `vtex.exe`.
368
389
  - [GodotSource](https://github.com/craftablescience/godotsource): A work-in-progress set of bindings to connect the `sourcepp`
369
390
  libraries to Godot. Allows GDScript to work with the libraries, and allows Godot to directly load Source engine assets from
370
391
  a user project or from installed Source games.
@@ -278,6 +278,40 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
278
278
  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
279
279
 
280
280
 
281
+ --------------- SciPy ---------------
282
+
283
+ Copyright (c) 2001-2002 Enthought, Inc. 2003, SciPy Developers.
284
+ All rights reserved.
285
+
286
+ Redistribution and use in source and binary forms, with or without
287
+ modification, are permitted provided that the following conditions
288
+ are met:
289
+
290
+ 1. Redistributions of source code must retain the above copyright
291
+ notice, this list of conditions and the following disclaimer.
292
+
293
+ 2. Redistributions in binary form must reproduce the above
294
+ copyright notice, this list of conditions and the following
295
+ disclaimer in the documentation and/or other materials provided
296
+ with the distribution.
297
+
298
+ 3. Neither the name of the copyright holder nor the names of its
299
+ contributors may be used to endorse or promote products derived
300
+ from this software without specific prior written permission.
301
+
302
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
303
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
304
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
305
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
306
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
307
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
308
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
309
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
310
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
311
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
312
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
313
+
314
+
281
315
  --------------- stb ---------------
282
316
 
283
317
  Copyright (c) 2017 Sean Barrett
@@ -30,7 +30,7 @@ endif()
30
30
  set(CMAKE_POSITION_INDEPENDENT_CODE ON)
31
31
 
32
32
  set(SOURCEPP_BUILD_PYTHON_WRAPPERS ON CACHE INTERNAL "" FORCE)
33
- set(SOURCEPP_PYTHON_VERSION "@SOURCEPP_PYTHON_VERSION@")
33
+ set(SOURCEPP_VERSION "@SOURCEPP_VERSION@")
34
34
 
35
35
  # As weird as this looks, this is necessary for sdist wheel
36
36
  set(SOURCEPP_PYTHON_IS_SUBDIR OFF)
@@ -5,7 +5,7 @@ build-backend = "scikit_build_core.build"
5
5
 
6
6
  [project]
7
7
  name = "sourcepp"
8
- version = "${SOURCEPP_PYTHON_VERSION}"
8
+ version = "${SOURCEPP_VERSION}"
9
9
  authors = [{ name = "craftablescience", email = "lauralewisdev@gmail.com" }]
10
10
  maintainers = [{ name = "craftablescience", email = "lauralewisdev@gmail.com" }]
11
11
  description = "Several modern C++20 libraries for sanely parsing Valve formats."
@@ -5,7 +5,7 @@ build-backend = "scikit_build_core.build"
5
5
 
6
6
  [project]
7
7
  name = "sourcepp"
8
- version = "2025.01.26dev1"
8
+ version = "2025.2.12dev1"
9
9
  authors = [{ name = "craftablescience", email = "lauralewisdev@gmail.com" }]
10
10
  maintainers = [{ name = "craftablescience", email = "lauralewisdev@gmail.com" }]
11
11
  description = "Several modern C++20 libraries for sanely parsing Valve formats."
@@ -0,0 +1,315 @@
1
+ #pragma once
2
+
3
+ #include <nanobind/nanobind.h>
4
+ #include <nanobind/stl/array.h>
5
+ #include <nanobind/stl/optional.h>
6
+ #include <nanobind/stl/string.h>
7
+ #include <nanobind/stl/string_view.h>
8
+ #include <nanobind/stl/vector.h>
9
+
10
+ namespace py = nanobind;
11
+
12
+ #include <bsppp/bsppp.h>
13
+
14
+ namespace bsppp {
15
+
16
+ inline void register_python(py::module_& m) {
17
+ auto bsppp = m.def_submodule("bsppp");
18
+ using namespace bsppp;
19
+
20
+ auto cBSP = py::class_<BSP>(bsppp, "BSP");
21
+
22
+ auto cBSPEntityKeyValues = py::class_<BSPEntityKeyValues>(cBSP, "EntityKeyValues");
23
+
24
+ py::class_<BSPEntityKeyValues::Element>(cBSPEntityKeyValues, "Element")
25
+ .def_prop_rw("key", &BSPEntityKeyValues::Element::getKey, &BSPEntityKeyValues::Element::setKey)
26
+ .def_prop_rw("value", &BSPEntityKeyValues::Element::getValue<std::string_view>, &BSPEntityKeyValues::Element::setValue<std::string_view>)
27
+ .def_prop_ro("invalid", &BSPEntityKeyValues::Element::isInvalid);
28
+
29
+ cBSPEntityKeyValues
30
+ .def(py::init<>())
31
+ .def("has_child", &BSPEntityKeyValues::hasChild, py::arg("child_key"))
32
+ .def_prop_ro("keyvalues_count", py::overload_cast<>(&BSPEntityKeyValues::getKeyValuesCount, py::const_))
33
+ .def("get_keyvalues_count_for_key", py::overload_cast<std::string_view>(&BSPEntityKeyValues::getKeyValuesCount, py::const_), py::arg("child_key"))
34
+ .def_prop_ro("keyvalues", &BSPEntityKeyValues::getKeyValues, py::rv_policy::reference_internal)
35
+ .def("at", py::overload_cast<unsigned int>(&BSPEntityKeyValues::operator[]), py::arg("n"), py::rv_policy::reference_internal)
36
+ .def("get", py::overload_cast<std::string_view>(&BSPEntityKeyValues::operator[]), py::arg("child_key"), py::rv_policy::reference_internal)
37
+ .def("__getitem__", py::overload_cast<std::string_view>(&BSPEntityKeyValues::operator[]), py::arg("child_key"), py::rv_policy::reference_internal, py::is_operator())
38
+ .def("get_n", py::overload_cast<std::string_view, unsigned int>(&BSPEntityKeyValues::operator()), py::arg("child_key"), py::arg("n"), py::rv_policy::reference_internal)
39
+ .def("add_keyvalue", &BSPEntityKeyValues::addKeyValue<std::string_view>, py::arg("child_key"), py::arg("value"))
40
+ .def("remove_keyvalue", &BSPEntityKeyValues::removeKeyValue, py::arg("child_key"), py::arg("n") = -1)
41
+ .def("bake", &BSPEntityKeyValues::bake, py::arg("use_escapes"));
42
+
43
+ py::class_<BSPPlane_v0>(cBSP, "Plane_v0")
44
+ .def(py::init<>())
45
+ .def_rw("normal", &BSPPlane_v0::normal)
46
+ .def_rw("dist", &BSPPlane_v0::dist)
47
+ .def_rw("type", &BSPPlane_v0::type);
48
+
49
+ py::class_<BSPTextureData_v0>(cBSP, "TextureData_v0")
50
+ .def(py::init<>())
51
+ .def_rw("reflectivity", &BSPTextureData_v0::reflectivity)
52
+ .def_rw("name_string_table_id", &BSPTextureData_v0::nameStringTableID)
53
+ .def_rw("width", &BSPTextureData_v0::width)
54
+ .def_rw("height", &BSPTextureData_v0::height)
55
+ .def_rw("view_width", &BSPTextureData_v0::width)
56
+ .def_rw("view_height", &BSPTextureData_v0::height);
57
+
58
+ py::class_<BSPVertex_v0>(cBSP, "Vertex_v0")
59
+ .def(py::init<>())
60
+ .def_rw("position", &BSPVertex_v0::position);
61
+
62
+ py::class_<BSPNode_v0>(cBSP, "Node_v0")
63
+ .def(py::init<>())
64
+ .def_rw("plane_num", &BSPNode_v0::planeNum)
65
+ .def_rw("children", &BSPNode_v0::children)
66
+ .def_rw("mins", &BSPNode_v0::mins)
67
+ .def_rw("maxs", &BSPNode_v0::maxs)
68
+ .def_rw("first_face", &BSPNode_v0::firstFace)
69
+ .def_rw("num_faces", &BSPNode_v0::numFaces)
70
+ .def_rw("area", &BSPNode_v0::area);
71
+
72
+ py::class_<BSPNode_v1>(cBSP, "Node_v1")
73
+ .def(py::init<>())
74
+ .def_rw("plane_num", &BSPNode_v1::planeNum)
75
+ .def_rw("children", &BSPNode_v1::children)
76
+ .def_rw("mins", &BSPNode_v1::mins)
77
+ .def_rw("maxs", &BSPNode_v1::maxs)
78
+ .def_rw("first_face", &BSPNode_v1::firstFace)
79
+ .def_rw("num_faces", &BSPNode_v1::numFaces)
80
+ .def_rw("area", &BSPNode_v1::area)
81
+ .def_static("upgrade", &BSPNode_v1::upgrade, py::arg("old"));
82
+
83
+ py::class_<BSPTextureInfo_v0>(cBSP, "TextureInfo_v0")
84
+ .def(py::init<>())
85
+ .def_rw("texture_vector1", &BSPTextureInfo_v0::textureVector1)
86
+ .def_rw("texture_vector2", &BSPTextureInfo_v0::textureVector2)
87
+ .def_rw("lightmap_vector1", &BSPTextureInfo_v0::lightmapVector1)
88
+ .def_rw("lightmap_vector2", &BSPTextureInfo_v0::lightmapVector2)
89
+ .def_rw("flags", &BSPTextureInfo_v0::flags)
90
+ .def_rw("texture_data", &BSPTextureInfo_v0::textureData);
91
+
92
+ py::class_<BSPFace_v1>(cBSP, "Face_v1")
93
+ .def(py::init<>())
94
+ .def_rw("plane_num", &BSPFace_v1::planeNum)
95
+ .def_rw("side", &BSPFace_v1::side)
96
+ .def_rw("on_node", &BSPFace_v1::onNode)
97
+ .def_rw("first_edge", &BSPFace_v1::firstEdge)
98
+ .def_rw("num_edges", &BSPFace_v1::numEdges)
99
+ .def_rw("tex_info", &BSPFace_v1::texInfo)
100
+ .def_rw("disp_info", &BSPFace_v1::dispInfo)
101
+ .def_rw("surface_fog_volume_id", &BSPFace_v1::surfaceFogVolumeID)
102
+ .def_rw("styles", &BSPFace_v1::styles)
103
+ .def_rw("light_offset", &BSPFace_v1::lightOffset)
104
+ .def_rw("area", &BSPFace_v1::area)
105
+ .def_rw("lightmap_texture_mins_in_luxels", &BSPFace_v1::lightmapTextureMinsInLuxels)
106
+ .def_rw("lightmap_texture_size_in_luxels", &BSPFace_v1::lightmapTextureSizeInLuxels)
107
+ .def_rw("original_face", &BSPFace_v1::originalFace)
108
+ .def_rw("num_prims", &BSPFace_v1::numPrims)
109
+ .def_rw("first_prim_id", &BSPFace_v1::firstPrimID)
110
+ .def_rw("smoothing_groups", &BSPFace_v1::smoothingGroups);
111
+
112
+ py::class_<BSPFace_v2>(cBSP, "Face_v2")
113
+ .def(py::init<>())
114
+ .def_rw("plane_num", &BSPFace_v2::planeNum)
115
+ .def_rw("side", &BSPFace_v2::side)
116
+ .def_rw("on_node", &BSPFace_v2::onNode)
117
+ .def_rw("first_edge", &BSPFace_v2::firstEdge)
118
+ .def_rw("num_edges", &BSPFace_v2::numEdges)
119
+ .def_rw("tex_info", &BSPFace_v2::texInfo)
120
+ .def_rw("disp_info", &BSPFace_v2::dispInfo)
121
+ .def_rw("surface_fog_volume_id", &BSPFace_v2::surfaceFogVolumeID)
122
+ .def_rw("styles", &BSPFace_v2::styles)
123
+ .def_rw("light_offset", &BSPFace_v2::lightOffset)
124
+ .def_rw("area", &BSPFace_v2::area)
125
+ .def_rw("lightmap_texture_mins_in_luxels", &BSPFace_v2::lightmapTextureMinsInLuxels)
126
+ .def_rw("lightmap_texture_size_in_luxels", &BSPFace_v2::lightmapTextureSizeInLuxels)
127
+ .def_rw("original_face", &BSPFace_v2::originalFace)
128
+ .def_prop_rw("enable_shadows", [](const BSPFace_v2& self) -> bool { return self.enableShadows; }, [](BSPFace_v2& self, bool enableShadows) { self.enableShadows = enableShadows; })
129
+ .def_prop_rw("num_prims", [](const BSPFace_v2& self) { return self.numPrims; }, [](BSPFace_v2& self, bool numPrims) { self.numPrims = numPrims; })
130
+ .def_rw("first_prim_id", &BSPFace_v2::firstPrimID)
131
+ .def_rw("smoothing_groups", &BSPFace_v2::smoothingGroups)
132
+ .def_static("upgrade", &BSPFace_v2::upgrade);
133
+
134
+ py::class_<BSPEdge_v0>(cBSP, "Edge_v0")
135
+ .def(py::init<>())
136
+ .def_rw("v0", &BSPEdge_v0::v0)
137
+ .def_rw("v1", &BSPEdge_v0::v1);
138
+
139
+ py::class_<BSPEdge_v1>(cBSP, "Edge_v1")
140
+ .def(py::init<>())
141
+ .def_rw("v0", &BSPEdge_v1::v0)
142
+ .def_rw("v1", &BSPEdge_v1::v1)
143
+ .def_static("upgrade", &BSPEdge_v1::upgrade);
144
+
145
+ py::class_<BSPSurfEdge_v0>(cBSP, "SurfEdge_v0")
146
+ .def(py::init<>())
147
+ .def_rw("surf_edge", &BSPSurfEdge_v0::surfEdge);
148
+
149
+ py::class_<BSPBrushModel_v0>(cBSP, "BrushModel_v0")
150
+ .def(py::init<>())
151
+ .def_rw("min", &BSPBrushModel_v0::min)
152
+ .def_rw("max", &BSPBrushModel_v0::max)
153
+ .def_rw("origin", &BSPBrushModel_v0::origin)
154
+ .def_rw("head_node", &BSPBrushModel_v0::headNode)
155
+ .def_rw("first_face", &BSPBrushModel_v0::firstFace)
156
+ .def_rw("num_faces", &BSPBrushModel_v0::numFaces);
157
+
158
+ auto cBSPGameLump = py::class_<BSPGameLump>(cBSP, "GameLump");
159
+
160
+ py::enum_<BSPGameLump::Signature>(cBSPGameLump, "Signature")
161
+ .value("STATIC_PROPS", BSPGameLump::SIGNATURE_STATIC_PROPS)
162
+ .value("DETAIL_PROPS", BSPGameLump::SIGNATURE_DETAIL_PROPS)
163
+ .value("DETAIL_PROP_LIGHTING_LDR", BSPGameLump::SIGNATURE_DETAIL_PROP_LIGHTING_LDR)
164
+ .value("DETAIL_PROP_LIGHTING_HDR", BSPGameLump::SIGNATURE_DETAIL_PROP_LIGHTING_HDR)
165
+ .export_values();
166
+
167
+ cBSPGameLump
168
+ .def_rw("signature", &BSPGameLump::signature)
169
+ .def_rw("is_compressed", &BSPGameLump::isCompressed)
170
+ .def_rw("version", &BSPGameLump::version)
171
+ .def_rw("offset", &BSPGameLump::offset)
172
+ .def_rw("uncompressed_length", &BSPGameLump::uncompressedLength)
173
+ .def_prop_rw("data", [](const BSPGameLump& self) {
174
+ return py::bytes{self.data.data(), self.data.size()};
175
+ }, [](BSPGameLump& self, const py::bytes& data) {
176
+ self.data = {reinterpret_cast<const std::byte*>(data.data()), reinterpret_cast<const std::byte*>(data.data()) + data.size()};
177
+ });
178
+
179
+ bsppp.attr("BSP_SIGNATURE") = BSP_SIGNATURE;
180
+ bsppp.attr("BSP_LUMP_COUNT") = BSP_LUMP_COUNT;
181
+ bsppp.attr("BSP_LUMP_ORDER") = BSP_LUMP_ORDER;
182
+
183
+ py::enum_<BSPLump>(cBSP, "Lump")
184
+ .value("UNKNOWN", BSPLump::UNKNOWN)
185
+ .value("ENTITIES", BSPLump::ENTITIES)
186
+ .value("PLANES", BSPLump::PLANES)
187
+ .value("TEXDATA", BSPLump::TEXDATA)
188
+ .value("VERTEXES", BSPLump::VERTEXES)
189
+ .value("VISIBILITY", BSPLump::VISIBILITY)
190
+ .value("NODES", BSPLump::NODES)
191
+ .value("TEXINFO", BSPLump::TEXINFO)
192
+ .value("FACES", BSPLump::FACES)
193
+ .value("LIGHTING", BSPLump::LIGHTING)
194
+ .value("OCCLUSION", BSPLump::OCCLUSION)
195
+ .value("LEAFS", BSPLump::LEAFS)
196
+ .value("FACEIDS", BSPLump::FACEIDS)
197
+ .value("EDGES", BSPLump::EDGES)
198
+ .value("SURFEDGES", BSPLump::SURFEDGES)
199
+ .value("MODELS", BSPLump::MODELS)
200
+ .value("WORLDLIGHTS", BSPLump::WORLDLIGHTS)
201
+ .value("LEAFFACES", BSPLump::LEAFFACES)
202
+ .value("LEAFBRUSHES", BSPLump::LEAFBRUSHES)
203
+ .value("BRUSHES", BSPLump::BRUSHES)
204
+ .value("BRUSHSIDES", BSPLump::BRUSHSIDES)
205
+ .value("AREAS", BSPLump::AREAS)
206
+ .value("AREAPORTALS", BSPLump::AREAPORTALS)
207
+ .value("S2004_PORTALS", BSPLump::S2004_PORTALS)
208
+ .value("UNUSED0", BSPLump::UNUSED0)
209
+ .value("SL4D2_PROPCOLLISION", BSPLump::SL4D2_PROPCOLLISION)
210
+ .value("S2004_CLUSTERS", BSPLump::S2004_CLUSTERS)
211
+ .value("UNUSED1", BSPLump::UNUSED1)
212
+ .value("SL4D2_PROPHULLS", BSPLump::SL4D2_PROPHULLS)
213
+ .value("S2004_PORTALVERTS", BSPLump::S2004_PORTALVERTS)
214
+ .value("UNUSED2", BSPLump::UNUSED2)
215
+ .value("SL4D2_PROPHULLVERTS", BSPLump::SL4D2_PROPHULLVERTS)
216
+ .value("S2004_CLUSTERPORTALS", BSPLump::S2004_CLUSTERPORTALS)
217
+ .value("UNUSED3", BSPLump::UNUSED3)
218
+ .value("SL4D2_PROPTRIS", BSPLump::SL4D2_PROPTRIS)
219
+ .value("DISPINFO", BSPLump::DISPINFO)
220
+ .value("ORIGINALFACES", BSPLump::ORIGINALFACES)
221
+ .value("PHYSDISP", BSPLump::PHYSDISP)
222
+ .value("PHYSCOLLIDE", BSPLump::PHYSCOLLIDE)
223
+ .value("VERTNORMALS", BSPLump::VERTNORMALS)
224
+ .value("VERTNORMALINDICES", BSPLump::VERTNORMALINDICES)
225
+ .value("S2004_DISP_LIGHTMAP_ALPHAS", BSPLump::S2004_DISP_LIGHTMAP_ALPHAS)
226
+ .value("UNUSED4", BSPLump::UNUSED4)
227
+ .value("DISP_VERTS", BSPLump::DISP_VERTS)
228
+ .value("DISP_LIGHTMAP_SAMPLE_POSITIONS", BSPLump::DISP_LIGHTMAP_SAMPLE_POSITIONS)
229
+ .value("GAME_LUMP", BSPLump::GAME_LUMP)
230
+ .value("LEAFWATERDATA", BSPLump::LEAFWATERDATA)
231
+ .value("PRIMITIVES", BSPLump::PRIMITIVES)
232
+ .value("PRIMVERTS", BSPLump::PRIMVERTS)
233
+ .value("PRIMINDICES", BSPLump::PRIMINDICES)
234
+ .value("PAKFILE", BSPLump::PAKFILE)
235
+ .value("CLIPPORTALVERTS", BSPLump::CLIPPORTALVERTS)
236
+ .value("CUBEMAPS", BSPLump::CUBEMAPS)
237
+ .value("TEXDATA_STRING_DATA", BSPLump::TEXDATA_STRING_DATA)
238
+ .value("TEXDATA_STRING_TABLE", BSPLump::TEXDATA_STRING_TABLE)
239
+ .value("OVERLAYS", BSPLump::OVERLAYS)
240
+ .value("LEAFMINDISTTOWATER", BSPLump::LEAFMINDISTTOWATER)
241
+ .value("FACE_MACRO_TEXTURE_INFO", BSPLump::FACE_MACRO_TEXTURE_INFO)
242
+ .value("DISP_TRIS", BSPLump::DISP_TRIS)
243
+ .value("S2004_PHYSCOLLIDESURFACE", BSPLump::S2004_PHYSCOLLIDESURFACE)
244
+ .value("UNUSED5", BSPLump::UNUSED5)
245
+ .value("SL4D2_PROP_BLOB", BSPLump::SL4D2_PROP_BLOB)
246
+ .value("WATEROVERLAYS", BSPLump::WATEROVERLAYS)
247
+ .value("S2006_XBOX_LIGHTMAPPAGES", BSPLump::S2006_XBOX_LIGHTMAPPAGES)
248
+ .value("LEAF_AMBIENT_INDEX_HDR", BSPLump::LEAF_AMBIENT_INDEX_HDR)
249
+ .value("S2006_XBOX_LIGHTMAPPAGEINFOS", BSPLump::S2006_XBOX_LIGHTMAPPAGEINFOS)
250
+ .value("LEAF_AMBIENT_INDEX", BSPLump::LEAF_AMBIENT_INDEX)
251
+ .value("LIGHTING_HDR", BSPLump::LIGHTING_HDR)
252
+ .value("WORLDLIGHTS_HDR", BSPLump::WORLDLIGHTS_HDR)
253
+ .value("LEAF_AMBIENT_LIGHTING_HDR", BSPLump::LEAF_AMBIENT_LIGHTING_HDR)
254
+ .value("LEAF_AMBIENT_LIGHTING", BSPLump::LEAF_AMBIENT_LIGHTING)
255
+ .value("XBOX_XZIPPAKFILE", BSPLump::XBOX_XZIPPAKFILE)
256
+ .value("FACES_HDR", BSPLump::FACES_HDR)
257
+ .value("MAP_FLAGS", BSPLump::MAP_FLAGS)
258
+ .value("OVERLAY_FADES", BSPLump::OVERLAY_FADES)
259
+ .value("L4D_OVERLAY_SYSTEM_LEVELS", BSPLump::L4D_OVERLAY_SYSTEM_LEVELS)
260
+ .value("UNUSED6", BSPLump::UNUSED6)
261
+ .value("L4D2_PHYSLEVEL", BSPLump::L4D2_PHYSLEVEL)
262
+ .value("UNUSED7", BSPLump::UNUSED7)
263
+ .value("ASW_DISP_MULTIBLEND", BSPLump::ASW_DISP_MULTIBLEND)
264
+ .value("UNUSED8", BSPLump::UNUSED8)
265
+ .export_values();
266
+
267
+ cBSP
268
+ .def(py::init<std::string, bool>(), py::arg("path"), py::arg("load_patch_files") = true)
269
+ .def("__bool__", &BSP::operator bool, py::is_operator())
270
+ .def_static("create", &BSP::create, py::arg("path"), py::arg("version") = 21, py::arg("map_revision") = 0)
271
+ .def_prop_rw("version", &BSP::getVersion, &BSP::setVersion)
272
+ .def_prop_rw("map_revision", &BSP::getMapRevision, &BSP::setMapRevision)
273
+ .def_prop_rw("l4d2", &BSP::isL4D2, &BSP::setL4D2)
274
+ .def_prop_rw("console", &BSP::isConsole, &BSP::setConsole)
275
+ .def("has_lump", &BSP::hasLump, py::arg("lump_index"))
276
+ .def("is_lump_compressed", &BSP::isLumpCompressed, py::arg("lump_index"))
277
+ .def("get_lump_version", &BSP::getLumpVersion, py::arg("lump_index"))
278
+ .def("get_lump_data", [](const BSP& self, BSPLump lumpIndex, bool noDecompression = false) -> py::object {
279
+ const auto d = self.getLumpData(lumpIndex, noDecompression);
280
+ return d ? py::bytes{d->data(), d->size()} : py::none();
281
+ }, py::arg("lump_index"), py::arg("no_decompression") = false)
282
+ .def("get_lump_data_for_entities", &BSP::getLumpData<BSPLump::ENTITIES>)
283
+ .def("get_lump_data_for_planes", &BSP::getLumpData<BSPLump::PLANES>)
284
+ .def("get_lump_data_for_texdata", &BSP::getLumpData<BSPLump::TEXDATA>)
285
+ .def("get_lump_data_for_vertexes", &BSP::getLumpData<BSPLump::VERTEXES>)
286
+ .def("get_lump_data_for_nodes", &BSP::getLumpData<BSPLump::NODES>)
287
+ .def("get_lump_data_for_texinfo", &BSP::getLumpData<BSPLump::TEXINFO>)
288
+ .def("get_lump_data_for_faces", &BSP::getLumpData<BSPLump::FACES>)
289
+ .def("get_lump_data_for_edges", &BSP::getLumpData<BSPLump::EDGES>)
290
+ .def("get_lump_data_for_surfedges", &BSP::getLumpData<BSPLump::SURFEDGES>)
291
+ .def("get_lump_data_for_models", &BSP::getLumpData<BSPLump::MODELS>)
292
+ .def("get_lump_data_for_originalfaces", &BSP::getLumpData<BSPLump::ORIGINALFACES>)
293
+ .def("get_lump_data_for_game_lump", &BSP::getLumpData<BSPLump::GAME_LUMP>)
294
+ .def("set_lump", [](BSP& self, BSPLump lumpIndex, uint32_t version, const py::bytes& data, uint8_t compressLevel = 0) {
295
+ self.setLump(lumpIndex, version, {reinterpret_cast<const std::byte*>(data.data()), data.size()}, compressLevel);
296
+ }, py::arg("lump_index"), py::arg("version"), py::arg("data"), py::arg("compress_level") = 0)
297
+ .def("set_lump_for_entities", [](BSP& self, uint32_t version, const std::vector<BSPEntityKeyValues>& data, uint8_t compressLevel = 0) {
298
+ self.setLump(version, data, compressLevel);
299
+ }, py::arg("version"), py::arg("data"), py::arg("compress_level"))
300
+ .def("is_game_lump_compressed", &BSP::isGameLumpCompressed, py::arg("signature"))
301
+ .def("get_game_lump_data", [](const BSP& self, BSPGameLump::Signature signature) -> py::object {
302
+ const auto d = self.getGameLumpData(signature);
303
+ return d ? py::bytes{d->data(), d->size()} : py::none();
304
+ }, py::arg("signature"))
305
+ .def("set_game_lump", &BSP::setGameLump, py::arg("signature"), py::arg("version"), py::arg("data"), py::arg("compress_level") = 0)
306
+ .def("reset_lump", &BSP::resetLump, py::arg("lump_index"))
307
+ .def("reset", &BSP::reset)
308
+ .def("create_lump_patch_file", &BSP::createLumpPatchFile, py::arg("lump_index"))
309
+ .def("set_lump_from_patch_file", &BSP::setLumpFromPatchFile, py::arg("lump_file_path"))
310
+ .def("bake", &BSP::bake, py::arg("output_path") = "");
311
+
312
+ // todo(python): PakLump.h (when vpkpp bindings are in)
313
+ }
314
+
315
+ } // namespace bsppp
@@ -0,0 +1,5 @@
1
+ from ._sourcepp_impl import __doc__, bsppp, gamepp, sourcepp, steampp, toolpp, vcryptpp, vtfpp
2
+
3
+ __author__ = "craftablescience"
4
+ __version__ = "2025.2.12dev1"
5
+ __all__ = ['__author__', '__doc__', '__version__', 'bsppp', 'gamepp', 'sourcepp', 'steampp', 'toolpp', 'vcryptpp', 'vtfpp']
@@ -1,5 +1,9 @@
1
1
  #include "sourcepp.h"
2
2
 
3
+ #ifdef BSPPP
4
+ #include "bsppp.h"
5
+ #endif
6
+
3
7
  #ifdef GAMEPP
4
8
  #include "gamepp.h"
5
9
  #endif
@@ -25,6 +29,12 @@ NB_MODULE(_sourcepp_impl, m) {
25
29
 
26
30
  sourcepp::register_python(m);
27
31
 
32
+ #ifdef BSPPP
33
+ bsppp::register_python(m);
34
+ #else
35
+ m.def_submodule("bsppp");
36
+ #endif
37
+
28
38
  #ifdef GAMEPP
29
39
  gamepp::register_python(m);
30
40
  #else
@@ -165,8 +165,10 @@ void register_python(py::module_& m) {
165
165
  .value("BOX", ResizeFilter::BOX)
166
166
  .value("BILINEAR", ResizeFilter::BILINEAR)
167
167
  .value("CUBIC_BSPLINE", ResizeFilter::CUBIC_BSPLINE)
168
- .value("CATMULLROM", ResizeFilter::CATMULLROM)
168
+ .value("CATMULL_ROM", ResizeFilter::CATMULL_ROM)
169
169
  .value("MITCHELL", ResizeFilter::MITCHELL)
170
+ .value("POINT_SAMPLE", ResizeFilter::POINT_SAMPLE)
171
+ .value("KAISER", ResizeFilter::KAISER)
170
172
  .export_values();
171
173
 
172
174
  py::enum_<ResizeMethod>(ImageConversion, "ResizeMethod")
@@ -235,11 +237,11 @@ void register_python(py::module_& m) {
235
237
  .def("set_image", [](PPL& self, const py::bytes& imageData, ImageFormat format, uint32_t width, uint32_t height, uint32_t lod = 0) {
236
238
  self.setImage({reinterpret_cast<const std::byte*>(imageData.data()), imageData.size()}, format, width, height, lod);
237
239
  }, py::arg("imageData"), py::arg("format"), py::arg("width"), py::arg("height"), py::arg("lod") = 0)
238
- .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) {
240
+ .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::DEFAULT) {
239
241
  self.setImage({reinterpret_cast<const std::byte*>(imageData.data()), imageData.size()}, format, width, height, resizedWidth, resizedHeight, lod, filter);
240
- }, 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)
242
+ }, 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::DEFAULT)
241
243
  .def("set_image_from_file", py::overload_cast<const std::string&, uint32_t>(&PPL::setImage), py::arg("image_path"), py::arg("lod") = 0)
242
- .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)
244
+ .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::DEFAULT)
243
245
  .def("save_image", [](const PPL& self, uint32_t lod = 0, ImageConversion::FileFormat fileFormat = ImageConversion::FileFormat::DEFAULT) {
244
246
  const auto d = self.saveImageToFile(lod, fileFormat);
245
247
  return py::bytes{d.data(), d.size()};
@@ -428,11 +430,12 @@ void register_python(py::module_& m) {
428
430
  .def_prop_rw("flags", &VTF::getFlags, &VTF::setFlags)
429
431
  .def("add_flags", &VTF::addFlags, py::arg("flags"))
430
432
  .def("remove_flags", &VTF::removeFlags, py::arg("flags"))
433
+ .def_static("get_default_compressed_format", &VTF::getDefaultCompressedFormat, py::arg("input_format"), py::arg("major_version"), py::arg("minor_version"))
431
434
  .def_prop_ro("format", &VTF::getFormat)
432
- .def("set_format", &VTF::setFormat, py::arg("new_format"), py::arg("filter") = ImageConversion::ResizeFilter::BILINEAR)
435
+ .def("set_format", &VTF::setFormat, py::arg("new_format"), py::arg("filter") = ImageConversion::ResizeFilter::DEFAULT)
433
436
  .def_prop_rw("mip_count", &VTF::getMipCount, &VTF::setMipCount)
434
437
  .def("set_recommended_mip_count", &VTF::setRecommendedMipCount)
435
- .def("compute_mips", &VTF::computeMips, py::arg("filter") = ImageConversion::ResizeFilter::BILINEAR)
438
+ .def("compute_mips", &VTF::computeMips, py::arg("filter") = ImageConversion::ResizeFilter::DEFAULT)
436
439
  .def_prop_rw("frame_count", &VTF::getFrameCount, &VTF::setFrameCount)
437
440
  .def_prop_ro("face_count", &VTF::getFaceCount)
438
441
  .def("set_face_count", &VTF::setFaceCount, py::arg("is_cubemap"), py::arg("has_spheremap") = false)
@@ -488,10 +491,10 @@ void register_python(py::module_& m) {
488
491
  const auto d = self.getImageDataAsRGBA8888(mip, frame, face, slice);
489
492
  return py::bytes{d.data(), d.size()};
490
493
  }, py::arg("mip") = 0, py::arg("frame") = 0, py::arg("face") = 0, py::arg("slice") = 0)
491
- .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) {
494
+ .def("set_image", [](VTF& self, const py::bytes& imageData, ImageFormat format, uint16_t width, uint16_t height, ImageConversion::ResizeFilter filter = ImageConversion::ResizeFilter::DEFAULT, uint8_t mip = 0, uint16_t frame = 0, uint8_t face = 0, uint16_t slice = 0) {
492
495
  return self.setImage({reinterpret_cast<const std::byte*>(imageData.data()), imageData.size()}, format, width, height, filter, mip, frame, face, slice);
493
496
  }, 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)
494
- .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)
497
+ .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::DEFAULT, py::arg("mip") = 0, py::arg("frame") = 0, py::arg("face") = 0, py::arg("slice") = 0)
495
498
  .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) {
496
499
  const auto d = self.saveImageToFile(mip, frame, face, slice, fileFormat);
497
500
  return py::bytes{d.data(), d.size()};
@@ -513,7 +516,7 @@ void register_python(py::module_& m) {
513
516
  .def("set_thumbnail", [](VTF& self, const py::bytes& imageData, ImageFormat format, uint16_t width, uint16_t height) {
514
517
  return self.setThumbnail({reinterpret_cast<const std::byte*>(imageData.data()), imageData.size()}, format, width, height);
515
518
  }, py::arg("image_data"), py::arg("format"), py::arg("width"), py::arg("height"))
516
- .def("compute_thumbnail", &VTF::computeThumbnail, py::arg("filter") = ImageConversion::ResizeFilter::BILINEAR)
519
+ .def("compute_thumbnail", &VTF::computeThumbnail, py::arg("filter") = ImageConversion::ResizeFilter::DEFAULT)
517
520
  .def("remove_thumbnail", &VTF::removeThumbnail)
518
521
  .def("save_thumbnail", [](const VTF& self, ImageConversion::FileFormat fileFormat = ImageConversion::FileFormat::DEFAULT) {
519
522
  const auto d = self.saveThumbnailToFile(fileFormat);
@@ -1,5 +0,0 @@
1
- from ._sourcepp_impl import __doc__, gamepp, sourcepp, steampp, toolpp, vcryptpp, vtfpp
2
-
3
- __author__ = "craftablescience"
4
- __version__ = "2025.01.26dev1"
5
- __all__ = ['__author__', '__doc__', '__version__', 'gamepp', 'sourcepp', 'steampp', 'toolpp', 'vcryptpp', 'vtfpp']