mirror of
https://github.com/obsproject/obs-studio.git
synced 2024-09-20 04:42:18 +02:00
544953c870
Implements transitions, and introduces "Studio Mode" which allows live editing of the same or different scenes while preserving what's currently being displayed. Studio Mode offers a number of new features: - The ability to edit different scenes or the same scene without modifying what's currently being displayed (of course) - The ability to set up "quick transitions" with a desired transition and duration that can be assigned hotkeys - The option to create full copies of all sources in the program scene to allow editing of source properties of the same scene live without modifying the output, or (by default) just use references. (Note however that certain sources cannot be duplicated, such as capture sources, media sources, and device sources) - Swap Mode (enabled by default) which swaps the program scene with the preview scene when a transition completes Currently, only non-configurable transitions (transitions without properties) are listed, and the only transitions available as of this writing are fade and cut. In future versions more transitions will be added, such as swipe, stingers, and many other various sort of transitions, and the UI will support being able to add/configure/remove those sort of configurable transitions.
207 lines
5.4 KiB
C++
207 lines
5.4 KiB
C++
/******************************************************************************
|
|
Copyright (C) 2014 by Hugh Bailey <obs.jim@gmail.com>
|
|
|
|
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 <QMessageBox>
|
|
#include "window-basic-main.hpp"
|
|
#include "window-basic-source-select.hpp"
|
|
#include "qt-wrappers.hpp"
|
|
#include "obs-app.hpp"
|
|
|
|
struct AddSourceData {
|
|
obs_source_t *source;
|
|
bool visible;
|
|
};
|
|
|
|
bool OBSBasicSourceSelect::EnumSources(void *data, obs_source_t *source)
|
|
{
|
|
OBSBasicSourceSelect *window = static_cast<OBSBasicSourceSelect*>(data);
|
|
const char *name = obs_source_get_name(source);
|
|
const char *id = obs_source_get_id(source);
|
|
|
|
if (strcmp(id, window->id) == 0)
|
|
window->ui->sourceList->addItem(QT_UTF8(name));
|
|
|
|
return true;
|
|
}
|
|
|
|
void OBSBasicSourceSelect::OBSSourceAdded(void *data, calldata_t *calldata)
|
|
{
|
|
OBSBasicSourceSelect *window = static_cast<OBSBasicSourceSelect*>(data);
|
|
obs_source_t *source = (obs_source_t*)calldata_ptr(calldata, "source");
|
|
|
|
QMetaObject::invokeMethod(window, "SourceAdded",
|
|
Q_ARG(OBSSource, source));
|
|
}
|
|
|
|
void OBSBasicSourceSelect::OBSSourceRemoved(void *data, calldata_t *calldata)
|
|
{
|
|
OBSBasicSourceSelect *window = static_cast<OBSBasicSourceSelect*>(data);
|
|
obs_source_t *source = (obs_source_t*)calldata_ptr(calldata, "source");
|
|
|
|
QMetaObject::invokeMethod(window, "SourceRemoved",
|
|
Q_ARG(OBSSource, source));
|
|
}
|
|
|
|
void OBSBasicSourceSelect::SourceAdded(OBSSource source)
|
|
{
|
|
const char *name = obs_source_get_name(source);
|
|
const char *sourceId = obs_source_get_id(source);
|
|
|
|
if (strcmp(sourceId, id) != 0)
|
|
return;
|
|
|
|
ui->sourceList->addItem(name);
|
|
}
|
|
|
|
void OBSBasicSourceSelect::SourceRemoved(OBSSource source)
|
|
{
|
|
const char *name = obs_source_get_name(source);
|
|
const char *sourceId = obs_source_get_id(source);
|
|
|
|
if (strcmp(sourceId, id) != 0)
|
|
return;
|
|
|
|
QList<QListWidgetItem*> items =
|
|
ui->sourceList->findItems(name, Qt::MatchFixedString);
|
|
|
|
if (!items.count())
|
|
return;
|
|
|
|
delete items[0];
|
|
}
|
|
|
|
static void AddSource(void *_data, obs_scene_t *scene)
|
|
{
|
|
AddSourceData *data = (AddSourceData *)_data;
|
|
obs_sceneitem_t *sceneitem;
|
|
|
|
sceneitem = obs_scene_add(scene, data->source);
|
|
obs_sceneitem_set_visible(sceneitem, data->visible);
|
|
}
|
|
|
|
static void AddExisting(const char *name, const bool visible)
|
|
{
|
|
OBSBasic *main = reinterpret_cast<OBSBasic*>(App()->GetMainWindow());
|
|
OBSScene scene = main->GetCurrentScene();
|
|
if (!scene)
|
|
return;
|
|
|
|
obs_source_t *source = obs_get_source_by_name(name);
|
|
if (source) {
|
|
AddSourceData data;
|
|
data.source = source;
|
|
data.visible = visible;
|
|
obs_scene_atomic_update(scene, AddSource, &data);
|
|
|
|
obs_source_release(source);
|
|
}
|
|
}
|
|
|
|
bool AddNew(QWidget *parent, const char *id, const char *name,
|
|
const bool visible, OBSSource &newSource)
|
|
{
|
|
OBSBasic *main = reinterpret_cast<OBSBasic*>(App()->GetMainWindow());
|
|
OBSScene scene = main->GetCurrentScene();
|
|
bool success = false;
|
|
if (!scene)
|
|
return false;
|
|
|
|
obs_source_t *source = obs_get_source_by_name(name);
|
|
if (source) {
|
|
QMessageBox::information(parent,
|
|
QTStr("NameExists.Title"),
|
|
QTStr("NameExists.Text"));
|
|
|
|
} else {
|
|
source = obs_source_create(id, name, NULL, nullptr);
|
|
|
|
if (source) {
|
|
AddSourceData data;
|
|
data.source = source;
|
|
data.visible = visible;
|
|
obs_scene_atomic_update(scene, AddSource, &data);
|
|
|
|
newSource = source;
|
|
|
|
success = true;
|
|
}
|
|
}
|
|
|
|
obs_source_release(source);
|
|
return success;
|
|
}
|
|
|
|
void OBSBasicSourceSelect::on_buttonBox_accepted()
|
|
{
|
|
bool useExisting = ui->selectExisting->isChecked();
|
|
bool visible = ui->sourceVisible->isChecked();
|
|
|
|
if (useExisting) {
|
|
QListWidgetItem *item = ui->sourceList->currentItem();
|
|
if (!item)
|
|
return;
|
|
|
|
AddExisting(QT_TO_UTF8(item->text()), visible);
|
|
} else {
|
|
if (ui->sourceName->text().isEmpty()) {
|
|
QMessageBox::information(this,
|
|
QTStr("NoNameEntered.Title"),
|
|
QTStr("NoNameEntered.Text"));
|
|
return;
|
|
}
|
|
|
|
if (!AddNew(this, id, QT_TO_UTF8(ui->sourceName->text()),
|
|
visible, newSource))
|
|
return;
|
|
}
|
|
|
|
done(DialogCode::Accepted);
|
|
}
|
|
|
|
void OBSBasicSourceSelect::on_buttonBox_rejected()
|
|
{
|
|
done(DialogCode::Rejected);
|
|
}
|
|
|
|
OBSBasicSourceSelect::OBSBasicSourceSelect(OBSBasic *parent, const char *id_)
|
|
: QDialog (parent),
|
|
ui (new Ui::OBSBasicSourceSelect),
|
|
id (id_)
|
|
{
|
|
ui->setupUi(this);
|
|
|
|
ui->sourceList->setAttribute(Qt::WA_MacShowFocusRect, false);
|
|
|
|
QString placeHolderText{QT_UTF8(obs_source_get_display_name(id))};
|
|
|
|
QString text{placeHolderText};
|
|
int i = 1;
|
|
obs_source_t *source = nullptr;
|
|
while ((source = obs_get_source_by_name(QT_TO_UTF8(text)))) {
|
|
obs_source_release(source);
|
|
text = QString("%1 %2").arg(placeHolderText).arg(i++);
|
|
}
|
|
|
|
ui->sourceName->setText(text);
|
|
ui->sourceName->setFocus(); //Fixes deselect of text.
|
|
ui->sourceName->selectAll();
|
|
|
|
installEventFilter(CreateShortcutFilter());
|
|
|
|
obs_enum_sources(EnumSources, this);
|
|
}
|