Skip to content

frontend: Improve preview source snapping - #12298

Open
Warchamp7 wants to merge 4 commits into
obsproject:masterfrom
Warchamp7:more-snapping
Open

frontend: Improve preview source snapping#12298
Warchamp7 wants to merge 4 commits into
obsproject:masterfrom
Warchamp7:more-snapping

Conversation

@Warchamp7

@Warchamp7 Warchamp7 commented Jun 19, 2025

Copy link
Copy Markdown
Member

Description

This PR makes a number of changes to source snapping in the preview:

  • Sources no longer snap to hidden sources
  • Edges can now snap to the same axis edge of other sources
    • Ex. The top edge of a source can now snap to the top edge of another source
  • Sources snap along the entire axis
    • Sources don't have to be touching to snap
  • Visual indicators for snapping
  • Replaces calculation macro with a static method

Additionally

  • Changes the default snap distance from 10.0 -> 5.0
  • Hidden sources can no longer be hovered or clicked in the preview to select them
obs64_wuvM7eemGG.mp4

Motivation and Context

I want to improve source snapping behaviour and visual feedback

How Has This Been Tested?

Moved a bunch of sources around. Toggled relevant snapping settings on and off to ensure behaviour matched settings.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • Tweak (non-breaking change to improve existing functionality)
  • Code cleanup (non-breaking change which makes code smaller or more readable)

Checklist:

  • My code has been run through clang-format.
  • I have read the contributing document.
  • My code is not on the master branch.
  • The code has been tested.
  • All commit messages are properly formatted and commits squashed where appropriate.
  • I have included updates to all appropriate documentation.

@Warchamp7 Warchamp7 added the area/ui-ux Anything to do with changes or additions to UI/UX elements. label Jun 19, 2025
@Warchamp7 Warchamp7 added this to the OBS Studio 32.0 milestone Jun 19, 2025
@WizardCM WizardCM added the kind/enhancement Enhancements are not bugs or new features but can improve usability or performance. label Jun 21, 2025
@Warchamp7
Warchamp7 requested a review from PatTheMav September 23, 2025 21:47

@PatTheMav PatTheMav left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Functionally this PR is fine, but it seems very brute force and not particularly efficient to me and falls victim to "featuritis", just piling on little features one by one, each doing its own thing in isolation with no regard to other (similar) features and the architecture behind it.

Preview control drawing should be a single process, by a single responsible entity in code that knows about all of its "features" and thus set up a single render pass to draw all the pieces it knows should be visible for any given frame.

Comment thread frontend/widgets/OBSBasicPreview.cpp
Comment thread frontend/widgets/OBSBasicPreview.cpp Outdated
Comment thread frontend/widgets/OBSBasicPreview.cpp Outdated
Comment thread frontend/widgets/OBSBasicPreview.cpp
@Warchamp7 Warchamp7 moved this to Ready For Review in OBS Studio 32.1 PR Considerations Oct 29, 2025
@RytoEX RytoEX moved this from Ready For Review to Requires Changes in OBS Studio 32.1 PR Considerations Dec 18, 2025
@Warchamp7 Warchamp7 moved this from Requires Changes to Ready For Review in OBS Studio 32.1 PR Considerations Jan 8, 2026
@Warchamp7
Warchamp7 force-pushed the more-snapping branch 2 times, most recently from a7a004e to f53cd97 Compare January 13, 2026 22:10
@RytoEX
RytoEX requested a review from PatTheMav May 8, 2026 18:41
@Warchamp7
Warchamp7 force-pushed the more-snapping branch 2 times, most recently from 152442d to 02623d0 Compare June 15, 2026 22:28
@Warchamp7

Copy link
Copy Markdown
Member Author

I've added another commit that updates the default snap distance from 10.0 -> 5.0 and will migrate the old value one time. Since the snap distance is scaled by preview zoom level the default value of 10 is pretty aggressive especially with more snap candidates now.

@@ -31,6 +31,17 @@ enum class ItemHandle : uint32_t {
Rot = ITEM_ROT
};

struct SnapGuide {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a global type or would it make more sense to make it a nested type of OBSBasicPreview, given its limited usage?

Comment thread frontend/widgets/OBSBasicPreview.cpp Outdated
#define HELPER_ROT_BREAKPOINT 45.0f

namespace {
bool checkEdgeSnap(float moveAxis, float checkAxis, float clampDistance, float &offset)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A function named checkSomething should not have side-effects. What is the purpose of updating the offset as part of the check?

If the update is required, there's two cleaner ways to do it:

  • Either return an optional value, which is only set when the check succeeds.
  • Or return a struct which contains the check result as well as updated values.

@@ -893,15 +926,32 @@ static bool AddItemBounds(obs_scene_t * /* scene */, obs_sceneitem_t *item, void
struct OffsetData {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per our style guidelines, struct should only be used for "dumb" data structures. As soon as you add any methods to it, it needs to become a class.

I am on the fence about this - coming from Swift it feels natural to have structured data with "helper" methods embedded within the type, and as soon as you need actual heap-allocated objects which you share via references you use classes.

Probably worth amending our style guideline to make this deviation from Google's guidelines explicit, because I do not see much value in turning OffsetData into a class , just because you add helper functions to it.

Comment thread frontend/widgets/OBSBasicPreview.hpp Outdated
vec2 start;
vec2 end;

SnapGuide(float x1, float y1, float x2, float y2)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The constructor violates best practices from our style guide, because it forces the deconstruction of semantically linked values (x,y-coordinate pairs in this case) into distinct values, which opens up new ways to pass wrong data.

Indeed the code above should probably look more like this:

	if (checkEdgeSnap(movingEdge.x(), itemEdge.x(), data->clampDist, data->offset.x)) {
        vec2 startPoint {itemEdge.x(), 0.0f};
        vec2 endPoint {itemEdge.x(), screen.y};
		main->addSnapGuide({startPoint, endPoint});

The compiler will automatically pick up the desired type SnapGuide from the signature of addSnapGuide and thus take those two vec2's to create one explicitly.

The lines are shorter and easier to read, the relationship between the values is clear. Points or origins should be represented by the type system and consistently used by it. Qt itself uses QPoint for that reason (which could and maybe should(?) be used instead of vec2?).

Comment thread frontend/OBSApp.cpp Outdated
extern "C" __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
#endif

static constexpr double kDefaultSnapDistance = 5.0;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
static constexpr double kDefaultSnapDistance = 5.0;
constexpr double kDefaultSnapDistance = 5.0;

static is superfluous.

@github-project-automation github-project-automation Bot moved this from Ready For Review to Requires Changes in 33.0 Release Tracker Aug 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/ui-ux Anything to do with changes or additions to UI/UX elements. kind/enhancement Enhancements are not bugs or new features but can improve usability or performance.

Projects

Status: Requires Changes

Development

Successfully merging this pull request may close these issues.

4 participants