Merge pull request #2141 from cg2121/t-bar

Add t-bar to studio mode
master
Jim 2019-12-27 17:48:23 -08:00 committed by GitHub
commit 96f00cdffc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 269 additions and 11 deletions

View File

@ -1049,3 +1049,36 @@ SceneTree#scenes {
* [themeID="replayIconSmall"] {
qproperty-icon: url(./Dark/save.svg);
}
/* Studio Mode T-Bar */
QSlider[themeID="tBarSlider"] {
height: 80px;
}
QSlider::groove:horizontal[themeID="tBarSlider"] {
height: 5px;
margin: 0 12px;
background-color: QLinearGradient(x1: 0, y1: 0, x2: 0, y2: 1,
stop: 0 rgb(31,30,31),
stop: 0.75 rgb(50, 49, 50));
border: none;
border-radius: 2px;
}
QSlider::sub-page:horizontal[themeID="tBarSlider"] {
height: 5px;
margin: 0 12px;
background-color: QLinearGradient(x1: 0, y1: 0, x2: 0, y2: 1,
stop: 0 rgb(31,30,31),
stop: 0.75 rgb(50, 49, 50));
border: none;
border-radius: 2px;
}
QSlider::handle:horizontal[themeID="tBarSlider"] {
background-color: #d2d2d2;
width: 25px;
height: 80px;
margin: -24px -12px;
}

View File

@ -810,3 +810,28 @@ SceneTree {
* [themeID="replayIconSmall"] {
qproperty-icon: url(./Dark/save.svg);
}
/* Studio Mode T-Bar */
QSlider[themeID="tBarSlider"] {
height: 80px;
}
QSlider::groove:horizontal[themeID="tBarSlider"] {
border: 1px solid #4c4c4c;
height: 5px;
background: rgb(31,30,31);;
margin: 0 12px;
}
QSlider::sub-page:horizontal[themeID="tBarSlider"] {
background: rgb(31,30,31);;
border: 1px solid #4c4c4c;
}
QSlider::handle:horizontal[themeID="tBarSlider"] {
background-color: #d2d2d2;
width: 25px;
height: 80px;
margin: -24px -12px;
}

View File

@ -1373,3 +1373,36 @@ SceneTree#scenes {
* [themeID="replayIconSmall"] {
qproperty-icon: url(./Dark/save.svg);
}
/* Studio Mode T-Bar */
QSlider[themeID="tBarSlider"] {
height: 80px;
}
QSlider::groove:horizontal[themeID="tBarSlider"] {
height: 5px;
margin: 0 12px;
background-color: QLinearGradient(x1: 1, y1: 0, x2: 0, y2: 0,
stop: 0 rgb(35, 38, 41), /* Dark Gray */
stop: 0.75 rgb(50, 49, 50));
border: none;
border-radius: 2px;
}
QSlider::sub-page:horizontal[themeID="tBarSlider"] {
height: 5px;
margin: 0 12px;
background-color: QLinearGradient(x1: 1, y1: 0, x2: 0, y2: 0,
stop: 0 rgb(35, 38, 41), /* Dark Gray */
stop: 0.75 rgb(50, 49, 50));
border: none;
border-radius: 2px;
}
QSlider::handle:horizontal[themeID="tBarSlider"] {
background-color: #d2d2d2;
width: 25px;
height: 80px;
margin: -24px -12px;
}

View File

@ -241,3 +241,29 @@ SceneTree {
* [themeID="replayIconSmall"] {
qproperty-icon: url(:res/images/save.svg);
}
/* Studio Mode T-Bar */
QSlider[themeID="tBarSlider"] {
height: 80px;
}
QSlider::groove:horizontal[themeID="tBarSlider"] {
border: 1px solid #4c4c4c;
height: 5px;
background: #DCD9D7;
margin: 0 12px;
}
QSlider::sub-page:horizontal[themeID="tBarSlider"] {
background: #DCD9D7;
border: 1px solid #4c4c4c;
}
QSlider::handle:horizontal[themeID="tBarSlider"] {
background-color: #f3f3f3;
border: 1px solid #4c4c4c;
width: 25px;
height: 80px;
margin: -24px -12px;
}

View File

@ -306,7 +306,7 @@ void OBSBasic::TransitionFullyStopped()
void OBSBasic::TransitionToScene(OBSSource source, bool force,
bool quickTransition, int quickDuration,
bool black)
bool black, bool manual)
{
obs_scene_t *scene = obs_scene_from_source(source);
bool usingPreviewProgram = IsPreviewProgramMode();
@ -316,7 +316,8 @@ void OBSBasic::TransitionToScene(OBSSource source, bool force,
OBSWeakSource lastProgramScene;
if (usingPreviewProgram) {
lastProgramScene = programScene;
if (!tBarActive)
lastProgramScene = programScene;
programScene = OBSGetWeakRef(source);
if (swapScenesMode && !force && !black) {
@ -341,12 +342,16 @@ void OBSBasic::TransitionToScene(OBSSource source, bool force,
OBSSource transition = obs_get_output_source(0);
obs_source_release(transition);
bool stillTransitioning = obs_transition_get_time(transition) < 1.0f;
float t = obs_transition_get_time(transition);
bool stillTransitioning = (!tBarActive && t < 1.0f) ||
(tBarActive && t > 0.0f) || tBarDown;
// If actively transitioning, block new transitions from starting
if (usingPreviewProgram && stillTransitioning)
goto cleanup;
tBarActive = false;
if (force) {
obs_transition_set(transition, source);
if (api)
@ -390,8 +395,13 @@ void OBSBasic::TransitionToScene(OBSSource source, bool force,
if (quickTransition)
duration = quickDuration;
bool success = obs_transition_start(
transition, OBS_TRANSITION_MODE_AUTO, duration, source);
enum obs_transition_mode mode =
manual ? OBS_TRANSITION_MODE_MANUAL
: OBS_TRANSITION_MODE_AUTO;
bool success = obs_transition_start(transition, mode, duration,
source);
if (!success)
TransitionFullyStopped();
}
@ -444,6 +454,8 @@ void OBSBasic::SetTransition(OBSSource transition)
ui->transitionRemove->setEnabled(configurable);
ui->transitionProps->setEnabled(configurable);
EnableTBar();
if (api)
api->on_event(OBS_FRONTEND_EVENT_TRANSITION_CHANGED);
}
@ -765,6 +777,10 @@ void OBSBasic::TransitionClicked()
TransitionToScene(GetCurrentScene());
}
#define T_BAR_PRECISION 1024
#define T_BAR_PRECISION_F ((float)T_BAR_PRECISION)
#define T_BAR_CLAMP (T_BAR_PRECISION / 10)
void OBSBasic::CreateProgramOptions()
{
programOptions = new QWidget();
@ -796,9 +812,19 @@ void OBSBasic::CreateProgramOptions()
mainButtonLayout->addWidget(transitionButton);
mainButtonLayout->addWidget(configTransitions);
tBar = new QSlider(Qt::Horizontal);
tBar->setMinimum(0);
tBar->setMaximum(T_BAR_PRECISION - 1);
tBar->setProperty("themeID", "tBarSlider");
connect(tBar, SIGNAL(sliderMoved(int)), this, SLOT(TBarChanged(int)));
connect(tBar, SIGNAL(sliderReleased()), this, SLOT(TBarReleased()));
layout->addStretch(0);
layout->addLayout(mainButtonLayout);
layout->addLayout(quickTransitions);
layout->addWidget(tBar);
layout->addStretch(0);
programOptions->setLayout(layout);
@ -871,6 +897,58 @@ void OBSBasic::CreateProgramOptions()
connect(configTransitions, &QAbstractButton::clicked, onConfig);
}
void OBSBasic::TBarReleased()
{
int val = tBar->value();
if ((tBar->maximum() - val) <= T_BAR_CLAMP) {
obs_transition_set_manual_time(GetCurrentTransition(), 1.0f);
tBar->blockSignals(true);
tBar->setValue(0);
tBar->blockSignals(false);
tBarActive = false;
} else if (val <= T_BAR_CLAMP) {
obs_transition_set_manual_time(GetCurrentTransition(), 0.0f);
tBar->blockSignals(true);
tBar->setValue(0);
tBar->blockSignals(false);
}
tBarDown = false;
}
void OBSBasic::TBarChanged(int value)
{
if (!tBarDown) {
obs_transition_set_manual_torque(GetCurrentTransition(), 8.0f,
0.05f);
TransitionToScene(GetCurrentSceneSource(), false, false, false,
0, true);
tBarActive = true;
tBarDown = true;
}
obs_transition_set_manual_time(GetCurrentTransition(),
(float)value / T_BAR_PRECISION_F);
}
void OBSBasic::EnableTBar()
{
if (!previewProgramMode)
return;
const char *id = obs_source_get_id(GetCurrentTransition());
if (!id || strcmp(id, "cut_transition") == 0 ||
strcmp(id, "obs_stinger_transition") == 0) {
tBar->setValue(0);
tBar->setEnabled(false);
} else {
tBar->setEnabled(true);
}
}
void OBSBasic::on_modeSwitch_clicked()
{
SetPreviewProgramMode(!IsPreviewProgramMode());
@ -1137,6 +1215,8 @@ void OBSBasic::QuickTransitionChange()
qt->source = GetTransitionComboItem(ui->transitions, trIdx);
ResetQuickTransitionText(qt);
}
EnableTBar();
}
void OBSBasic::QuickTransitionChangeDuration(int value)
@ -1258,6 +1338,7 @@ void OBSBasic::SetPreviewProgramMode(bool enabled)
CreateProgramDisplay();
CreateProgramOptions();
EnableTBar();
OBSScene curScene = GetCurrentScene();

View File

@ -502,6 +502,11 @@ private:
QIcon GetBrowserIcon() const;
QIcon GetDefaultIcon() const;
QSlider *tBar;
bool tBarActive = false;
bool tBarDown = false;
void EnableTBar();
public slots:
void DeferSaveBegin();
void DeferSaveEnd();
@ -541,7 +546,8 @@ public slots:
void TransitionToScene(OBSScene scene, bool force = false);
void TransitionToScene(OBSSource scene, bool force = false,
bool quickTransition = false,
int quickDuration = 0, bool black = false);
int quickDuration = 0, bool black = false,
bool manual = false);
void SetCurrentScene(OBSSource scene, bool force = false);
bool AddSceneCollection(bool create_new,
@ -645,6 +651,9 @@ private slots:
void SetSceneIcon(const QIcon &icon);
void SetDefaultIcon(const QIcon &icon);
void TBarChanged(int value);
void TBarReleased();
private:
/* OBS Callbacks */
static void SceneReordered(void *data, calldata_t *params);

View File

@ -700,6 +700,10 @@ struct obs_source {
gs_texrender_t *transition_texrender[2];
pthread_mutex_t transition_mutex;
obs_source_t *transition_sources[2];
float transition_manual_clamp;
float transition_manual_torque;
float transition_manual_target;
float transition_manual_val;
bool transitioning_video;
bool transitioning_audio;
bool transition_source_active[2];
@ -727,7 +731,7 @@ extern bool obs_source_init_context(struct obs_source *source,
extern bool obs_transition_init(obs_source_t *transition);
extern void obs_transition_free(obs_source_t *transition);
extern void obs_transition_tick(obs_source_t *transition);
extern void obs_transition_tick(obs_source_t *transition, float t);
extern void obs_transition_enum_sources(obs_source_t *transition,
obs_source_enum_proc_t enum_callback,
void *param);

View File

@ -16,6 +16,7 @@
******************************************************************************/
#include "obs-internal.h"
#include "graphics/math-extra.h"
#define lock_transition(transition) \
pthread_mutex_lock(&transition->transition_mutex);
@ -203,11 +204,24 @@ static void recalculate_transition_size(obs_source_t *transition)
transition->transition_actual_cy = cy;
}
void obs_transition_tick(obs_source_t *transition)
void obs_transition_tick(obs_source_t *transition, float t)
{
recalculate_transition_size(transition);
recalculate_transition_matrices(transition);
if (transition->transition_mode == OBS_TRANSITION_MODE_MANUAL) {
if (transition->transition_manual_torque == 0.0f) {
transition->transition_manual_val =
transition->transition_manual_target;
} else {
transition->transition_manual_val = calc_torquef(
transition->transition_manual_val,
transition->transition_manual_target,
transition->transition_manual_torque,
transition->transition_manual_clamp, t);
}
}
if (trylock_textures(transition) == 0) {
gs_texrender_reset(transition->transition_texrender[0]);
gs_texrender_reset(transition->transition_texrender[1]);
@ -351,6 +365,7 @@ bool obs_transition_start(obs_source_t *transition,
bool active;
bool same_as_source;
bool same_as_dest;
bool same_mode;
if (!transition_valid(transition, "obs_transition_start"))
return false;
@ -358,11 +373,21 @@ bool obs_transition_start(obs_source_t *transition,
lock_transition(transition);
same_as_source = dest == transition->transition_sources[0];
same_as_dest = dest == transition->transition_sources[1];
same_mode = mode == transition->transition_mode;
active = transition_active(transition);
unlock_transition(transition);
if (same_as_source && !active)
return false;
if (active && mode == OBS_TRANSITION_MODE_MANUAL && same_mode &&
same_as_dest)
return true;
lock_transition(transition);
transition->transition_mode = mode;
transition->transition_manual_val = 0.0f;
transition->transition_manual_target = 0.0f;
unlock_transition(transition);
if (transition->info.transition_start)
transition->info.transition_start(transition->context.data);
@ -389,11 +414,25 @@ bool obs_transition_start(obs_source_t *transition,
recalculate_transition_size(transition);
recalculate_transition_matrices(transition);
/* TODO: Add mode */
UNUSED_PARAMETER(mode);
return true;
}
void obs_transition_set_manual_torque(obs_source_t *transition, float torque,
float clamp)
{
lock_transition(transition);
transition->transition_manual_torque = torque;
transition->transition_manual_clamp = clamp;
unlock_transition(transition);
}
void obs_transition_set_manual_time(obs_source_t *transition, float t)
{
lock_transition(transition);
transition->transition_manual_target = t;
unlock_transition(transition);
}
void obs_transition_set(obs_source_t *transition, obs_source_t *source)
{
obs_source_t *s[2];
@ -429,6 +468,9 @@ void obs_transition_set(obs_source_t *transition, obs_source_t *source)
static float calc_time(obs_source_t *transition, uint64_t ts)
{
if (transition->transition_mode == OBS_TRANSITION_MODE_MANUAL)
return transition->transition_manual_val;
uint64_t end;
if (ts <= transition->transition_start_time)

View File

@ -1067,7 +1067,7 @@ void obs_source_video_tick(obs_source_t *source, float seconds)
return;
if (source->info.type == OBS_SOURCE_TYPE_TRANSITION)
obs_transition_tick(source);
obs_transition_tick(source, seconds);
if ((source->info.output_flags & OBS_SOURCE_ASYNC) != 0)
async_tick(source);

View File

@ -1333,6 +1333,7 @@ EXPORT obs_source_t *obs_transition_get_active_source(obs_source_t *transition);
enum obs_transition_mode {
OBS_TRANSITION_MODE_AUTO,
OBS_TRANSITION_MODE_MANUAL,
};
EXPORT bool obs_transition_start(obs_source_t *transition,
@ -1341,6 +1342,10 @@ EXPORT bool obs_transition_start(obs_source_t *transition,
EXPORT void obs_transition_set(obs_source_t *transition, obs_source_t *source);
EXPORT void obs_transition_set_manual_time(obs_source_t *transition, float t);
EXPORT void obs_transition_set_manual_torque(obs_source_t *transition,
float torque, float clamp);
enum obs_transition_scale_type {
OBS_TRANSITION_SCALE_MAX_ONLY,
OBS_TRANSITION_SCALE_ASPECT,