frontend: Add support loading/saving additional canvases

This commit is contained in:
Dennis Sädtler 2025-01-27 03:07:37 +01:00 committed by Ryan Foster
parent afd7619c98
commit 368185019e
5 changed files with 84 additions and 3 deletions

View File

@ -15,6 +15,7 @@ target_sources(
widgets/OBSBasic.cpp
widgets/OBSBasic.hpp
widgets/OBSBasic_Browser.cpp
widgets/OBSBasic_Canvases.cpp
widgets/OBSBasic_Clipboard.cpp
widgets/OBSBasic_ContextToolbar.cpp
widgets/OBSBasic_Docks.cpp

View File

@ -842,7 +842,7 @@ void OBSBasic::InitOBSCallbacks()
{
ProfileScope("OBSBasic::InitOBSCallbacks");
signalHandlers.reserve(signalHandlers.size() + 9);
signalHandlers.reserve(signalHandlers.size() + 10);
signalHandlers.emplace_back(obs_get_signal_handler(), "source_create", OBSBasic::SourceCreated, this);
signalHandlers.emplace_back(obs_get_signal_handler(), "source_remove", OBSBasic::SourceRemoved, this);
signalHandlers.emplace_back(obs_get_signal_handler(), "source_activate", OBSBasic::SourceActivated, this);
@ -866,6 +866,7 @@ void OBSBasic::InitOBSCallbacks()
Qt::QueuedConnection);
},
this);
signalHandlers.emplace_back(obs_get_signal_handler(), "canvas_remove", OBSBasic::CanvasRemoved, this);
}
#define STARTUP_SEPARATOR "==== Startup complete ==============================================="

View File

@ -23,6 +23,7 @@
#include <OBSApp.hpp>
#include <oauth/Auth.hpp>
#include <utility/BasicOutputHandler.hpp>
#include <utility/OBSCanvas.hpp>
#include <utility/VCamConfig.hpp>
#include <utility/platform.hpp>
#include <utility/undo_stack.hpp>
@ -1108,6 +1109,23 @@ public:
std::optional<SceneCollection> GetSceneCollectionByName(const std::string &collectionName) const;
std::optional<SceneCollection> GetSceneCollectionByFileName(const std::string &fileName) const;
/* -------------------------------------
* MARK: - OBSBasic_Canvases
* -------------------------------------
*/
private:
std::vector<OBS::Canvas> canvases;
static void CanvasRemoved(void *data, calldata_t *params);
public:
const std::vector<OBS::Canvas> &GetCanvases() const noexcept { return canvases; }
const OBS::Canvas &AddCanvas(const std::string &name, obs_video_info *ovi = nullptr, int flags = 0);
public slots:
bool RemoveCanvas(obs_canvas_t *canvas);
/* -------------------------------------
* MARK: - OBSBasic_SceneItems
* -------------------------------------

View File

@ -0,0 +1,47 @@
/******************************************************************************
Copyright (C) 2025 by Dennis Sädtler <saedtler@twitch.tv>
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 <http://www.gnu.org/licenses/>.
******************************************************************************/
#include "OBSBasic.hpp"
void OBSBasic::CanvasRemoved(void *data, calldata_t *params)
{
obs_canvas_t *canvas = static_cast<obs_canvas_t *>(calldata_ptr(params, "canvas"));
QMetaObject::invokeMethod(static_cast<OBSBasic *>(data), "RemoveCanvas", Q_ARG(OBSCanvas, OBSCanvas(canvas)));
}
const OBS::Canvas &OBSBasic::AddCanvas(const std::string &name, obs_video_info *ovi, int flags)
{
OBSCanvas canvas = obs_canvas_create(name.c_str(), ovi, flags);
auto &it = canvases.emplace_back(canvas);
OnEvent(OBS_FRONTEND_EVENT_CANVAS_ADDED);
return it;
}
bool OBSBasic::RemoveCanvas(obs_canvas_t *canvas)
{
if (!canvas)
return false;
auto canvas_it = std::find(std::begin(canvases), std::end(canvases), canvas);
if (canvas_it != std::end(canvases)) {
canvases.erase(canvas_it);
OnEvent(OBS_FRONTEND_EVENT_CANVAS_REMOVED);
return true;
}
return false;
}

View File

@ -808,7 +808,8 @@ static void SaveAudioDevice(const char *name, int channel, obs_data_t *parent, v
static obs_data_t *GenerateSaveData(obs_data_array_t *sceneOrder, obs_data_array_t *quickTransitionData,
int transitionDuration, obs_data_array_t *transitions, OBSScene &scene,
OBSSource &curProgramScene, obs_data_array_t *savedProjectorList)
OBSSource &curProgramScene, obs_data_array_t *savedProjectorList,
obs_data_array_t *savedCanvases)
{
obs_data_t *saveData = obs_data_create();
@ -865,6 +866,7 @@ static obs_data_t *GenerateSaveData(obs_data_array_t *sceneOrder, obs_data_array
obs_data_set_array(saveData, "quick_transitions", quickTransitionData);
obs_data_set_array(saveData, "transitions", transitions);
obs_data_set_array(saveData, "saved_projectors", savedProjectorList);
obs_data_set_array(saveData, "canvases", savedCanvases);
obs_data_array_release(sourcesArray);
obs_data_array_release(groupsArray);
@ -885,8 +887,10 @@ void OBSBasic::Save(SceneCollection &collection)
OBSDataArrayAutoRelease transitions = SaveTransitions();
OBSDataArrayAutoRelease quickTrData = SaveQuickTransitions();
OBSDataArrayAutoRelease savedProjectorList = SaveProjectors();
OBSDataArrayAutoRelease savedCanvases = OBS::Canvas::SaveCanvases(canvases);
OBSDataAutoRelease saveData = GenerateSaveData(sceneOrder, quickTrData, ui->transitionDuration->value(),
transitions, scene, curProgramScene, savedProjectorList);
transitions, scene, curProgramScene, savedProjectorList,
savedCanvases);
obs_data_set_bool(saveData, "preview_locked", ui->preview->Locked());
obs_data_set_bool(saveData, "scaling_enabled", ui->preview->IsFixedScaling());
@ -1171,6 +1175,7 @@ void OBSBasic::LoadData(obs_data_t *data, SceneCollection &collection)
OBSDataArrayAutoRelease sources = obs_data_get_array(data, "sources");
OBSDataArrayAutoRelease groups = obs_data_get_array(data, "groups");
OBSDataArrayAutoRelease transitions = obs_data_get_array(data, "transitions");
OBSDataArrayAutoRelease collection_canvases = obs_data_get_array(data, "canvases");
const char *sceneName = obs_data_get_string(data, "current_scene");
const char *programSceneName = obs_data_get_string(data, "current_program_scene");
const char *transitionName = obs_data_get_string(data, "current_transition");
@ -1207,6 +1212,9 @@ void OBSBasic::LoadData(obs_data_t *data, SceneCollection &collection)
LoadAudioDevice(AUX_AUDIO_3, 5, data);
LoadAudioDevice(AUX_AUDIO_4, 6, data);
if (collection_canvases)
canvases = OBS::Canvas::LoadCanvases(collection_canvases);
if (!sources) {
sources = std::move(groups);
} else {
@ -1525,6 +1533,12 @@ void OBSBasic::ClearSceneData()
obs_enum_scenes(cb, nullptr);
obs_enum_sources(cb, nullptr);
for (const auto &canvas : canvases) {
obs_canvas_enum_scenes(canvas, cb, nullptr);
}
canvases.clear();
OnEvent(OBS_FRONTEND_EVENT_SCENE_COLLECTION_CLEANUP);
undo_s.clear();