UI, libobs: Add ability to lock individual scene items
Adds a lock checkbox to allow the user to lock a specific scene item. Closes jp9000/obs-studio#949
This commit is contained in:
parent
5c2328cca2
commit
fce078d997
@ -161,6 +161,7 @@ set(obs_SOURCES
|
||||
adv-audio-control.cpp
|
||||
item-widget-helpers.cpp
|
||||
visibility-checkbox.cpp
|
||||
locked-checkbox.cpp
|
||||
vertical-scroll-area.cpp
|
||||
visibility-item-widget.cpp
|
||||
slider-absoluteset-style.cpp
|
||||
@ -208,6 +209,7 @@ set(obs_HEADERS
|
||||
adv-audio-control.hpp
|
||||
item-widget-helpers.hpp
|
||||
visibility-checkbox.hpp
|
||||
locked-checkbox.hpp
|
||||
vertical-scroll-area.hpp
|
||||
visibility-item-widget.hpp
|
||||
slider-absoluteset-style.hpp
|
||||
|
BIN
UI/forms/images/locked_mask.png
Normal file
BIN
UI/forms/images/locked_mask.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 288 B |
BIN
UI/forms/images/unlocked_mask.png
Normal file
BIN
UI/forms/images/unlocked_mask.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 318 B |
@ -14,6 +14,8 @@
|
||||
<file>images/up.png</file>
|
||||
<file>images/obs.png</file>
|
||||
<file>images/tray_active.png</file>
|
||||
<file>images/locked_mask.png</file>
|
||||
<file>images/unlocked_mask.png</file>
|
||||
</qresource>
|
||||
<qresource prefix="/settings">
|
||||
<file>images/settings/advanced.png</file>
|
||||
|
36
UI/locked-checkbox.cpp
Normal file
36
UI/locked-checkbox.cpp
Normal file
@ -0,0 +1,36 @@
|
||||
#include <QPaintEvent>
|
||||
#include <QPixmap>
|
||||
#include <QPainter>
|
||||
#include "locked-checkbox.hpp"
|
||||
|
||||
#include <util/c99defs.h>
|
||||
|
||||
LockedCheckBox::LockedCheckBox() : QCheckBox()
|
||||
{
|
||||
lockedImage =
|
||||
QPixmap::fromImage(QImage(":/res/images/locked_mask.png"));
|
||||
unlockedImage =
|
||||
QPixmap::fromImage(QImage(":/res/images/unlocked_mask.png"));
|
||||
setMinimumSize(16, 16);
|
||||
|
||||
setStyleSheet("outline: none;");
|
||||
}
|
||||
|
||||
void LockedCheckBox::paintEvent(QPaintEvent *event)
|
||||
{
|
||||
UNUSED_PARAMETER(event);
|
||||
|
||||
QPixmap &pixmap = isChecked() ? lockedImage : unlockedImage;
|
||||
QImage image(pixmap.size(), QImage::Format_ARGB32);
|
||||
|
||||
QPainter draw(&image);
|
||||
draw.setCompositionMode(QPainter::CompositionMode_Source);
|
||||
draw.drawPixmap(0, 0, pixmap.width(), pixmap.height(), pixmap);
|
||||
draw.setCompositionMode(QPainter::CompositionMode_SourceIn);
|
||||
draw.fillRect(QRectF(QPointF(0.0f, 0.0f), pixmap.size()),
|
||||
palette().color(foregroundRole()));
|
||||
|
||||
QPainter p(this);
|
||||
p.drawPixmap(0, 0, image.width(), image.height(),
|
||||
QPixmap::fromImage(image));
|
||||
}
|
17
UI/locked-checkbox.hpp
Normal file
17
UI/locked-checkbox.hpp
Normal file
@ -0,0 +1,17 @@
|
||||
#include <QCheckBox>
|
||||
#include <QPixmap>
|
||||
|
||||
class QPaintEvernt;
|
||||
|
||||
class LockedCheckBox : public QCheckBox {
|
||||
Q_OBJECT
|
||||
|
||||
QPixmap lockedImage;
|
||||
QPixmap unlockedImage;
|
||||
|
||||
public:
|
||||
LockedCheckBox();
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
};
|
@ -1,5 +1,6 @@
|
||||
#include "visibility-item-widget.hpp"
|
||||
#include "visibility-checkbox.hpp"
|
||||
#include "locked-checkbox.hpp"
|
||||
#include "qt-wrappers.hpp"
|
||||
#include "obs-app.hpp"
|
||||
#include <QListWidget>
|
||||
@ -49,6 +50,7 @@ VisibilityItemWidget::VisibilityItemWidget(obs_sceneitem_t *item_)
|
||||
{
|
||||
const char *name = obs_source_get_name(source);
|
||||
bool enabled = obs_sceneitem_visible(item);
|
||||
bool locked = obs_sceneitem_locked(item);
|
||||
obs_scene_t *scene = obs_sceneitem_get_scene(item);
|
||||
obs_source_t *sceneSource = obs_scene_get_source(scene);
|
||||
|
||||
@ -60,13 +62,23 @@ VisibilityItemWidget::VisibilityItemWidget(obs_sceneitem_t *item_)
|
||||
#endif
|
||||
vis->setChecked(enabled);
|
||||
|
||||
lock = new LockedCheckBox();
|
||||
lock->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
|
||||
/* Fix for non-apple systems where the spacing would be too big */
|
||||
#ifndef __APPLE__
|
||||
lock->setMaximumSize(16, 16);
|
||||
#endif
|
||||
lock->setChecked(locked);
|
||||
|
||||
label = new QLabel(QT_UTF8(name));
|
||||
label->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
|
||||
|
||||
QHBoxLayout *itemLayout = new QHBoxLayout();
|
||||
itemLayout->addWidget(vis);
|
||||
itemLayout->addWidget(lock);
|
||||
itemLayout->addWidget(label);
|
||||
itemLayout->setContentsMargins(5, 2, 5, 2);
|
||||
itemLayout->setSpacing(2);
|
||||
|
||||
setLayout(itemLayout);
|
||||
setStyleSheet("background-color: rgba(255, 255, 255, 0);");
|
||||
@ -80,6 +92,9 @@ VisibilityItemWidget::VisibilityItemWidget(obs_sceneitem_t *item_)
|
||||
|
||||
connect(vis, SIGNAL(clicked(bool)),
|
||||
this, SLOT(VisibilityClicked(bool)));
|
||||
|
||||
connect(lock, SIGNAL(clicked(bool)),
|
||||
this, SLOT(LockClicked(bool)));
|
||||
}
|
||||
|
||||
VisibilityItemWidget::~VisibilityItemWidget()
|
||||
@ -137,6 +152,18 @@ void VisibilityItemWidget::OBSSceneItemVisible(void *param, calldata_t *data)
|
||||
Q_ARG(bool, enabled));
|
||||
}
|
||||
|
||||
void VisibilityItemWidget::OBSSceneItemLocked(void *param, calldata_t *data)
|
||||
{
|
||||
VisibilityItemWidget *window =
|
||||
reinterpret_cast<VisibilityItemWidget*>(param);
|
||||
obs_sceneitem_t *curItem = (obs_sceneitem_t*)calldata_ptr(data, "item");
|
||||
bool locked = calldata_bool(data, "locked");
|
||||
|
||||
if (window->item == curItem)
|
||||
QMetaObject::invokeMethod(window, "SourceLocked",
|
||||
Q_ARG(bool, locked));
|
||||
}
|
||||
|
||||
void VisibilityItemWidget::OBSSourceEnabled(void *param, calldata_t *data)
|
||||
{
|
||||
VisibilityItemWidget *window =
|
||||
@ -165,12 +192,24 @@ void VisibilityItemWidget::VisibilityClicked(bool visible)
|
||||
obs_source_set_enabled(source, visible);
|
||||
}
|
||||
|
||||
void VisibilityItemWidget::LockClicked(bool locked)
|
||||
{
|
||||
if (item)
|
||||
obs_sceneitem_set_locked(item, locked);
|
||||
}
|
||||
|
||||
void VisibilityItemWidget::SourceEnabled(bool enabled)
|
||||
{
|
||||
if (vis->isChecked() != enabled)
|
||||
vis->setChecked(enabled);
|
||||
}
|
||||
|
||||
void VisibilityItemWidget::SourceLocked(bool locked)
|
||||
{
|
||||
if (lock->isChecked() != locked)
|
||||
lock->setChecked(locked);
|
||||
}
|
||||
|
||||
void VisibilityItemWidget::SourceRenamed(QString name)
|
||||
{
|
||||
if (label && name != label->text())
|
||||
|
@ -9,6 +9,7 @@ class QLineEdit;
|
||||
class QListWidget;
|
||||
class QListWidgetItem;
|
||||
class VisibilityCheckBox;
|
||||
class LockedCheckBox;
|
||||
|
||||
class VisibilityItemWidget : public QWidget {
|
||||
Q_OBJECT
|
||||
@ -18,6 +19,7 @@ private:
|
||||
OBSSource source;
|
||||
QLabel *label = nullptr;
|
||||
VisibilityCheckBox *vis = nullptr;
|
||||
LockedCheckBox *lock = nullptr;
|
||||
QString oldName;
|
||||
|
||||
OBSSignal sceneRemoveSignal;
|
||||
@ -31,6 +33,7 @@ private:
|
||||
static void OBSSceneRemove(void *param, calldata_t *data);
|
||||
static void OBSSceneItemRemove(void *param, calldata_t *data);
|
||||
static void OBSSceneItemVisible(void *param, calldata_t *data);
|
||||
static void OBSSceneItemLocked(void *param, calldata_t *data);
|
||||
static void OBSSourceEnabled(void *param, calldata_t *data);
|
||||
static void OBSSourceRenamed(void *param, calldata_t *data);
|
||||
|
||||
@ -38,8 +41,10 @@ private:
|
||||
|
||||
private slots:
|
||||
void VisibilityClicked(bool visible);
|
||||
void LockClicked(bool locked);
|
||||
void SourceEnabled(bool enabled);
|
||||
void SourceRenamed(QString name);
|
||||
void SourceLocked(bool locked);
|
||||
|
||||
public:
|
||||
VisibilityItemWidget(obs_source_t *source);
|
||||
|
@ -5004,6 +5004,9 @@ void OBSBasic::Nudge(int dist, MoveDir dir)
|
||||
|
||||
auto func = [] (obs_scene_t*, obs_sceneitem_t *item, void *param)
|
||||
{
|
||||
if (obs_sceneitem_locked(item))
|
||||
return true;
|
||||
|
||||
MoveInfo *info = reinterpret_cast<MoveInfo*>(param);
|
||||
struct vec2 dir;
|
||||
struct vec2 pos;
|
||||
|
@ -75,6 +75,8 @@ static bool FindItemAtPos(obs_scene_t *scene, obs_sceneitem_t *item,
|
||||
|
||||
if (!SceneItemHasVideo(item))
|
||||
return true;
|
||||
if (obs_sceneitem_locked(item))
|
||||
return true;
|
||||
|
||||
vec3_set(&pos3, data->pos.x, data->pos.y, 0.0f);
|
||||
|
||||
@ -674,6 +676,9 @@ void OBSBasicPreview::SnapItemMovement(vec2 &offset)
|
||||
|
||||
static bool move_items(obs_scene_t *scene, obs_sceneitem_t *item, void *param)
|
||||
{
|
||||
if (obs_sceneitem_locked(item))
|
||||
return true;
|
||||
|
||||
vec2 *offset = reinterpret_cast<vec2*>(param);
|
||||
|
||||
if (obs_sceneitem_selected(item)) {
|
||||
@ -1084,6 +1089,9 @@ static inline bool crop_enabled(const obs_sceneitem_crop *crop)
|
||||
bool OBSBasicPreview::DrawSelectedItem(obs_scene_t *scene,
|
||||
obs_sceneitem_t *item, void *param)
|
||||
{
|
||||
if (obs_sceneitem_locked(item))
|
||||
return true;
|
||||
|
||||
if (!obs_sceneitem_selected(item))
|
||||
return true;
|
||||
|
||||
@ -1183,6 +1191,7 @@ void OBSBasicPreview::DrawSceneEditing()
|
||||
gs_technique_begin_pass(tech, 0);
|
||||
|
||||
OBSScene scene = main->GetCurrentScene();
|
||||
|
||||
if (scene)
|
||||
obs_scene_enum_items(scene, DrawSelectedItem, this);
|
||||
|
||||
|
@ -590,6 +590,7 @@ static void scene_load_item(struct obs_scene *scene, obs_data_t *item_data)
|
||||
const char *scale_filter_str;
|
||||
struct obs_scene_item *item;
|
||||
bool visible;
|
||||
bool lock;
|
||||
|
||||
if (!source) {
|
||||
blog(LOG_WARNING, "[scene_load_item] Source %s not found!",
|
||||
@ -616,10 +617,12 @@ static void scene_load_item(struct obs_scene *scene, obs_data_t *item_data)
|
||||
item->rot = (float)obs_data_get_double(item_data, "rot");
|
||||
item->align = (uint32_t)obs_data_get_int(item_data, "align");
|
||||
visible = obs_data_get_bool(item_data, "visible");
|
||||
lock = obs_data_get_bool(item_data, "locked");
|
||||
obs_data_get_vec2(item_data, "pos", &item->pos);
|
||||
obs_data_get_vec2(item_data, "scale", &item->scale);
|
||||
|
||||
set_visibility(item, visible);
|
||||
obs_sceneitem_set_locked(item, lock);
|
||||
|
||||
item->bounds_type =
|
||||
(enum obs_bounds_type)obs_data_get_int(item_data,
|
||||
@ -697,6 +700,7 @@ static void scene_save_item(obs_data_array_t *array,
|
||||
|
||||
obs_data_set_string(item_data, "name", name);
|
||||
obs_data_set_bool (item_data, "visible", item->user_visible);
|
||||
obs_data_set_bool (item_data, "locked", item->locked);
|
||||
obs_data_set_double(item_data, "rot", item->rot);
|
||||
obs_data_set_vec2 (item_data, "pos", &item->pos);
|
||||
obs_data_set_vec2 (item_data, "scale", &item->scale);
|
||||
@ -1347,6 +1351,7 @@ obs_sceneitem_t *obs_scene_add(obs_scene_t *scene, obs_source_t *source)
|
||||
item->align = OBS_ALIGN_TOP | OBS_ALIGN_LEFT;
|
||||
item->actions_mutex = mutex;
|
||||
item->user_visible = true;
|
||||
item->locked = false;
|
||||
os_atomic_set_long(&item->active_refs, 1);
|
||||
vec2_set(&item->scale, 1.0f, 1.0f);
|
||||
matrix4_identity(&item->draw_transform);
|
||||
@ -1773,6 +1778,27 @@ bool obs_sceneitem_set_visible(obs_sceneitem_t *item, bool visible)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool obs_sceneitem_locked(const obs_sceneitem_t *item)
|
||||
{
|
||||
return item ? item->locked : false;
|
||||
}
|
||||
|
||||
bool obs_sceneitem_set_locked(obs_sceneitem_t *item, bool lock)
|
||||
{
|
||||
if (!item)
|
||||
return false;
|
||||
|
||||
if (item->locked == lock)
|
||||
return false;
|
||||
|
||||
if (!item->parent)
|
||||
return false;
|
||||
|
||||
item->locked = lock;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool sceneitems_match(obs_scene_t *scene, obs_sceneitem_t * const *items,
|
||||
size_t size, bool *order_matches)
|
||||
{
|
||||
|
@ -41,6 +41,7 @@ struct obs_scene_item {
|
||||
bool user_visible;
|
||||
bool visible;
|
||||
bool selected;
|
||||
bool locked;
|
||||
|
||||
gs_texrender_t *item_render;
|
||||
struct obs_sceneitem_crop crop;
|
||||
|
@ -1251,8 +1251,12 @@ EXPORT obs_scene_t *obs_sceneitem_get_scene(const obs_sceneitem_t *item);
|
||||
/** Gets the source of a scene item. */
|
||||
EXPORT obs_source_t *obs_sceneitem_get_source(const obs_sceneitem_t *item);
|
||||
|
||||
/* FIXME: The following functions should be deprecated and replaced with a way
|
||||
* to specify savable private user data. -Jim */
|
||||
EXPORT void obs_sceneitem_select(obs_sceneitem_t *item, bool select);
|
||||
EXPORT bool obs_sceneitem_selected(const obs_sceneitem_t *item);
|
||||
EXPORT bool obs_sceneitem_locked(const obs_sceneitem_t *item);
|
||||
EXPORT bool obs_sceneitem_set_locked(obs_sceneitem_t *item, bool lock);
|
||||
|
||||
/* Functions for getting/setting specific orientation of a scene item */
|
||||
EXPORT void obs_sceneitem_set_pos(obs_sceneitem_t *item, const struct vec2 *pos);
|
||||
|
Loading…
x
Reference in New Issue
Block a user