commit
96f00cdffc
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue