Skip to content

Commit

Permalink
UI: Add ability to crop scene items via the alt key
Browse files Browse the repository at this point in the history
  • Loading branch information
jp9000 committed Mar 31, 2016
1 parent 02806a7 commit 27310f8
Show file tree
Hide file tree
Showing 2 changed files with 166 additions and 5 deletions.
166 changes: 161 additions & 5 deletions obs/window-basic-preview.cpp
Expand Up @@ -284,11 +284,15 @@ static vec2 GetItemSize(obs_sceneitem_t *item)
obs_sceneitem_get_bounds(item, &size);
} else {
obs_source_t *source = obs_sceneitem_get_source(item);
obs_sceneitem_crop crop;
vec2 scale;

obs_sceneitem_get_scale(item, &scale);
size.x = float(obs_source_get_width(source)) * scale.x;
size.y = float(obs_source_get_height(source)) * scale.y;
obs_sceneitem_get_crop(item, &crop);
size.x = float(obs_source_get_width(source) -
crop.left - crop.right) * scale.x;
size.y = float(obs_source_get_height(source) -
crop.top - crop.bottom) * scale.y;
}

return size;
Expand Down Expand Up @@ -331,6 +335,15 @@ void OBSBasicPreview::GetStretchHandleData(const vec2 &pos)
-itemUL.x, -itemUL.y, 0.0f);
matrix4_rotate_aa4f(&screenToItem, &screenToItem,
0.0f, 0.0f, 1.0f, RAD(-itemRot));

obs_sceneitem_get_crop(stretchItem, &startCrop);
obs_sceneitem_get_pos(stretchItem, &startItemPos);

obs_source_t *source = obs_sceneitem_get_source(stretchItem);
cropSize.x = float(obs_source_get_width(source) -
startCrop.left - startCrop.right);
cropSize.y = float(obs_source_get_height(source) -
startCrop.top - startCrop.bottom);
}
}

Expand All @@ -340,6 +353,8 @@ void OBSBasicPreview::mousePressEvent(QMouseEvent *event)
float pixelRatio = main->devicePixelRatio();
float x = float(event->x()) - main->previewX / pixelRatio;
float y = float(event->y()) - main->previewY / pixelRatio;
Qt::KeyboardModifiers modifiers = QGuiApplication::keyboardModifiers();
bool altDown = (modifiers & Qt::AltModifier);

OBSQTDisplay::mousePressEvent(event);

Expand All @@ -350,6 +365,9 @@ void OBSBasicPreview::mousePressEvent(QMouseEvent *event)
if (event->button() == Qt::LeftButton)
mouseDown = true;

if (altDown)
cropping = true;

vec2_set(&startPos, x, y);
GetStretchHandleData(startPos);

Expand Down Expand Up @@ -412,6 +430,7 @@ void OBSBasicPreview::mouseReleaseEvent(QMouseEvent *event)
stretchItem = nullptr;
mouseDown = false;
mouseMoved = false;
cropping = false;
}
}

Expand Down Expand Up @@ -603,6 +622,121 @@ void OBSBasicPreview::SnapStretchingToScreen(vec3 &tl, vec3 &br)
br.y += offset.y;
}

void OBSBasicPreview::CropItem(const vec2 &pos)
{
obs_bounds_type boundsType = obs_sceneitem_get_bounds_type(stretchItem);
uint32_t stretchFlags = (uint32_t)stretchHandle;
uint32_t align = obs_sceneitem_get_alignment(stretchItem);
vec3 tl, br, pos3;

if (boundsType != OBS_BOUNDS_NONE) /* TODO */
return;

vec3_zero(&tl);
vec3_set(&br, stretchItemSize.x, stretchItemSize.y, 0.0f);

vec3_set(&pos3, pos.x, pos.y, 0.0f);
vec3_transform(&pos3, &pos3, &screenToItem);

obs_sceneitem_crop crop = startCrop;
vec2 scale;

obs_sceneitem_get_scale(stretchItem, &scale);

vec2 max_tl;
vec2 max_br;

vec2_set(&max_tl,
float(-crop.left) * scale.x,
float(-crop.top) * scale.y);
vec2_set(&max_br,
stretchItemSize.x + crop.right * scale.x,
stretchItemSize.y + crop.bottom * scale.y);

vec2_max((vec2*)&pos3, (vec2*)&pos3, &max_br);
vec2_min((vec2*)&pos3, (vec2*)&pos3, &max_tl);

if (stretchFlags & ITEM_LEFT) {
tl.x = pos3.x;

float maxX = stretchItemSize.x - (2.0 * scale.x);
if (tl.x > maxX) pos3.x = tl.x = maxX;
} else if (stretchFlags & ITEM_RIGHT) {
br.x = pos3.x;

float minX = (2.0 * scale.x);
if (br.x < minX) pos3.x = br.x = minX;
}

if (stretchFlags & ITEM_TOP) {
tl.y = pos3.y;

float maxY = stretchItemSize.y - (2.0 * scale.y);
if (tl.y > maxY) pos3.y = tl.y = maxY;
} else if (stretchFlags & ITEM_BOTTOM) {
br.y = pos3.y;

float minY = (2.0 * scale.y);
if (br.y < minY) pos3.y = br.y = minY;
}

#define ALIGN_X (ITEM_LEFT|ITEM_RIGHT)
#define ALIGN_Y (ITEM_TOP|ITEM_BOTTOM)
vec3 newPos;
vec3_zero(&newPos);

uint32_t align_x = (align & ALIGN_X);
uint32_t align_y = (align & ALIGN_Y);
if (align_x == (stretchFlags & ALIGN_X) && align_x != 0)
newPos.x = pos3.x;
else if (align & ITEM_RIGHT)
newPos.x = stretchItemSize.x;
else if (!(align & ITEM_LEFT))
newPos.x = stretchItemSize.x * 0.5f;

if (align_y == (stretchFlags & ALIGN_Y) && align_y != 0)
newPos.y = pos3.y;
else if (align & ITEM_BOTTOM)
newPos.y = stretchItemSize.y;
else if (!(align & ITEM_TOP))
newPos.y = stretchItemSize.y * 0.5f;
#undef ALIGN_X
#undef ALIGN_Y

crop = startCrop;

if (stretchFlags & ITEM_LEFT)
crop.left += int(std::round(tl.x / scale.x));
else if (stretchFlags & ITEM_RIGHT)
crop.right += int(std::round((stretchItemSize.x - br.x) / scale.x));

if (stretchFlags & ITEM_TOP)
crop.top += int(std::round(tl.y / scale.y));
else if (stretchFlags & ITEM_BOTTOM)
crop.bottom += int(std::round((stretchItemSize.y - br.y) / scale.y));

vec3_transform(&newPos, &newPos, &itemToScreen);
newPos.x = std::round(newPos.x);
newPos.y = std::round(newPos.y);

#if 0
vec3 curPos;
vec3_zero(&curPos);
obs_sceneitem_get_pos(stretchItem, (vec2*)&curPos);
blog(LOG_DEBUG, "curPos {%d, %d} - newPos {%d, %d}",
int(curPos.x), int(curPos.y),
int(newPos.x), int(newPos.y));
blog(LOG_DEBUG, "crop {%d, %d, %d, %d}",
crop.left, crop.top,
crop.right, crop.bottom);
#endif

obs_sceneitem_defer_update_begin(stretchItem);
obs_sceneitem_set_crop(stretchItem, &crop);
obs_sceneitem_set_pos(stretchItem, (vec2*)&newPos);
obs_sceneitem_defer_update_end(stretchItem);
}

void OBSBasicPreview::StretchItem(const vec2 &pos)
{
Qt::KeyboardModifiers modifiers = QGuiApplication::keyboardModifiers();
Expand Down Expand Up @@ -651,6 +785,12 @@ void OBSBasicPreview::StretchItem(const vec2 &pos)

obs_sceneitem_set_bounds(stretchItem, &size);
} else {
obs_sceneitem_crop crop;
obs_sceneitem_get_crop(stretchItem, &crop);

baseSize.x -= float(crop.left + crop.right);
baseSize.y -= float(crop.top + crop.bottom);

if (!shiftDown)
ClampAspect(tl, br, size, baseSize);

Expand Down Expand Up @@ -680,10 +820,15 @@ void OBSBasicPreview::mouseMoveEvent(QMouseEvent *event)
pos.x = std::round(pos.x);
pos.y = std::round(pos.y);

if (stretchHandle != ItemHandle::None)
StretchItem(pos);
else if (mouseOverItems)
if (stretchHandle != ItemHandle::None) {
if (cropping)
CropItem(pos);
else
StretchItem(pos);

} else if (mouseOverItems) {
MoveItems(pos);
}

mouseMoved = true;
}
Expand All @@ -704,6 +849,14 @@ static void DrawCircleAtPos(float x, float y, matrix4 &matrix,
gs_matrix_pop();
}

static inline bool crop_enabled(const obs_sceneitem_crop *crop)
{
return crop->left > 0 ||
crop->top > 0 ||
crop->right > 0 ||
crop->bottom > 0;
}

bool OBSBasicPreview::DrawSelectedItem(obs_scene_t *scene,
obs_sceneitem_t *item, void *param)
{
Expand Down Expand Up @@ -736,6 +889,9 @@ bool OBSBasicPreview::DrawSelectedItem(obs_scene_t *scene,
if (!visible)
return true;

obs_transform_info info;
obs_sceneitem_get_info(item, &info);

gs_load_vertexbuffer(main->circle);

DrawCircleAtPos(0.0f, 0.0f, boxTransform, main->previewScale);
Expand Down
5 changes: 5 additions & 0 deletions obs/window-basic-preview.hpp
Expand Up @@ -30,6 +30,9 @@ class OBSBasicPreview : public OBSQTDisplay {
Q_OBJECT

private:
obs_sceneitem_crop startCrop;
vec2 startItemPos;
vec2 cropSize;
OBSSceneItem stretchItem;
ItemHandle stretchHandle = ItemHandle::None;
vec2 stretchItemSize;
Expand All @@ -41,6 +44,7 @@ class OBSBasicPreview : public OBSQTDisplay {
bool mouseDown = false;
bool mouseMoved = false;
bool mouseOverItems = false;
bool cropping = false;

static vec2 GetMouseEventPos(QMouseEvent *event);
static bool DrawSelectedItem(obs_scene_t *scene, obs_sceneitem_t *item,
Expand All @@ -59,6 +63,7 @@ class OBSBasicPreview : public OBSQTDisplay {
void SnapStretchingToScreen(vec3 &tl, vec3 &br);
void ClampAspect(vec3 &tl, vec3 &br, vec2 &size, const vec2 &baseSize);
vec3 CalculateStretchPos(const vec3 &tl, const vec3 &br);
void CropItem(const vec2 &pos);
void StretchItem(const vec2 &pos);

static void SnapItemMovement(vec2 &offset);
Expand Down

0 comments on commit 27310f8

Please sign in to comment.