UI: Add box select to preview
This change adds the ability to box select by clicking and dragging from an empty part of the preview. Shift + Drag add any items in the box to the selection. Alt + Drag will remove items in the box from the selection. Ctrl + Drag inverts the selected state for items in the box.
This commit is contained in:
parent
f838136597
commit
128b90af9d
@ -194,6 +194,9 @@ if(MSVC)
|
||||
../deps/libff/libff/ff-util.c
|
||||
PROPERTIES COMPILE_FLAGS -Dinline=__inline
|
||||
)
|
||||
set(obs_PLATFORM_LIBRARIES
|
||||
${obs_PLATFORM_LIBRARIES}
|
||||
w32-pthreads)
|
||||
endif()
|
||||
|
||||
set(obs_SOURCES
|
||||
|
@ -263,6 +263,27 @@ void SourceTreeItem::mouseDoubleClickEvent(QMouseEvent *event)
|
||||
}
|
||||
}
|
||||
|
||||
void SourceTreeItem::enterEvent(QEvent *event)
|
||||
{
|
||||
QWidget::enterEvent(event);
|
||||
|
||||
OBSBasicPreview *preview = OBSBasicPreview::Get();
|
||||
|
||||
std::lock_guard<std::mutex> lock(preview->selectMutex);
|
||||
preview->hoveredPreviewItems.clear();
|
||||
preview->hoveredPreviewItems.push_back(sceneitem);
|
||||
}
|
||||
|
||||
void SourceTreeItem::leaveEvent(QEvent *event)
|
||||
{
|
||||
QWidget::leaveEvent(event);
|
||||
|
||||
OBSBasicPreview *preview = OBSBasicPreview::Get();
|
||||
|
||||
std::lock_guard<std::mutex> lock(preview->selectMutex);
|
||||
preview->hoveredPreviewItems.clear();
|
||||
}
|
||||
|
||||
bool SourceTreeItem::IsEditing()
|
||||
{
|
||||
return editor != nullptr;
|
||||
@ -1281,19 +1302,22 @@ void SourceTree::mouseMoveEvent(QMouseEvent *event)
|
||||
|
||||
OBSBasicPreview *preview = OBSBasicPreview::Get();
|
||||
|
||||
if (item)
|
||||
preview->hoveredListItem = item->sceneitem;
|
||||
else
|
||||
preview->hoveredListItem = nullptr;
|
||||
|
||||
QListView::mouseMoveEvent(event);
|
||||
|
||||
std::lock_guard<std::mutex> lock(preview->selectMutex);
|
||||
preview->hoveredPreviewItems.clear();
|
||||
if (item)
|
||||
preview->hoveredPreviewItems.push_back(item->sceneitem);
|
||||
}
|
||||
|
||||
void SourceTree::leaveEvent(QEvent *event)
|
||||
{
|
||||
OBSBasicPreview *preview = OBSBasicPreview::Get();
|
||||
preview->hoveredListItem = nullptr;
|
||||
|
||||
QListView::leaveEvent(event);
|
||||
|
||||
std::lock_guard<std::mutex> lock(preview->selectMutex);
|
||||
preview->hoveredPreviewItems.clear();
|
||||
}
|
||||
|
||||
void SourceTree::selectionChanged(const QItemSelection &selected,
|
||||
|
@ -30,6 +30,8 @@ class SourceTreeItem : public QWidget {
|
||||
friend class SourceTreeModel;
|
||||
|
||||
void mouseDoubleClickEvent(QMouseEvent *event) override;
|
||||
void enterEvent(QEvent *event) override;
|
||||
void leaveEvent(QEvent *event) override;
|
||||
|
||||
virtual bool eventFilter(QObject *object, QEvent *event) override;
|
||||
|
||||
|
@ -28,11 +28,14 @@ OBSBasicPreview::OBSBasicPreview(QWidget *parent, Qt::WindowFlags flags)
|
||||
|
||||
OBSBasicPreview::~OBSBasicPreview()
|
||||
{
|
||||
if (overflow) {
|
||||
obs_enter_graphics();
|
||||
obs_enter_graphics();
|
||||
|
||||
if (overflow)
|
||||
gs_texture_destroy(overflow);
|
||||
obs_leave_graphics();
|
||||
}
|
||||
if (rectFill)
|
||||
gs_vertexbuffer_destroy(rectFill);
|
||||
|
||||
obs_leave_graphics();
|
||||
}
|
||||
|
||||
vec2 OBSBasicPreview::GetMouseEventPos(QMouseEvent *event)
|
||||
@ -70,6 +73,22 @@ struct SceneFindData {
|
||||
}
|
||||
};
|
||||
|
||||
struct SceneFindBoxData {
|
||||
const vec2 &startPos;
|
||||
const vec2 &pos;
|
||||
std::vector<obs_sceneitem_t *> sceneItems;
|
||||
|
||||
SceneFindBoxData(const SceneFindData &) = delete;
|
||||
SceneFindBoxData(SceneFindData &&) = delete;
|
||||
SceneFindBoxData &operator=(const SceneFindData &) = delete;
|
||||
SceneFindBoxData &operator=(SceneFindData &&) = delete;
|
||||
|
||||
inline SceneFindBoxData(const vec2 &startPos_, const vec2 &pos_)
|
||||
: startPos(startPos_), pos(pos_)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
static bool SceneItemHasVideo(obs_sceneitem_t *item)
|
||||
{
|
||||
obs_source_t *source = obs_sceneitem_get_source(item);
|
||||
@ -518,6 +537,8 @@ void OBSBasicPreview::mousePressEvent(QMouseEvent *event)
|
||||
float y = float(event->y()) - main->previewY / pixelRatio;
|
||||
Qt::KeyboardModifiers modifiers = QGuiApplication::keyboardModifiers();
|
||||
bool altDown = (modifiers & Qt::AltModifier);
|
||||
bool shiftDown = (modifiers & Qt::ShiftModifier);
|
||||
bool ctrlDown = (modifiers & Qt::ControlModifier);
|
||||
|
||||
OBSQTDisplay::mousePressEvent(event);
|
||||
|
||||
@ -528,9 +549,25 @@ void OBSBasicPreview::mousePressEvent(QMouseEvent *event)
|
||||
if (event->button() == Qt::LeftButton)
|
||||
mouseDown = true;
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(selectMutex);
|
||||
selectedItems.clear();
|
||||
}
|
||||
|
||||
if (altDown)
|
||||
cropping = true;
|
||||
|
||||
if (altDown || shiftDown || ctrlDown) {
|
||||
vec2 s;
|
||||
SceneFindBoxData data(s, s);
|
||||
|
||||
obs_scene_enum_items(main->GetCurrentScene(), FindSelected,
|
||||
&data);
|
||||
|
||||
std::lock_guard<std::mutex> lock(selectMutex);
|
||||
selectedItems = data.sceneItems;
|
||||
}
|
||||
|
||||
vec2_set(&startPos, x, y);
|
||||
GetStretchHandleData(startPos);
|
||||
|
||||
@ -540,6 +577,8 @@ void OBSBasicPreview::mousePressEvent(QMouseEvent *event)
|
||||
|
||||
mouseOverItems = SelectedAtPos(startPos);
|
||||
vec2_zero(&lastMoveOffset);
|
||||
|
||||
mousePos = startPos;
|
||||
}
|
||||
|
||||
static bool select_one(obs_scene_t *scene, obs_sceneitem_t *item, void *param)
|
||||
@ -601,6 +640,37 @@ void OBSBasicPreview::mouseReleaseEvent(QMouseEvent *event)
|
||||
if (!mouseMoved)
|
||||
ProcessClick(pos);
|
||||
|
||||
if (selectionBox) {
|
||||
Qt::KeyboardModifiers modifiers =
|
||||
QGuiApplication::keyboardModifiers();
|
||||
|
||||
bool altDown = modifiers & Qt::AltModifier;
|
||||
bool shiftDown = modifiers & Qt::ShiftModifier;
|
||||
bool ctrlDown = modifiers & Qt::ControlModifier;
|
||||
|
||||
std::lock_guard<std::mutex> lock(selectMutex);
|
||||
if (altDown || ctrlDown || shiftDown) {
|
||||
for (int i = 0; i < selectedItems.size(); i++) {
|
||||
obs_sceneitem_select(selectedItems[i],
|
||||
true);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < hoveredPreviewItems.size(); i++) {
|
||||
bool select = true;
|
||||
obs_sceneitem_t *item = hoveredPreviewItems[i];
|
||||
|
||||
if (altDown) {
|
||||
select = false;
|
||||
} else if (ctrlDown) {
|
||||
select = !obs_sceneitem_selected(item);
|
||||
}
|
||||
|
||||
obs_sceneitem_select(hoveredPreviewItems[i],
|
||||
select);
|
||||
}
|
||||
}
|
||||
|
||||
if (stretchGroup) {
|
||||
obs_sceneitem_defer_group_resize_end(stretchGroup);
|
||||
}
|
||||
@ -610,9 +680,14 @@ void OBSBasicPreview::mouseReleaseEvent(QMouseEvent *event)
|
||||
mouseDown = false;
|
||||
mouseMoved = false;
|
||||
cropping = false;
|
||||
selectionBox = false;
|
||||
|
||||
OBSSceneItem item = GetItemAtPos(pos, true);
|
||||
hoveredPreviewItem = item;
|
||||
|
||||
std::lock_guard<std::mutex> lock(selectMutex);
|
||||
hoveredPreviewItems.clear();
|
||||
hoveredPreviewItems.push_back(item);
|
||||
selectedItems.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@ -833,6 +908,191 @@ void OBSBasicPreview::MoveItems(const vec2 &pos)
|
||||
obs_scene_enum_items(scene, move_items, &moveOffset);
|
||||
}
|
||||
|
||||
static bool CounterClockwise(float x1, float x2, float x3, float y1, float y2,
|
||||
float y3)
|
||||
{
|
||||
return (y3 - y1) * (x2 - x1) > (y2 - y1) * (x3 - x1);
|
||||
}
|
||||
|
||||
static bool IntersectLine(float x1, float x2, float x3, float x4, float y1,
|
||||
float y2, float y3, float y4)
|
||||
{
|
||||
bool a = CounterClockwise(x1, x2, x3, y1, y2, y3);
|
||||
bool b = CounterClockwise(x1, x2, x4, y1, y2, y4);
|
||||
bool c = CounterClockwise(x3, x4, x1, y3, y4, y1);
|
||||
bool d = CounterClockwise(x3, x4, x2, y3, y4, y2);
|
||||
|
||||
return (a != b) && (c != d);
|
||||
}
|
||||
|
||||
static bool IntersectBox(matrix4 transform, float x1, float x2, float y1,
|
||||
float y2)
|
||||
{
|
||||
float x3, x4, y3, y4;
|
||||
|
||||
x3 = transform.t.x;
|
||||
y3 = transform.t.y;
|
||||
x4 = x3 + transform.x.x;
|
||||
y4 = y3 + transform.x.y;
|
||||
|
||||
if (IntersectLine(x1, x1, x3, x4, y1, y2, y3, y4) ||
|
||||
IntersectLine(x1, x2, x3, x4, y1, y1, y3, y4) ||
|
||||
IntersectLine(x2, x2, x3, x4, y1, y2, y3, y4) ||
|
||||
IntersectLine(x1, x2, x3, x4, y2, y2, y3, y4))
|
||||
return true;
|
||||
|
||||
x4 = x3 + transform.y.x;
|
||||
y4 = y3 + transform.y.y;
|
||||
|
||||
if (IntersectLine(x1, x1, x3, x4, y1, y2, y3, y4) ||
|
||||
IntersectLine(x1, x2, x3, x4, y1, y1, y3, y4) ||
|
||||
IntersectLine(x2, x2, x3, x4, y1, y2, y3, y4) ||
|
||||
IntersectLine(x1, x2, x3, x4, y2, y2, y3, y4))
|
||||
return true;
|
||||
|
||||
x3 = transform.t.x + transform.x.x;
|
||||
y3 = transform.t.y + transform.x.y;
|
||||
x4 = x3 + transform.y.x;
|
||||
y4 = y3 + transform.y.y;
|
||||
|
||||
if (IntersectLine(x1, x1, x3, x4, y1, y2, y3, y4) ||
|
||||
IntersectLine(x1, x2, x3, x4, y1, y1, y3, y4) ||
|
||||
IntersectLine(x2, x2, x3, x4, y1, y2, y3, y4) ||
|
||||
IntersectLine(x1, x2, x3, x4, y2, y2, y3, y4))
|
||||
return true;
|
||||
|
||||
x3 = transform.t.x + transform.y.x;
|
||||
y3 = transform.t.y + transform.y.y;
|
||||
x4 = x3 + transform.x.x;
|
||||
y4 = y3 + transform.x.y;
|
||||
|
||||
if (IntersectLine(x1, x1, x3, x4, y1, y2, y3, y4) ||
|
||||
IntersectLine(x1, x2, x3, x4, y1, y1, y3, y4) ||
|
||||
IntersectLine(x2, x2, x3, x4, y1, y2, y3, y4) ||
|
||||
IntersectLine(x1, x2, x3, x4, y2, y2, y3, y4))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
#undef PI
|
||||
|
||||
bool OBSBasicPreview::FindSelected(obs_scene_t *scene, obs_sceneitem_t *item,
|
||||
void *param)
|
||||
{
|
||||
SceneFindBoxData *data = reinterpret_cast<SceneFindBoxData *>(param);
|
||||
|
||||
if (obs_sceneitem_selected(item))
|
||||
data->sceneItems.push_back(item);
|
||||
|
||||
UNUSED_PARAMETER(scene);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool FindItemsInBox(obs_scene_t *scene, obs_sceneitem_t *item,
|
||||
void *param)
|
||||
{
|
||||
SceneFindBoxData *data = reinterpret_cast<SceneFindBoxData *>(param);
|
||||
matrix4 transform;
|
||||
matrix4 invTransform;
|
||||
vec3 transformedPos;
|
||||
vec3 pos3;
|
||||
vec3 pos3_;
|
||||
|
||||
float x1 = std::min(data->startPos.x, data->pos.x);
|
||||
float x2 = std::max(data->startPos.x, data->pos.x);
|
||||
float y1 = std::min(data->startPos.y, data->pos.y);
|
||||
float y2 = std::max(data->startPos.y, data->pos.y);
|
||||
|
||||
if (!SceneItemHasVideo(item))
|
||||
return true;
|
||||
if (obs_sceneitem_locked(item))
|
||||
return true;
|
||||
if (!obs_sceneitem_visible(item))
|
||||
return true;
|
||||
|
||||
vec3_set(&pos3, data->pos.x, data->pos.y, 0.0f);
|
||||
|
||||
obs_sceneitem_get_box_transform(item, &transform);
|
||||
|
||||
matrix4_inv(&invTransform, &transform);
|
||||
vec3_transform(&transformedPos, &pos3, &invTransform);
|
||||
vec3_transform(&pos3_, &transformedPos, &transform);
|
||||
|
||||
if (CloseFloat(pos3.x, pos3_.x) && CloseFloat(pos3.y, pos3_.y) &&
|
||||
transformedPos.x >= 0.0f && transformedPos.x <= 1.0f &&
|
||||
transformedPos.y >= 0.0f && transformedPos.y <= 1.0f) {
|
||||
|
||||
data->sceneItems.push_back(item);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (transform.t.x > x1 && transform.t.x < x2 && transform.t.y > y1 &&
|
||||
transform.t.y < y2) {
|
||||
|
||||
data->sceneItems.push_back(item);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (transform.t.x + transform.x.x > x1 &&
|
||||
transform.t.x + transform.x.x < x2 &&
|
||||
transform.t.y + transform.x.y > y1 &&
|
||||
transform.t.y + transform.x.y < y2) {
|
||||
|
||||
data->sceneItems.push_back(item);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (transform.t.x + transform.y.x > x1 &&
|
||||
transform.t.x + transform.y.x < x2 &&
|
||||
transform.t.y + transform.y.y > y1 &&
|
||||
transform.t.y + transform.y.y < y2) {
|
||||
|
||||
data->sceneItems.push_back(item);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (transform.t.x + transform.x.x + transform.y.x > x1 &&
|
||||
transform.t.x + transform.x.x + transform.y.x < x2 &&
|
||||
transform.t.y + transform.x.y + transform.y.y > y1 &&
|
||||
transform.t.y + transform.x.y + transform.y.y < y2) {
|
||||
|
||||
data->sceneItems.push_back(item);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (transform.t.x + 0.5 * (transform.x.x + transform.y.x) > x1 &&
|
||||
transform.t.x + 0.5 * (transform.x.x + transform.y.x) < x2 &&
|
||||
transform.t.y + 0.5 * (transform.x.y + transform.y.y) > y1 &&
|
||||
transform.t.y + 0.5 * (transform.x.y + transform.y.y) < y2) {
|
||||
|
||||
data->sceneItems.push_back(item);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (IntersectBox(transform, x1, x2, y1, y2)) {
|
||||
data->sceneItems.push_back(item);
|
||||
return true;
|
||||
}
|
||||
|
||||
UNUSED_PARAMETER(scene);
|
||||
return true;
|
||||
}
|
||||
|
||||
void OBSBasicPreview::BoxItems(const vec2 &startPos, const vec2 &pos)
|
||||
{
|
||||
OBSBasic *main = reinterpret_cast<OBSBasic *>(App()->GetMainWindow());
|
||||
|
||||
OBSScene scene = main->GetCurrentScene();
|
||||
if (!scene)
|
||||
return;
|
||||
|
||||
SceneFindBoxData data(startPos, pos);
|
||||
obs_scene_enum_items(scene, FindItemsInBox, &data);
|
||||
|
||||
std::lock_guard<std::mutex> lock(selectMutex);
|
||||
hoveredPreviewItems = data.sceneItems;
|
||||
}
|
||||
|
||||
vec3 OBSBasicPreview::CalculateStretchPos(const vec3 &tl, const vec3 &br)
|
||||
{
|
||||
uint32_t alignment = obs_sceneitem_get_alignment(stretchItem);
|
||||
@ -1160,8 +1420,6 @@ void OBSBasicPreview::mouseMoveEvent(QMouseEvent *event)
|
||||
return;
|
||||
|
||||
if (mouseDown) {
|
||||
hoveredPreviewItem = nullptr;
|
||||
|
||||
vec2 pos = GetMouseEventPos(event);
|
||||
|
||||
if (!mouseMoved && !mouseOverItems &&
|
||||
@ -1174,6 +1432,8 @@ void OBSBasicPreview::mouseMoveEvent(QMouseEvent *event)
|
||||
pos.y = std::round(pos.y);
|
||||
|
||||
if (stretchHandle != ItemHandle::None) {
|
||||
selectionBox = false;
|
||||
|
||||
OBSBasic *main = reinterpret_cast<OBSBasic *>(
|
||||
App()->GetMainWindow());
|
||||
OBSScene scene = main->GetCurrentScene();
|
||||
@ -1194,23 +1454,32 @@ void OBSBasicPreview::mouseMoveEvent(QMouseEvent *event)
|
||||
StretchItem(pos);
|
||||
|
||||
} else if (mouseOverItems) {
|
||||
selectionBox = false;
|
||||
MoveItems(pos);
|
||||
} else {
|
||||
selectionBox = true;
|
||||
if (!mouseMoved)
|
||||
DoSelect(startPos);
|
||||
BoxItems(startPos, pos);
|
||||
}
|
||||
|
||||
mouseMoved = true;
|
||||
mousePos = pos;
|
||||
} else {
|
||||
vec2 pos = GetMouseEventPos(event);
|
||||
OBSSceneItem item = GetItemAtPos(pos, true);
|
||||
|
||||
hoveredPreviewItem = item;
|
||||
std::lock_guard<std::mutex> lock(selectMutex);
|
||||
hoveredPreviewItems.clear();
|
||||
hoveredPreviewItems.push_back(item);
|
||||
}
|
||||
}
|
||||
|
||||
void OBSBasicPreview::leaveEvent(QEvent *event)
|
||||
void OBSBasicPreview::leaveEvent(QEvent *)
|
||||
{
|
||||
hoveredPreviewItem = nullptr;
|
||||
|
||||
UNUSED_PARAMETER(event);
|
||||
std::lock_guard<std::mutex> lock(selectMutex);
|
||||
if (!selectionBox)
|
||||
hoveredPreviewItems.clear();
|
||||
}
|
||||
|
||||
static void DrawSquareAtPos(float x, float y)
|
||||
@ -1405,8 +1674,17 @@ bool OBSBasicPreview::DrawSelectedItem(obs_scene_t *scene,
|
||||
OBSBasicPreview *prev = reinterpret_cast<OBSBasicPreview *>(param);
|
||||
OBSBasic *main = OBSBasic::Get();
|
||||
|
||||
bool hovered = prev->hoveredPreviewItem == item ||
|
||||
prev->hoveredListItem == item;
|
||||
bool hovered = false;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(prev->selectMutex);
|
||||
for (int i = 0; i < prev->hoveredPreviewItems.size(); i++) {
|
||||
if (prev->hoveredPreviewItems[i] == item) {
|
||||
hovered = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool selected = obs_sceneitem_selected(item);
|
||||
|
||||
if (!selected && !hovered)
|
||||
@ -1510,6 +1788,44 @@ bool OBSBasicPreview::DrawSelectedItem(obs_scene_t *scene,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OBSBasicPreview::DrawSelectionBox(float x1, float y1, float x2, float y2,
|
||||
gs_vertbuffer_t *rectFill)
|
||||
{
|
||||
x1 = std::round(x1);
|
||||
x2 = std::round(x2);
|
||||
y1 = std::round(y1);
|
||||
y2 = std::round(y2);
|
||||
|
||||
gs_effect_t *eff = gs_get_effect();
|
||||
gs_eparam_t *colParam = gs_effect_get_param_by_name(eff, "color");
|
||||
|
||||
vec4 fillColor;
|
||||
vec4_set(&fillColor, 0.7f, 0.7f, 0.7f, 0.5f);
|
||||
|
||||
vec4 borderColor;
|
||||
vec4_set(&borderColor, 1.0f, 1.0f, 1.0f, 1.0f);
|
||||
|
||||
vec2 scale;
|
||||
vec2_set(&scale, std::abs(x2 - x1), std::abs(y2 - y1));
|
||||
|
||||
gs_matrix_push();
|
||||
gs_matrix_identity();
|
||||
|
||||
gs_matrix_translate3f(x1, y1, 0.0f);
|
||||
gs_matrix_scale3f(x2 - x1, y2 - y1, 1.0f);
|
||||
|
||||
gs_effect_set_vec4(colParam, &fillColor);
|
||||
gs_load_vertexbuffer(rectFill);
|
||||
gs_draw(GS_TRISTRIP, 0, 0);
|
||||
|
||||
gs_effect_set_vec4(colParam, &borderColor);
|
||||
DrawRect(HANDLE_RADIUS / 2, scale);
|
||||
|
||||
gs_matrix_pop();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void OBSBasicPreview::DrawOverflow()
|
||||
{
|
||||
if (locked)
|
||||
@ -1573,6 +1889,26 @@ void OBSBasicPreview::DrawSceneEditing()
|
||||
gs_matrix_pop();
|
||||
}
|
||||
|
||||
if (selectionBox) {
|
||||
if (!rectFill) {
|
||||
gs_render_start(true);
|
||||
|
||||
gs_vertex2f(0.0f, 0.0f);
|
||||
gs_vertex2f(1.0f, 0.0f);
|
||||
gs_vertex2f(1.0f, 1.0f);
|
||||
gs_vertex2f(1.0f, 1.0f);
|
||||
gs_vertex2f(0.0f, 0.0f);
|
||||
gs_vertex2f(0.0f, 1.0f);
|
||||
|
||||
rectFill = gs_render_save();
|
||||
}
|
||||
|
||||
DrawSelectionBox(startPos.x * main->previewScale,
|
||||
startPos.y * main->previewScale,
|
||||
mousePos.x * main->previewScale,
|
||||
mousePos.y * main->previewScale, rectFill);
|
||||
}
|
||||
|
||||
gs_load_vertexbuffer(nullptr);
|
||||
|
||||
gs_technique_end_pass(tech);
|
||||
|
@ -3,6 +3,9 @@
|
||||
#include <obs.hpp>
|
||||
#include <graphics/vec2.h>
|
||||
#include <graphics/matrix4.h>
|
||||
#include <util/threading.h>
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
#include "qt-display.hpp"
|
||||
#include "obs-app.hpp"
|
||||
|
||||
@ -32,6 +35,7 @@ class OBSBasicPreview : public OBSQTDisplay {
|
||||
Q_OBJECT
|
||||
|
||||
friend class SourceTree;
|
||||
friend class SourceTreeItem;
|
||||
|
||||
private:
|
||||
obs_sceneitem_crop startCrop;
|
||||
@ -46,8 +50,10 @@ private:
|
||||
matrix4 invGroupTransform;
|
||||
|
||||
gs_texture_t *overflow = nullptr;
|
||||
gs_vertbuffer_t *rectFill = nullptr;
|
||||
|
||||
vec2 startPos;
|
||||
vec2 mousePos;
|
||||
vec2 lastMoveOffset;
|
||||
vec2 scrollingFrom;
|
||||
vec2 scrollingOffset;
|
||||
@ -58,17 +64,23 @@ private:
|
||||
bool locked = false;
|
||||
bool scrollMode = false;
|
||||
bool fixedScaling = false;
|
||||
bool selectionBox = false;
|
||||
int32_t scalingLevel = 0;
|
||||
float scalingAmount = 1.0f;
|
||||
|
||||
obs_sceneitem_t *hoveredPreviewItem = nullptr;
|
||||
obs_sceneitem_t *hoveredListItem = nullptr;
|
||||
std::vector<obs_sceneitem_t *> hoveredPreviewItems;
|
||||
std::vector<obs_sceneitem_t *> selectedItems;
|
||||
std::mutex selectMutex;
|
||||
|
||||
static vec2 GetMouseEventPos(QMouseEvent *event);
|
||||
static bool FindSelected(obs_scene_t *scene, obs_sceneitem_t *item,
|
||||
void *param);
|
||||
static bool DrawSelectedOverflow(obs_scene_t *scene,
|
||||
obs_sceneitem_t *item, void *param);
|
||||
static bool DrawSelectedItem(obs_scene_t *scene, obs_sceneitem_t *item,
|
||||
void *param);
|
||||
static bool DrawSelectionBox(float x1, float y1, float x2, float y2,
|
||||
gs_vertbuffer_t *box);
|
||||
|
||||
static OBSSceneItem GetItemAtPos(const vec2 &pos, bool selectBelow);
|
||||
static bool SelectedAtPos(const vec2 &pos);
|
||||
@ -88,6 +100,7 @@ private:
|
||||
|
||||
static void SnapItemMovement(vec2 &offset);
|
||||
void MoveItems(const vec2 &pos);
|
||||
void BoxItems(const vec2 &startPos, const vec2 &pos);
|
||||
|
||||
void ProcessClick(const vec2 &pos);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user