diff --git a/frontend/CMakeLists.txt b/frontend/CMakeLists.txt index 380941569..fed457ee5 100644 --- a/frontend/CMakeLists.txt +++ b/frontend/CMakeLists.txt @@ -46,6 +46,7 @@ include(cmake/ui-components.cmake) include(cmake/ui-dialogs.cmake) include(cmake/ui-docks.cmake) include(cmake/feature-importers.cmake) +include(cmake/ui-models.cmake) include(cmake/ui-oauth.cmake) include(cmake/feature-browserpanels.cmake) include(cmake/ui-qt.cmake) diff --git a/frontend/cmake/ui-models.cmake b/frontend/cmake/ui-models.cmake new file mode 100644 index 000000000..a5f948740 --- /dev/null +++ b/frontend/cmake/ui-models.cmake @@ -0,0 +1 @@ +target_sources(obs-studio PRIVATE models/SceneCollection.cpp models/SceneCollection.hpp models/Rect.cpp models/Rect.hpp) diff --git a/frontend/models/Rect.cpp b/frontend/models/Rect.cpp new file mode 100644 index 000000000..1292d405d --- /dev/null +++ b/frontend/models/Rect.cpp @@ -0,0 +1,35 @@ +/****************************************************************************** + Copyright (C) 2025 by Patrick Heyer + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +******************************************************************************/ + +#include "Rect.hpp" + +namespace OBS { +bool Rect::isZero() const +{ + return width_ == 0.0 || height_ == 0.0; +} + +bool operator==(const Rect &lhs, const Rect &rhs) +{ + return lhs.width_ == rhs.width_ && lhs.height_ == rhs.height_; +} + +bool operator!=(const Rect &lhs, const Rect &rhs) +{ + return lhs.width_ != rhs.width_ || lhs.height_ != rhs.height_; +} +} // namespace OBS diff --git a/frontend/models/Rect.hpp b/frontend/models/Rect.hpp new file mode 100644 index 000000000..9e73a6429 --- /dev/null +++ b/frontend/models/Rect.hpp @@ -0,0 +1,98 @@ +/****************************************************************************** + Copyright (C) 2025 by Patrick Heyer + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +******************************************************************************/ + +#pragma once + +#include +#include + +namespace { +template inline double safeConvertToDouble(numberType number) +{ + constexpr double minDoubleValue = 0.0; + constexpr double maxDoubleValue = std::numeric_limits::max(); + + if (number > maxDoubleValue) { + return maxDoubleValue; + } else if (number < minDoubleValue) { + return minDoubleValue; + } else { + return static_cast(number); + } +} +} // namespace + +namespace OBS { + +struct Rect { + double width_ = 0.0; + double height_ = 0.0; + + Rect() = default; + + template Rect(widthType width, heightType height) + { + setWidth(width); + setHeight(height); + } + + template returnType getWidth() const + { + static_assert(std::is_convertible_v, + "Cannot convert to requested return type"); + + return static_cast(width_); + }; + + template void setWidth(numberType width) + { + static_assert(std::is_same_v || std::is_convertible_v, + "Cannot convert provided argument to "); + + if (std::is_same::value) { + width_ = std::max(static_cast(width), 0.0); + } else { + width_ = safeConvertToDouble(width); + } + } + + template returnType getHeight() const + { + static_assert(std::is_convertible_v, + "Cannot convert to requested return type"); + + return static_cast(height_); + }; + + template void setHeight(numberType height) + { + static_assert(std::is_same_v || std::is_convertible_v, + "Cannot convert provided argument to "); + + if (std::is_same::value) { + height_ = std::max(static_cast(height), 0.0); + } else { + height_ = safeConvertToDouble(height); + } + } + + bool isZero() const; + + friend bool operator==(const Rect &lhs, const Rect &rhs); + friend bool operator!=(const Rect &lhs, const Rect &rhs); +}; +} // namespace OBS diff --git a/frontend/models/SceneCollection.cpp b/frontend/models/SceneCollection.cpp new file mode 100644 index 000000000..3c6557e56 --- /dev/null +++ b/frontend/models/SceneCollection.cpp @@ -0,0 +1,71 @@ +/****************************************************************************** + Copyright (C) 2025 by Patrick Heyer + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +******************************************************************************/ + +#include "SceneCollection.hpp" + +static constexpr std::string_view invalidCoordinateMode = "Invalid coordinate mode provided"; + +namespace OBS { +std::string SceneCollection::getName() const +{ + return name_; +} + +std::string SceneCollection::getFileName() const +{ + return filePath_.filename().u8string(); +} + +std::string SceneCollection::getFileStem() const +{ + return filePath_.stem().u8string(); +} + +std::filesystem::path SceneCollection::getFilePath() const +{ + return filePath_; +} + +std::string SceneCollection::getFilePathString() const +{ + return filePath_.u8string(); +} + +SceneCoordinateMode SceneCollection::getCoordinateMode() const +{ + return coordinateMode_; +} + +void SceneCollection::setCoordinateMode(SceneCoordinateMode newMode) +{ + if (newMode != SceneCoordinateMode::Invalid) { + coordinateMode_ = newMode; + } else { + throw std::invalid_argument(invalidCoordinateMode.data()); + } +} + +Rect SceneCollection::getMigrationResolution() const +{ + return migrationResolution_; +} + +void SceneCollection::setMigrationResolution(Rect newResolution) +{ + migrationResolution_ = newResolution; +} +} // namespace OBS diff --git a/frontend/models/SceneCollection.hpp b/frontend/models/SceneCollection.hpp new file mode 100644 index 000000000..1d7a2060e --- /dev/null +++ b/frontend/models/SceneCollection.hpp @@ -0,0 +1,64 @@ +/****************************************************************************** + Copyright (C) 2025 by Patrick Heyer + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +******************************************************************************/ + +#pragma once + +#include "Rect.hpp" + +#include +#include + +namespace OBS { + +enum class SceneCoordinateMode { Invalid, Absolute, Relative }; + +class SceneCollection { +private: + std::string name_; + std::filesystem::path filePath_; + + SceneCoordinateMode coordinateMode_ = SceneCoordinateMode::Relative; + Rect migrationResolution_; + +public: + SceneCollection() = default; + SceneCollection(const std::string &name, const std::filesystem::path &filePath) + : name_(name), + filePath_(filePath) {}; + + std::string getName() const; + std::string getFileName() const; + std::string getFileStem() const; + std::filesystem::path getFilePath() const; + std::string getFilePathString() const; + + SceneCoordinateMode getCoordinateMode() const; + void setCoordinateMode(SceneCoordinateMode newMode); + + Rect getMigrationResolution() const; + void setMigrationResolution(Rect newResolution); + template + void setMigrationResolution(widthType width, heightType height) + { + this->migrationResolution_ = Rect(width, height); + } + + inline int getVersion() const { return (coordinateMode_ == SceneCoordinateMode::Relative) ? 2 : 1; }; + + bool empty() const { return name_.empty() || filePath_.empty(); } +}; +} // namespace OBS