mirror of
https://github.com/obsproject/obs-studio.git
synced 2024-07-19 17:49:14 +00:00
UI: Allow zoom with the scroll wheel
Adds the ability to zoom into the preview when fixed scaling mode is enabled. (Edit by Jim: Also now saves zoom and scroll position) Closes jp9000/obs-studio#917
This commit is contained in:
parent
d70c97db3a
commit
8942c18695
|
@ -430,8 +430,14 @@ void OBSBasic::Save(const char *file)
|
|||
savedPreviewProjectorList);
|
||||
|
||||
obs_data_set_bool(saveData, "preview_locked", ui->preview->Locked());
|
||||
obs_data_set_int(saveData, "scaling_mode",
|
||||
static_cast<uint32_t>(ui->preview->GetScalingMode()));
|
||||
obs_data_set_bool(saveData, "scaling_enabled",
|
||||
ui->preview->IsFixedScaling());
|
||||
obs_data_set_int(saveData, "scaling_level",
|
||||
ui->preview->GetScalingLevel());
|
||||
obs_data_set_double(saveData, "scaling_off_x",
|
||||
ui->preview->GetScrollX());
|
||||
obs_data_set_double(saveData, "scaling_off_y",
|
||||
ui->preview->GetScrollY());
|
||||
|
||||
if (api) {
|
||||
obs_data_t *moduleObj = obs_data_create();
|
||||
|
@ -771,18 +777,20 @@ retryScene:
|
|||
ui->preview->SetLocked(previewLocked);
|
||||
ui->actionLockPreview->setChecked(previewLocked);
|
||||
|
||||
ScalingMode previewScaling = static_cast<ScalingMode>(
|
||||
obs_data_get_int(data, "scaling_mode"));
|
||||
switch (previewScaling) {
|
||||
case ScalingMode::Window:
|
||||
case ScalingMode::Canvas:
|
||||
case ScalingMode::Output:
|
||||
break;
|
||||
default:
|
||||
previewScaling = ScalingMode::Window;
|
||||
}
|
||||
/* ---------------------- */
|
||||
|
||||
ui->preview->SetScaling(previewScaling);
|
||||
bool fixedScaling = obs_data_get_bool(data, "scaling_enabled");
|
||||
int scalingLevel = (int)obs_data_get_int(data, "scaling_level");
|
||||
float scrollOffX = (float)obs_data_get_double(data, "scaling_off_x");
|
||||
float scrollOffY = (float)obs_data_get_double(data, "scaling_off_y");
|
||||
|
||||
if (fixedScaling) {
|
||||
ui->preview->SetScalingLevel(scalingLevel);
|
||||
ui->preview->SetScrollingOffset(scrollOffX, scrollOffY);
|
||||
}
|
||||
ui->preview->SetFixedScaling(fixedScaling);
|
||||
|
||||
/* ---------------------- */
|
||||
|
||||
if (api) {
|
||||
obs_data_t *modulesObj = obs_data_get_obj(data, "modules");
|
||||
|
@ -1848,13 +1856,22 @@ OBSSceneItem OBSBasic::GetCurrentSceneItem()
|
|||
|
||||
void OBSBasic::UpdatePreviewScalingMenu()
|
||||
{
|
||||
ScalingMode scalingMode = ui->preview->GetScalingMode();
|
||||
ui->actionScaleWindow->setChecked(
|
||||
scalingMode == ScalingMode::Window);
|
||||
ui->actionScaleCanvas->setChecked(
|
||||
scalingMode == ScalingMode::Canvas);
|
||||
bool fixedScaling = ui->preview->IsFixedScaling();
|
||||
float scalingAmount = ui->preview->GetScalingAmount();
|
||||
if (!fixedScaling) {
|
||||
ui->actionScaleWindow->setChecked(true);
|
||||
ui->actionScaleCanvas->setChecked(false);
|
||||
ui->actionScaleOutput->setChecked(false);
|
||||
return;
|
||||
}
|
||||
|
||||
obs_video_info ovi;
|
||||
obs_get_video_info(&ovi);
|
||||
|
||||
ui->actionScaleWindow->setChecked(false);
|
||||
ui->actionScaleCanvas->setChecked(scalingAmount == 1.0f);
|
||||
ui->actionScaleOutput->setChecked(
|
||||
scalingMode == ScalingMode::Output);
|
||||
scalingAmount == float(ovi.output_width) / float(ovi.base_width));
|
||||
}
|
||||
|
||||
void OBSBasic::UpdateSources(OBSScene scene)
|
||||
|
@ -2844,32 +2861,23 @@ void OBSBasic::ResetAudioDevice(const char *sourceId, const char *deviceId,
|
|||
void OBSBasic::ResizePreview(uint32_t cx, uint32_t cy)
|
||||
{
|
||||
QSize targetSize;
|
||||
ScalingMode scalingMode;
|
||||
bool isFixedScaling;
|
||||
obs_video_info ovi;
|
||||
|
||||
/* resize preview panel to fix to the top section of the window */
|
||||
targetSize = GetPixelSize(ui->preview);
|
||||
|
||||
scalingMode = ui->preview->GetScalingMode();
|
||||
isFixedScaling = ui->preview->IsFixedScaling();
|
||||
obs_get_video_info(&ovi);
|
||||
|
||||
if (scalingMode == ScalingMode::Canvas) {
|
||||
previewScale = 1.0f;
|
||||
if (isFixedScaling) {
|
||||
previewScale = ui->preview->GetScalingAmount();
|
||||
GetCenterPosFromFixedScale(int(cx), int(cy),
|
||||
targetSize.width() - PREVIEW_EDGE_SIZE * 2,
|
||||
targetSize.height() - PREVIEW_EDGE_SIZE * 2,
|
||||
previewX, previewY, previewScale);
|
||||
previewX += ui->preview->ScrollX();
|
||||
previewY += ui->preview->ScrollY();
|
||||
|
||||
} else if (scalingMode == ScalingMode::Output) {
|
||||
previewScale = float(ovi.output_width) / float(ovi.base_width);
|
||||
GetCenterPosFromFixedScale(int(cx), int(cy),
|
||||
targetSize.width() - PREVIEW_EDGE_SIZE * 2,
|
||||
targetSize.height() - PREVIEW_EDGE_SIZE * 2,
|
||||
previewX, previewY, previewScale);
|
||||
previewX += ui->preview->ScrollX();
|
||||
previewY += ui->preview->ScrollY();
|
||||
previewX += ui->preview->GetScrollX();
|
||||
previewY += ui->preview->GetScrollY();
|
||||
|
||||
} else {
|
||||
GetScaleAndCenterPos(int(cx), int(cy),
|
||||
|
@ -5290,26 +5298,38 @@ void OBSBasic::on_scalingMenu_aboutToShow()
|
|||
text = text.arg(QString::number(ovi.output_width),
|
||||
QString::number(ovi.output_height));
|
||||
action->setText(text);
|
||||
action->setVisible(!(ovi.output_width == ovi.base_width &&
|
||||
ovi.output_height == ovi.base_height));
|
||||
|
||||
UpdatePreviewScalingMenu();
|
||||
}
|
||||
|
||||
void OBSBasic::on_actionScaleWindow_triggered()
|
||||
{
|
||||
ui->preview->SetScaling(ScalingMode::Window);
|
||||
ui->preview->SetFixedScaling(false);
|
||||
ui->preview->ResetScrollingOffset();
|
||||
emit ui->preview->DisplayResized();
|
||||
}
|
||||
|
||||
void OBSBasic::on_actionScaleCanvas_triggered()
|
||||
{
|
||||
ui->preview->SetScaling(ScalingMode::Canvas);
|
||||
ui->preview->SetFixedScaling(true);
|
||||
ui->preview->SetScalingLevel(0);
|
||||
emit ui->preview->DisplayResized();
|
||||
}
|
||||
|
||||
void OBSBasic::on_actionScaleOutput_triggered()
|
||||
{
|
||||
ui->preview->SetScaling(ScalingMode::Output);
|
||||
obs_video_info ovi;
|
||||
obs_get_video_info(&ovi);
|
||||
|
||||
ui->preview->SetFixedScaling(true);
|
||||
float scalingAmount = float(ovi.output_width) / float(ovi.base_width);
|
||||
// log base ZOOM_SENSITIVITY of x = log(x) / log(ZOOM_SENSITIVITY)
|
||||
int32_t approxScalingLevel = int32_t(
|
||||
round(log(scalingAmount) / log(ZOOM_SENSITIVITY)));
|
||||
ui->preview->SetScalingLevel(approxScalingLevel);
|
||||
ui->preview->SetScalingAmount(scalingAmount);
|
||||
emit ui->preview->DisplayResized();
|
||||
}
|
||||
|
||||
|
|
|
@ -382,8 +382,7 @@ void OBSBasicPreview::GetStretchHandleData(const vec2 &pos)
|
|||
|
||||
void OBSBasicPreview::keyPressEvent(QKeyEvent *event)
|
||||
{
|
||||
if (GetScalingMode() == ScalingMode::Window ||
|
||||
event->isAutoRepeat()) {
|
||||
if (!IsFixedScaling() || event->isAutoRepeat()) {
|
||||
OBSQTDisplay::keyPressEvent(event);
|
||||
return;
|
||||
}
|
||||
|
@ -415,9 +414,23 @@ void OBSBasicPreview::keyReleaseEvent(QKeyEvent *event)
|
|||
OBSQTDisplay::keyReleaseEvent(event);
|
||||
}
|
||||
|
||||
void OBSBasicPreview::wheelEvent(QWheelEvent *event)
|
||||
{
|
||||
if (scrollMode && IsFixedScaling()
|
||||
&& event->orientation() == Qt::Vertical) {
|
||||
if (event->delta() > 0)
|
||||
SetScalingLevel(scalingLevel + 1);
|
||||
else if (event->delta() < 0)
|
||||
SetScalingLevel(scalingLevel - 1);
|
||||
emit DisplayResized();
|
||||
}
|
||||
|
||||
OBSQTDisplay::wheelEvent(event);
|
||||
}
|
||||
|
||||
void OBSBasicPreview::mousePressEvent(QMouseEvent *event)
|
||||
{
|
||||
if (scrollMode && GetScalingMode() != ScalingMode::Window &&
|
||||
if (scrollMode && IsFixedScaling() &&
|
||||
event->button() == Qt::LeftButton) {
|
||||
setCursor(Qt::ClosedHandCursor);
|
||||
scrollingFrom.x = event->x();
|
||||
|
@ -1205,3 +1218,15 @@ void OBSBasicPreview::ResetScrollingOffset()
|
|||
{
|
||||
vec2_zero(&scrollingOffset);
|
||||
}
|
||||
|
||||
void OBSBasicPreview::SetScalingLevel(int32_t newScalingLevelVal) {
|
||||
float newScalingAmountVal = pow(ZOOM_SENSITIVITY, float(newScalingLevelVal));
|
||||
scalingLevel = newScalingLevelVal;
|
||||
SetScalingAmount(newScalingAmountVal);
|
||||
}
|
||||
|
||||
void OBSBasicPreview::SetScalingAmount(float newScalingAmountVal) {
|
||||
scrollingOffset.x *= newScalingAmountVal / scalingAmount;
|
||||
scrollingOffset.y *= newScalingAmountVal / scalingAmount;
|
||||
scalingAmount = newScalingAmountVal;
|
||||
}
|
|
@ -14,6 +14,8 @@ class QMouseEvent;
|
|||
#define ITEM_TOP (1<<2)
|
||||
#define ITEM_BOTTOM (1<<3)
|
||||
|
||||
#define ZOOM_SENSITIVITY 1.125f
|
||||
|
||||
enum class ItemHandle : uint32_t {
|
||||
None = 0,
|
||||
TopLeft = ITEM_TOP | ITEM_LEFT,
|
||||
|
@ -26,12 +28,6 @@ enum class ItemHandle : uint32_t {
|
|||
BottomRight = ITEM_BOTTOM | ITEM_RIGHT
|
||||
};
|
||||
|
||||
enum class ScalingMode : uint32_t {
|
||||
Window = 0,
|
||||
Canvas = 1,
|
||||
Output = 2
|
||||
};
|
||||
|
||||
class OBSBasicPreview : public OBSQTDisplay {
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -41,7 +37,6 @@ private:
|
|||
vec2 cropSize;
|
||||
OBSSceneItem stretchItem;
|
||||
ItemHandle stretchHandle = ItemHandle::None;
|
||||
ScalingMode scale = ScalingMode::Window;
|
||||
vec2 stretchItemSize;
|
||||
matrix4 screenToItem;
|
||||
matrix4 itemToScreen;
|
||||
|
@ -56,6 +51,9 @@ private:
|
|||
bool cropping = false;
|
||||
bool locked = false;
|
||||
bool scrollMode = false;
|
||||
bool fixedScaling = false;
|
||||
int32_t scalingLevel = 0;
|
||||
float scalingAmount = 1.0f;
|
||||
|
||||
static vec2 GetMouseEventPos(QMouseEvent *event);
|
||||
static bool DrawSelectedItem(obs_scene_t *scene, obs_sceneitem_t *item,
|
||||
|
@ -88,22 +86,30 @@ public:
|
|||
virtual void keyPressEvent(QKeyEvent *event) override;
|
||||
virtual void keyReleaseEvent(QKeyEvent *event) override;
|
||||
|
||||
virtual void wheelEvent(QWheelEvent *event) override;
|
||||
|
||||
virtual void mousePressEvent(QMouseEvent *event) override;
|
||||
virtual void mouseReleaseEvent(QMouseEvent *event) override;
|
||||
virtual void mouseMoveEvent(QMouseEvent *event) override;
|
||||
|
||||
void DrawSceneEditing();
|
||||
void ResetScrollingOffset();
|
||||
|
||||
inline void SetLocked(bool newLockedVal) {locked = newLockedVal;}
|
||||
inline void ToggleLocked() {locked = !locked;}
|
||||
inline bool Locked() const {return locked;}
|
||||
|
||||
inline void SetScaling(ScalingMode newScaledVal) {scale = newScaledVal;}
|
||||
inline ScalingMode GetScalingMode() const {return scale;}
|
||||
inline void SetFixedScaling(bool newFixedScalingVal) { fixedScaling = newFixedScalingVal; }
|
||||
inline bool IsFixedScaling() const { return fixedScaling; }
|
||||
|
||||
inline float ScrollX() const {return scrollingOffset.x;}
|
||||
inline float ScrollY() const {return scrollingOffset.y;}
|
||||
void SetScalingLevel(int32_t newScalingLevelVal);
|
||||
void SetScalingAmount(float newScalingAmountVal);
|
||||
inline int32_t GetScalingLevel() const { return scalingLevel; }
|
||||
inline float GetScalingAmount() const { return scalingAmount; }
|
||||
|
||||
void ResetScrollingOffset();
|
||||
inline void SetScrollingOffset(float x, float y) {vec2_set(&scrollingOffset, x, y);}
|
||||
inline float GetScrollX() const {return scrollingOffset.x;}
|
||||
inline float GetScrollY() const {return scrollingOffset.y;}
|
||||
|
||||
/* use libobs allocator for alignment because the matrices itemToScreen
|
||||
* and screenToItem may contain SSE data, which will cause SSE
|
||||
|
|
Loading…
Reference in a new issue