diff --git a/UI/data/locale/en-US.ini b/UI/data/locale/en-US.ini index 802859d4b6e49cbd34bfde14bb3b344899b51d5a..3c9075265171707b766541352ce59b067cfb095a 100644 --- a/UI/data/locale/en-US.ini +++ b/UI/data/locale/en-US.ini @@ -415,6 +415,7 @@ Basic.Settings.General.KeepRecordingWhenStreamStops="Keep recording when stream Basic.Settings.General.SysTrayEnabled="Enable system tray icon" Basic.Settings.General.SysTrayWhenStarted="Minimize to system tray when started" Basic.Settings.General.SystemTrayHideMinimize="Hide to system tray instead of minimize to task bar" +Basic.Settings.General.SaveProjectors="Save projectors on exit" # basic mode 'stream' settings Basic.Settings.Stream="Stream" diff --git a/UI/forms/OBSBasicSettings.ui b/UI/forms/OBSBasicSettings.ui index ea8a1ff5a803866ab65f7699adb3304500a8f3e6..502d6961f92deebd1306f4d8f0f78c1fc1a287c3 100644 --- a/UI/forms/OBSBasicSettings.ui +++ b/UI/forms/OBSBasicSettings.ui @@ -185,21 +185,21 @@ - + Basic.Settings.General.RecordWhenStreaming - + Basic.Settings.General.SysTrayEnabled - + false @@ -209,7 +209,7 @@ - + false @@ -219,14 +219,14 @@ - + Qt::Horizontal - + true @@ -326,7 +326,7 @@ - + false @@ -343,6 +343,13 @@ + + + + Basic.Settings.General.SaveProjectors + + + @@ -2912,8 +2919,8 @@ 0 0 - 800 - 69 + 98 + 28 @@ -4204,6 +4211,16 @@ toggled(bool) systemTrayAlways setEnabled(bool) + + + 20 + 20 + + + 20 + 20 + + diff --git a/UI/obs-app.cpp b/UI/obs-app.cpp index 5b2d3808086b45642c9feb6ca8a4b6938d0e44b4..6cedde784a22e2817e6d9ed2b0267ec4fc87cfba 100644 --- a/UI/obs-app.cpp +++ b/UI/obs-app.cpp @@ -392,6 +392,8 @@ bool OBSApp::InitGlobalConfigDefaults() "SysTrayEnabled", true); config_set_default_bool(globalConfig, "BasicWindow", "SysTrayWhenStarted", false); + config_set_default_bool(globalConfig, "BasicWindow", + "SaveProjectors", false); config_set_default_bool(globalConfig, "BasicWindow", "ShowTransitions", true); config_set_default_bool(globalConfig, "BasicWindow", diff --git a/UI/window-basic-main-scene-collections.cpp b/UI/window-basic-main-scene-collections.cpp index 322e785cb6991d1a90ecce682c93a677e7174183..a7154419b2e2d5e99d37e2e360687a37452f14d3 100644 --- a/UI/window-basic-main-scene-collections.cpp +++ b/UI/window-basic-main-scene-collections.cpp @@ -222,6 +222,9 @@ void OBSBasic::RefreshSceneCollections() EnumSceneCollections(addCollection); ui->actionRemoveSceneCollection->setEnabled(count > 1); + + OBSBasic *main = reinterpret_cast(App()->GetMainWindow()); + main->OpenSavedProjectors(); } void OBSBasic::on_actionNewSceneCollection_triggered() diff --git a/UI/window-basic-main.cpp b/UI/window-basic-main.cpp index 1c9853f3a4ed5cd18ffa857f5babb82a0714c2b9..9af9ca96735eeaade384b011aabb982902bad82a 100644 --- a/UI/window-basic-main.cpp +++ b/UI/window-basic-main.cpp @@ -123,6 +123,9 @@ OBSBasic::OBSBasic(QWidget *parent) : OBSMainWindow (parent), ui (new Ui::OBSBasic) { + projectorArray.resize(10, ""); + previewProjectorArray.resize(10, 0); + setAcceptDrops(true); ui->setupUi(this); @@ -262,7 +265,9 @@ static void SaveAudioDevice(const char *name, int channel, obs_data_t *parent, 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) + OBSScene &scene, OBSSource &curProgramScene, + obs_data_array_t *savedProjectorList, + obs_data_array_t *savedPreviewProjectorList) { obs_data_t *saveData = obs_data_create(); @@ -303,6 +308,9 @@ static obs_data_t *GenerateSaveData(obs_data_array_t *sceneOrder, obs_data_set_array(saveData, "sources", sourcesArray); 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, "saved_preview_projectors", + savedPreviewProjectorList); obs_data_array_release(sourcesArray); obs_data_set_string(saveData, "current_transition", @@ -360,6 +368,36 @@ obs_data_array_t *OBSBasic::SaveSceneListOrder() return sceneOrder; } +obs_data_array_t *OBSBasic::SaveProjectors() +{ + obs_data_array_t *saveProjector = obs_data_array_create(); + + for (size_t i = 0; i < projectorArray.size(); i++) { + obs_data_t *data = obs_data_create(); + obs_data_set_string(data, "saved_projectors", + projectorArray.at(i).c_str()); + obs_data_array_push_back(saveProjector, data); + obs_data_release(data); + } + + return saveProjector; +} + +obs_data_array_t *OBSBasic::SavePreviewProjectors() +{ + obs_data_array_t *saveProjector = obs_data_array_create(); + + for (size_t i = 0; i < previewProjectorArray.size(); i++) { + obs_data_t *data = obs_data_create(); + obs_data_set_int(data, "saved_preview_projectors", + previewProjectorArray.at(i)); + obs_data_array_push_back(saveProjector, data); + obs_data_release(data); + } + + return saveProjector; +} + void OBSBasic::Save(const char *file) { OBSScene scene = GetCurrentScene(); @@ -370,9 +408,12 @@ void OBSBasic::Save(const char *file) obs_data_array_t *sceneOrder = SaveSceneListOrder(); obs_data_array_t *transitions = SaveTransitions(); obs_data_array_t *quickTrData = SaveQuickTransitions(); + obs_data_array_t *savedProjectorList = SaveProjectors(); + obs_data_array_t *savedPreviewProjectorList = SavePreviewProjectors(); obs_data_t *saveData = GenerateSaveData(sceneOrder, quickTrData, ui->transitionDuration->value(), transitions, - scene, curProgramScene); + scene, curProgramScene, savedProjectorList, + savedPreviewProjectorList); obs_data_set_bool(saveData, "preview_locked", ui->preview->Locked()); obs_data_set_int(saveData, "scaling_mode", @@ -392,6 +433,8 @@ void OBSBasic::Save(const char *file) obs_data_array_release(sceneOrder); obs_data_array_release(quickTrData); obs_data_array_release(transitions); + obs_data_array_release(savedProjectorList); + obs_data_array_release(savedPreviewProjectorList); } static void LoadAudioDevice(const char *name, int channel, obs_data_t *parent) @@ -491,6 +534,32 @@ void OBSBasic::LoadSceneListOrder(obs_data_array_t *array) } } +void OBSBasic::LoadSavedProjectors(obs_data_array_t *array) +{ + size_t num = obs_data_array_count(array); + + for (size_t i = 0; i < num; i++) { + obs_data_t *data = obs_data_array_item(array, i); + projectorArray.at(i) = obs_data_get_string(data, + "saved_projectors"); + + obs_data_release(data); + } +} + +void OBSBasic::LoadSavedPreviewProjectors(obs_data_array_t *array) +{ + size_t num = obs_data_array_count(array); + + for (size_t i = 0; i < num; i++) { + obs_data_t *data = obs_data_array_item(array, i); + previewProjectorArray.at(i) = obs_data_get_int(data, + "saved_preview_projectors"); + + obs_data_release(data); + } +} + static void LogFilter(obs_source_t*, obs_source_t *filter, void *v_val) { const char *name = obs_source_get_name(filter); @@ -618,6 +687,23 @@ void OBSBasic::Load(const char *file) ui->transitionDuration->setValue(newDuration); SetTransition(curTransition); + obs_data_array_t *savedProjectors = obs_data_get_array(data, + "saved_projectors"); + + if (savedProjectors) + LoadSavedProjectors(savedProjectors); + + obs_data_array_release(savedProjectors); + + obs_data_array_t *savedPreviewProjectors = obs_data_get_array(data, + "saved_preview_projectors"); + + if (savedPreviewProjectors) + LoadSavedPreviewProjectors(savedPreviewProjectors); + + obs_data_array_release(savedPreviewProjectors); + + retryScene: curScene = obs_get_source_by_name(sceneName); curProgramScene = obs_get_source_by_name(programSceneName); @@ -1259,6 +1345,8 @@ void OBSBasic::OBSInit() ui->mainSplitter->setSizes(defSizes); SystemTray(true); + + OpenSavedProjectors(); } void OBSBasic::InitHotkeys() @@ -1891,6 +1979,14 @@ void OBSBasic::RenameSources(QString newName, QString prevName) volumes[i]->SetName(newName); } + std::string newText = newName.toUtf8().constData(); + std::string prevText = prevName.toUtf8().constData(); + + for (size_t j = 0; j < projectorArray.size(); j++) { + if (projectorArray.at(j) == prevText) + projectorArray.at(j) = newText; + } + SaveProject(); } @@ -4751,15 +4847,30 @@ void OBSBasic::NudgeRight() {Nudge(1, MoveDir::Right);} void OBSBasic::OpenProjector(obs_source_t *source, int monitor) { /* seriously? 10 monitors? */ - if (monitor > 9) + if (monitor > 9 || monitor > QGuiApplication::screens().size() - 1) return; + bool isPreview = false; + + if (source == nullptr) + isPreview = true; + delete projectors[monitor]; projectors[monitor].clear(); + RemoveSavedProjectors(monitor); + OBSProjector *projector = new OBSProjector(nullptr, source); - projector->Init(monitor); + const char *name = obs_source_get_name(source); + + if (isPreview) { + previewProjectorArray.at((size_t)monitor) = 1; + } else { + projectorArray.at((size_t)monitor) = name; + } + + projector->Init(monitor); projectors[monitor] = projector; } @@ -4789,6 +4900,42 @@ void OBSBasic::OpenSceneProjector() OpenProjector(obs_scene_get_source(scene), monitor); } +void OBSBasic::OpenSavedProjectors() +{ + bool projectorSave = config_get_bool(GetGlobalConfig(), + "BasicWindow", "SaveProjectors"); + + if (projectorSave) { + for (size_t i = 0; i < projectorArray.size(); i++) { + if (projectorArray.at(i).empty() == false) { + OBSSource source = obs_get_source_by_name( + projectorArray.at(i).c_str()); + + if (!source) { + RemoveSavedProjectors((int)i); + obs_source_release(source); + continue; + } + + OpenProjector(source, (int)i); + obs_source_release(source); + } + } + + for (size_t i = 0; i < previewProjectorArray.size(); i++) { + if (previewProjectorArray.at(i) == 1) { + OpenProjector(nullptr, (int)i); + } + } + } +} + +void OBSBasic::RemoveSavedProjectors(int monitor) +{ + previewProjectorArray.at((size_t)monitor) = 0; + projectorArray.at((size_t)monitor) = ""; +} + void OBSBasic::UpdateTitleBar() { stringstream name; diff --git a/UI/window-basic-main.hpp b/UI/window-basic-main.hpp index ad1238a13e3eb3d0e1e8bf50af4c8e673297339b..85afd1c44a831e3de067990c09284e16bd3aba7b 100644 --- a/UI/window-basic-main.hpp +++ b/UI/window-basic-main.hpp @@ -111,6 +111,9 @@ private: std::vector signalHandlers; + std::vector projectorArray; + std::vector previewProjectorArray; + bool loaded = false; long disableSaving = 1; bool projectChanged = false; @@ -331,6 +334,13 @@ private: QList visDlgPositions; + obs_data_array_t *SaveProjectors(); + void LoadSavedProjectors(obs_data_array_t *savedProjectors); + + obs_data_array_t *SavePreviewProjectors(); + void LoadSavedPreviewProjectors( + obs_data_array_t *savedPreviewProjectors); + public slots: void StartStreaming(); void StopStreaming(); @@ -482,6 +492,9 @@ public: void SystemTrayInit(); void SystemTray(bool firstStarted); + void OpenSavedProjectors(); + void RemoveSavedProjectors(int monitor); + protected: virtual void closeEvent(QCloseEvent *event) override; virtual void changeEvent(QEvent *event) override; diff --git a/UI/window-basic-settings.cpp b/UI/window-basic-settings.cpp index 5c43567d3ae718990ceca8cbadb8088aa06fb49c..00ea011c03fe1fe90a486ceb1927fb8728e09f2b 100644 --- a/UI/window-basic-settings.cpp +++ b/UI/window-basic-settings.cpp @@ -282,6 +282,7 @@ OBSBasicSettings::OBSBasicSettings(QWidget *parent) HookWidget(ui->systemTrayEnabled, CHECK_CHANGED, GENERAL_CHANGED); HookWidget(ui->systemTrayWhenStarted,CHECK_CHANGED, GENERAL_CHANGED); HookWidget(ui->systemTrayAlways, CHECK_CHANGED, GENERAL_CHANGED); + HookWidget(ui->saveProjectors, CHECK_CHANGED, GENERAL_CHANGED); HookWidget(ui->snappingEnabled, CHECK_CHANGED, GENERAL_CHANGED); HookWidget(ui->screenSnapping, CHECK_CHANGED, GENERAL_CHANGED); HookWidget(ui->centerSnapping, CHECK_CHANGED, GENERAL_CHANGED); @@ -896,6 +897,10 @@ void OBSBasicSettings::LoadGeneralSettings() "BasicWindow", "SysTrayMinimizeToTray"); ui->systemTrayAlways->setChecked(systemTrayAlways); + bool saveProjectors = config_get_bool(GetGlobalConfig(), + "BasicWindow", "SaveProjectors"); + ui->saveProjectors->setChecked(saveProjectors); + bool snappingEnabled = config_get_bool(GetGlobalConfig(), "BasicWindow", "SnappingEnabled"); ui->snappingEnabled->setChecked(snappingEnabled); @@ -2351,6 +2356,11 @@ void OBSBasicSettings::SaveGeneralSettings() config_set_bool(GetGlobalConfig(), "BasicWindow", "SysTrayMinimizeToTray", ui->systemTrayAlways->isChecked()); + + if (WidgetChanged(ui->saveProjectors)) + config_set_bool(GetGlobalConfig(), "BasicWindow", + "SaveProjectors", + ui->saveProjectors->isChecked()); } void OBSBasicSettings::SaveStream1Settings() diff --git a/UI/window-projector.cpp b/UI/window-projector.cpp index 3c9f6b1876d7febd4012edc92a72bef774b284ec..e894897775e21848b68d36b60f9ff44954612986 100644 --- a/UI/window-projector.cpp +++ b/UI/window-projector.cpp @@ -53,6 +53,7 @@ OBSProjector::~OBSProjector() void OBSProjector::Init(int monitor) { QScreen *screen = QGuiApplication::screens()[monitor]; + setGeometry(screen->geometry()); bool alwaysOnTop = config_get_bool(GetGlobalConfig(), @@ -70,6 +71,8 @@ void OBSProjector::Init(int monitor) addAction(action); connect(action, SIGNAL(triggered()), this, SLOT(EscapeTriggered())); + + savedMonitor = monitor; } void OBSProjector::OBSRender(void *data, uint32_t cx, uint32_t cy) @@ -114,6 +117,7 @@ void OBSProjector::OBSRender(void *data, uint32_t cx, uint32_t cy) void OBSProjector::OBSSourceRemoved(void *data, calldata_t *params) { OBSProjector *window = reinterpret_cast(data); + window->deleteLater(); UNUSED_PARAMETER(params); @@ -132,5 +136,8 @@ void OBSProjector::mousePressEvent(QMouseEvent *event) void OBSProjector::EscapeTriggered() { + OBSBasic *main = reinterpret_cast(App()->GetMainWindow()); + main->RemoveSavedProjectors(savedMonitor); + deleteLater(); } diff --git a/UI/window-projector.hpp b/UI/window-projector.hpp index f623f9e3c178a906b0cde5d89442f562285c3f71..394d2706f993eb069bb2e3990dbc9b25c98a1c9e 100644 --- a/UI/window-projector.hpp +++ b/UI/window-projector.hpp @@ -2,6 +2,7 @@ #include #include "qt-display.hpp" +#include "window-basic-main.hpp" class QMouseEvent; @@ -17,6 +18,8 @@ private: void mousePressEvent(QMouseEvent *event) override; + int savedMonitor = 0; + private slots: void EscapeTriggered();