Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -219,11 +219,11 @@ Several modern C++20 libraries for sanely parsing Valve formats, rolled into one
</tr>
<tr><!-- empty row to disable github striped bg color --></tr>
<tr>
<td rowspan="25"><code>vtfpp</code></td>
<td rowspan="27"><code>vtfpp</code></td>
<td><a href="https://wiki.mozilla.org/APNG_Specification">APNG</a></td>
<td align="center">✅</td>
<td align="center">❌</td>
<td rowspan="25" align="center">Python</td>
<td rowspan="27" align="center">Python</td>
</tr>
<tr><!-- empty row to disable github striped bg color --></tr>
<tr>
Expand Down Expand Up @@ -286,6 +286,12 @@ Several modern C++20 libraries for sanely parsing Valve formats, rolled into one
<td align="center">❌</td>
</tr>
<tr><!-- empty row to disable github striped bg color --></tr>
<tr>
<td><a href="https://developer.valvesoftware.com/wiki/Animated_Particles">SHT</a> v0-1</td>
<td align="center">✅</td>
<td align="center">✅</td>
</tr>
<tr><!-- empty row to disable github striped bg color --></tr>
<tr>
<td><a href="https://en.wikipedia.org/wiki/Truevision_TGA">TGA</a></td>
<td align="center">✅</td>
Expand Down
9 changes: 7 additions & 2 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -191,11 +191,11 @@ Several modern C++20 libraries for sanely parsing Valve formats, rolled into one
<td align="center">✅</td>
</tr>
<tr>
<td rowspan="13"><code>vtfpp</code></td>
<td rowspan="14"><code>vtfpp</code></td>
<td><a href="https://wiki.mozilla.org/APNG_Specification">APNG</a></td>
<td align="center">✅</td>
<td align="center">❌</td>
<td rowspan="13" align="center">Python</td>
<td rowspan="14" align="center">Python</td>
</tr>
<tr>
<td><a href="https://en.wikipedia.org/wiki/BMP_file_format">BMP</a></td>
Expand Down Expand Up @@ -247,6 +247,11 @@ Several modern C++20 libraries for sanely parsing Valve formats, rolled into one
<td align="center">✅</td>
<td align="center">❌</td>
</tr>
<tr>
<td><a href="https://developer.valvesoftware.com/wiki/Animated_Particles">SHT</a> v0-1</td>
<td align="center">✅</td>
<td align="center">✅</td>
</tr>
<tr>
<td><a href="https://en.wikipedia.org/wiki/Truevision_TGA">TGA</a></td>
<td align="center">✅</td>
Expand Down
3 changes: 3 additions & 0 deletions include/vtfpp/ImageConversion.h
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,9 @@ void setResizedDims(uint16_t& width, ResizeMethod widthResize, uint16_t& height,
/// Resize given image data to the new dimensions, where the new width and height are governed by the resize methods
[[nodiscard]] std::vector<std::byte> resizeImageDataStrict(std::span<const std::byte> imageData, ImageFormat format, uint16_t width, uint16_t newWidth, uint16_t& widthOut, ResizeMethod widthResize, uint16_t height, uint16_t newHeight, uint16_t& heightOut, ResizeMethod heightResize, bool srgb, ResizeFilter filter, ResizeEdge edge = ResizeEdge::CLAMP);

/// Crops the given image to the new dimensions. If the image format is compressed it will be converted to its container format before the crop, and converted back before returning
[[nodiscard]] std::vector<std::byte> cropImageData(std::span<const std::byte> imageData, ImageFormat format, uint16_t width, uint16_t newWidth, uint16_t xOffset, uint16_t height, uint16_t newHeight, uint16_t yOffset);

/// Extracts a single channel from the given image data.
/// May have unexpected behavior if called on formats that use bitfields like BGRA5551!
/// Data is packed according to pixel channel C++ type size
Expand Down
75 changes: 75 additions & 0 deletions include/vtfpp/SHT.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#pragma once

#include <array>
#include <cstddef>
#include <span>
#include <string>
#include <vector>

#include <sourcepp/Math.h>

namespace vtfpp {

class SHT {
public:
struct Sequence {
struct Frame {
struct Bounds {
float x1;
float y1;
float x2;
float y2;
};

float duration;
// A sprite frame can reference 1 or 4 images, depending on the version
std::array<Bounds, 4> bounds;

void setAllBounds(Bounds newBounds) {
this->bounds[0] = newBounds;
this->bounds[1] = newBounds;
this->bounds[2] = newBounds;
this->bounds[3] = newBounds;
}
};

uint32_t id;
bool loop;
std::vector<Frame> frames;
float durationTotal;
};

SHT();

explicit SHT(std::span<const std::byte> shtData);

explicit SHT(const std::string& shtPath);

[[nodiscard]] explicit operator bool() const;

[[nodiscard]] uint32_t getVersion() const;

void setVersion(uint32_t v);

[[nodiscard]] const std::vector<Sequence>& getSequences() const;

[[nodiscard]] std::vector<Sequence>& getSequences();

[[nodiscard]] const Sequence* getSequenceFromID(uint32_t id) const;

[[nodiscard]] Sequence* getSequenceFromID(uint32_t id);

[[nodiscard]] uint8_t getFrameBoundsCount() const;

[[nodiscard]] std::vector<std::byte> bake() const;

bool bake(const std::string& shtPath) const; // NOLINT(*-use-nodiscard)

protected:
bool opened;

uint32_t version;
std::vector<Sequence> sequences;
};

} // namespace vtfpp
17 changes: 16 additions & 1 deletion include/vtfpp/VTF.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <sourcepp/Macros.h>

#include "ImageConversion.h"
#include "SHT.h"

namespace vtfpp {

Expand Down Expand Up @@ -48,13 +49,18 @@ struct Resource {

using ConvertedData = std::variant<
std::monostate, // Anything that would be equivalent to just returning data directly, or used as an error
SHT, // Particle Sheet
uint32_t, // CRC, TSO
std::pair<uint8_t, uint8_t>, // LOD
std::string, // KVD
std::span<uint32_t> // AXC
>;
[[nodiscard]] ConvertedData convertData() const;

[[nodiscard]] SHT getDataAsParticleSheet() const {
return std::get<SHT>(this->convertData());
}

[[nodiscard]] uint32_t getDataAsCRC() const {
return std::get<uint32_t>(this->convertData());
}
Expand Down Expand Up @@ -296,7 +302,16 @@ class VTF {

[[nodiscard]] const Resource* getResource(Resource::Type type) const;

void setParticleSheetResource(std::span<const std::byte> value);
/// This is a convenience function. You're best off uploading the bounds to the GPU and scaling the UV there if trying to render a particle
[[nodiscard]] std::vector<std::byte> getParticleSheetFrameDataRaw(uint16_t& spriteWidth, uint16_t& spriteHeight, uint32_t shtSequenceID, uint32_t shtFrame, uint8_t shtBounds = 0, uint8_t mip = 0, uint16_t frame = 0, uint8_t face = 0, uint16_t slice = 0) const;

/// This is a convenience function. You're best off uploading the bounds to the GPU and scaling the UV there if trying to render a particle
[[nodiscard]] std::vector<std::byte> getParticleSheetFrameDataAs(ImageFormat newFormat, uint16_t& spriteWidth, uint16_t& spriteHeight, uint32_t shtSequenceID, uint32_t shtFrame, uint8_t shtBounds = 0, uint8_t mip = 0, uint16_t frame = 0, uint8_t face = 0, uint16_t slice = 0) const;

/// This is a convenience function. You're best off uploading the bounds to the GPU and scaling the UV there if trying to render a particle
[[nodiscard]] std::vector<std::byte> getParticleSheetFrameDataAsRGBA8888(uint16_t& spriteWidth, uint16_t& spriteHeight, uint32_t shtSequenceID, uint32_t shtFrame, uint8_t shtBounds = 0, uint8_t mip = 0, uint16_t frame = 0, uint8_t face = 0, uint16_t slice = 0) const;

void setParticleSheetResource(const SHT& value);

void removeParticleSheetResource();

Expand Down
1 change: 1 addition & 0 deletions include/vtfpp/vtfpp.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@
#include "ImageConversion.h"
#include "ImageFormats.h"
#include "PPL.h"
#include "SHT.h"
#include "VTF.h"
20 changes: 10 additions & 10 deletions lang/python/src/gamepp.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,16 @@ inline void register_python(py::module_& m) {
using namespace gamepp;

py::class_<GameInstance>(gamepp, "GameInstance")
.def_static("find", &GameInstance::find, py::arg("window_name_override") = "")
.def_prop_ro("window_title", &GameInstance::getWindowTitle)
.def_prop_ro("window_pos", &GameInstance::getWindowPos)
.def_prop_ro("window_size", &GameInstance::getWindowSize)
.def("command", &GameInstance::command, py::arg("command"), py::rv_policy::reference)
.def("input_begin", &GameInstance::inputBegin, py::arg("input"), py::rv_policy::reference)
.def("input_end", &GameInstance::inputEnd, py::arg("input"), py::rv_policy::reference)
.def("input_once", &GameInstance::inputOnce, py::arg("input"), py::rv_policy::reference)
.def("input_hold", &GameInstance::inputHold, py::arg("input"), py::arg("sec"), py::rv_policy::reference)
.def("wait", &GameInstance::wait, py::arg("sec"), py::rv_policy::reference);
.def_static("find", &GameInstance::find, py::arg("window_name_override") = "")
.def_prop_ro("window_title", &GameInstance::getWindowTitle)
.def_prop_ro("window_pos", &GameInstance::getWindowPos)
.def_prop_ro("window_size", &GameInstance::getWindowSize)
.def("command", &GameInstance::command, py::arg("command"), py::rv_policy::reference)
.def("input_begin", &GameInstance::inputBegin, py::arg("input"), py::rv_policy::reference)
.def("input_end", &GameInstance::inputEnd, py::arg("input"), py::rv_policy::reference)
.def("input_once", &GameInstance::inputOnce, py::arg("input"), py::rv_policy::reference)
.def("input_hold", &GameInstance::inputHold, py::arg("input"), py::arg("sec"), py::rv_policy::reference)
.def("wait", &GameInstance::wait, py::arg("sec"), py::rv_policy::reference);
}

} // namespace gamepp
10 changes: 5 additions & 5 deletions lang/python/src/sourcepp.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ inline void register_python(py::module_& m) {

const auto registerVecType = [&math]<typename V>(std::string_view name) {
py::class_<V>(math, name.data())
.def("__len__", &V::size)
.def("__setitem__", [](V& self, uint8_t index, typename V::value_type val) { self[index] = val; })
.def("__getitem__", [](V& self, uint8_t index) { return self[index]; })
.def_static("zero", &V::zero)
.def("is_zero", &V::isZero);
.def("__len__", &V::size)
.def("__setitem__", [](V& self, uint8_t index, typename V::value_type val) { self[index] = val; })
.def("__getitem__", [](V& self, uint8_t index) { return self[index]; })
.def_static("zero", &V::zero)
.def("is_zero", &V::isZero);
};

registerVecType.operator()<Vec2i8>("Vec2i8");
Expand Down
30 changes: 15 additions & 15 deletions lang/python/src/steampp.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,21 @@ inline void register_python(py::module_& m) {
using namespace steampp;

py::class_<Steam>(steampp, "Steam")
.def(py::init<>())
.def_prop_ro("install_dir", &Steam::getInstallDir)
.def_prop_ro("library_dirs", &Steam::getLibraryDirs)
.def_prop_ro("sourcemod_dir", &Steam::getSourceModDir)
.def_prop_ro("installed_apps", &Steam::getInstalledApps)
.def("is_app_installed", &Steam::isAppInstalled, py::arg("appID"))
.def("get_app_name", &Steam::getAppName, py::arg("appID"))
.def("get_app_install_dir", &Steam::getAppInstallDir, py::arg("appID"))
.def("get_app_icon_path", &Steam::getAppIconPath, py::arg("appID"))
.def("get_app_logo_path", &Steam::getAppLogoPath, py::arg("appID"))
.def("get_app_box_art_path", &Steam::getAppBoxArtPath, py::arg("appID"))
.def("get_app_store_art_path", &Steam::getAppStoreArtPath, py::arg("appID"))
.def("is_app_using_source_engine", &Steam::isAppUsingSourceEngine, py::arg("appID"))
.def("is_app_using_source_2_engine", &Steam::isAppUsingSource2Engine, py::arg("appID"))
.def("__bool__", &Steam::operator bool, py::is_operator());
.def(py::init<>())
.def_prop_ro("install_dir", &Steam::getInstallDir)
.def_prop_ro("library_dirs", &Steam::getLibraryDirs)
.def_prop_ro("sourcemod_dir", &Steam::getSourceModDir)
.def_prop_ro("installed_apps", &Steam::getInstalledApps)
.def("is_app_installed", &Steam::isAppInstalled, py::arg("appID"))
.def("get_app_name", &Steam::getAppName, py::arg("appID"))
.def("get_app_install_dir", &Steam::getAppInstallDir, py::arg("appID"))
.def("get_app_icon_path", &Steam::getAppIconPath, py::arg("appID"))
.def("get_app_logo_path", &Steam::getAppLogoPath, py::arg("appID"))
.def("get_app_box_art_path", &Steam::getAppBoxArtPath, py::arg("appID"))
.def("get_app_store_art_path", &Steam::getAppStoreArtPath, py::arg("appID"))
.def("is_app_using_source_engine", &Steam::isAppUsingSourceEngine, py::arg("appID"))
.def("is_app_using_source_2_engine", &Steam::isAppUsingSource2Engine, py::arg("appID"))
.def("__bool__", &Steam::operator bool, py::is_operator());
}

} // namespace steampp
Loading
Loading