UI: Add scene editing
So, scene editing was interesting (and by interesting I mean
excruciating). I almost implemented 'manipulator' visuals (ala 3dsmax
for example), and used 3 modes for controlling position/rotation/size,
but in a 2D editing, it felt clunky, so I defaulted back to simply
click-and-drag for movement, and then took a similar though slightly
different looking approach for handling scaling and reszing.
I also added a number of menu item helpers related to positioning,
scaling, rotating, flipping, and resetting the transform back to
default.
There is also a new 'transform' dialog (accessible via menu) which will
allow you to manually edit every single transform variable of a scene
item directly if desired.
If a scene item does not have bounds active, pulling on the sides of a
source will cause it to resize it via base scale rather than by the
bounding box system (if the source resizes that scale will apply). If
bounds are active, it will modify the bounding box only instead.
How a source scales when a bounding box is active depends on the type of
bounds being used. You can set it to scale to the inner bounds, the
outer bounds, scale to bounds width only, scale to bounds height only,
and a setting to stretch to bounds (which forces a source to always draw
at the bounding box size rather than be affected by its internal size).
You can also set it to be used as a 'maximum' size, so that the source
doesn't necessarily get scaled unless it extends beyond the bounds.
Like in OBS1, objects will snap to the edges unless the control key is
pressed. However, this will now happen even if the object is rotated or
oriented in any strange way. Snapping will also occur when stretching
or changing the bounding box size.
2014-06-15 00:54:48 -07:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <obs.hpp>
|
|
|
|
#include <graphics/vec2.h>
|
|
|
|
#include <graphics/matrix4.h>
|
|
|
|
#include "qt-display.hpp"
|
|
|
|
#include "obs-app.hpp"
|
|
|
|
|
|
|
|
class OBSBasic;
|
|
|
|
class QMouseEvent;
|
|
|
|
|
|
|
|
#define ITEM_LEFT (1<<0)
|
|
|
|
#define ITEM_RIGHT (1<<1)
|
|
|
|
#define ITEM_TOP (1<<2)
|
|
|
|
#define ITEM_BOTTOM (1<<3)
|
|
|
|
|
|
|
|
enum class ItemHandle : uint32_t {
|
|
|
|
None = 0,
|
|
|
|
TopLeft = ITEM_TOP | ITEM_LEFT,
|
|
|
|
TopCenter = ITEM_TOP,
|
|
|
|
TopRight = ITEM_TOP | ITEM_RIGHT,
|
|
|
|
CenterLeft = ITEM_LEFT,
|
|
|
|
CenterRight = ITEM_RIGHT,
|
|
|
|
BottomLeft = ITEM_BOTTOM | ITEM_LEFT,
|
|
|
|
BottomCenter = ITEM_BOTTOM,
|
|
|
|
BottomRight = ITEM_BOTTOM | ITEM_RIGHT
|
|
|
|
};
|
|
|
|
|
|
|
|
class OBSBasicPreview : public OBSQTDisplay {
|
|
|
|
Q_OBJECT
|
|
|
|
|
|
|
|
private:
|
|
|
|
OBSSceneItem stretchItem;
|
|
|
|
ItemHandle stretchHandle = ItemHandle::None;
|
|
|
|
vec2 stretchItemSize;
|
|
|
|
matrix4 screenToItem;
|
|
|
|
matrix4 itemToScreen;
|
|
|
|
|
|
|
|
vec2 startPos;
|
|
|
|
vec2 lastMoveOffset;
|
|
|
|
bool mouseDown = false;
|
|
|
|
bool mouseMoved = false;
|
|
|
|
bool mouseOverItems = false;
|
|
|
|
|
|
|
|
static vec2 GetMouseEventPos(QMouseEvent *event);
|
2014-09-25 17:44:05 -07:00
|
|
|
static bool DrawSelectedItem(obs_scene_t *scene, obs_sceneitem_t *item,
|
UI: Add scene editing
So, scene editing was interesting (and by interesting I mean
excruciating). I almost implemented 'manipulator' visuals (ala 3dsmax
for example), and used 3 modes for controlling position/rotation/size,
but in a 2D editing, it felt clunky, so I defaulted back to simply
click-and-drag for movement, and then took a similar though slightly
different looking approach for handling scaling and reszing.
I also added a number of menu item helpers related to positioning,
scaling, rotating, flipping, and resetting the transform back to
default.
There is also a new 'transform' dialog (accessible via menu) which will
allow you to manually edit every single transform variable of a scene
item directly if desired.
If a scene item does not have bounds active, pulling on the sides of a
source will cause it to resize it via base scale rather than by the
bounding box system (if the source resizes that scale will apply). If
bounds are active, it will modify the bounding box only instead.
How a source scales when a bounding box is active depends on the type of
bounds being used. You can set it to scale to the inner bounds, the
outer bounds, scale to bounds width only, scale to bounds height only,
and a setting to stretch to bounds (which forces a source to always draw
at the bounding box size rather than be affected by its internal size).
You can also set it to be used as a 'maximum' size, so that the source
doesn't necessarily get scaled unless it extends beyond the bounds.
Like in OBS1, objects will snap to the edges unless the control key is
pressed. However, this will now happen even if the object is rotated or
oriented in any strange way. Snapping will also occur when stretching
or changing the bounding box size.
2014-06-15 00:54:48 -07:00
|
|
|
void *param);
|
|
|
|
|
|
|
|
static OBSSceneItem GetItemAtPos(const vec2 &pos, bool selectBelow);
|
|
|
|
static bool SelectedAtPos(const vec2 &pos);
|
|
|
|
|
|
|
|
static void DoSelect(const vec2 &pos);
|
|
|
|
static void DoCtrlSelect(const vec2 &pos);
|
|
|
|
|
|
|
|
static vec3 GetScreenSnapOffset(const vec3 &tl, const vec3 &br);
|
|
|
|
|
|
|
|
void GetStretchHandleData(const vec2 &pos);
|
|
|
|
|
|
|
|
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 StretchItem(const vec2 &pos);
|
|
|
|
|
|
|
|
static void SnapItemMovement(vec2 &offset);
|
|
|
|
void MoveItems(const vec2 &pos);
|
|
|
|
|
|
|
|
void ProcessClick(const vec2 &pos);
|
|
|
|
|
|
|
|
public:
|
|
|
|
OBSBasicPreview(QWidget *parent, Qt::WindowFlags flags = 0);
|
|
|
|
|
|
|
|
virtual void mousePressEvent(QMouseEvent *event) override;
|
|
|
|
virtual void mouseReleaseEvent(QMouseEvent *event) override;
|
|
|
|
virtual void mouseMoveEvent(QMouseEvent *event) override;
|
|
|
|
|
|
|
|
void DrawSceneEditing();
|
|
|
|
|
|
|
|
/* use libobs allocator for alignment because the matrices itemToScreen
|
|
|
|
* and screenToItem may contain SSE data, which will cause SSE
|
|
|
|
* instructions to crash if the data is not aligned to at least a 16
|
|
|
|
* byte boundry. */
|
|
|
|
static inline void* operator new(size_t size) {return bmalloc(size);}
|
|
|
|
static inline void operator delete(void* ptr) {bfree(ptr);}
|
|
|
|
};
|