Adding Drag & Drop Support via Draggables & Slots#55
Merged
Jake-Rich merged 18 commits intoFacepunch:drag_dropfrom Feb 12, 2025
Merged
Adding Drag & Drop Support via Draggables & Slots#55Jake-Rich merged 18 commits intoFacepunch:drag_dropfrom
Jake-Rich merged 18 commits intoFacepunch:drag_dropfrom
Conversation
Added the JSON API required to setup & update Draggables & Slots. Also added the ability to reparent & order a transform if called via an update call, this is needed to allow reparenting a Draggable
Fix a potential illegal swap when a panel inside a restricted slot was swapped with a non-slotted panel. Changed DragRPC to not send when a swap/attach operation fails & the panel will reset to its last position, the change was made because in those situations, a player didnt intend to drag the panel, they intended to attach it.
fixed attachement fail sending a DragRPC, also properly sets the position of panels that can be dropped anywhere
4 tasks
the previous approach used offsets, only modifying the position if the new position would be within bounds. this caused awkward behaviour where the dragged object would stop long before its actual bounds. this was also framerate dependant as it would make bigger leaps on lower framerates, making it more likely that the new position would have been out of bounds and increasing the apparent distance from its bounds after actually testing the PR in game i've realized it is safe to just use the absolute position (anchor + offset) and to constrain that to the rect with respect to the padding.
adding default sprites and changed some images to use Image instead
the draggable now consider's both the parent's position and scale instead of just its scale when determining if its bounds need to be recached - this solves an issue with animated elements having cached old bounds the anchor now also gets parented based on the parentLimitIndex, previously it was parented to the draggable's initial parent which brought with it unwanted behaviour when that parent was moving
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implementing Drag & Drop into our UIs
The Breakdown
this PR adds 2 components, a
Draggablecomponent and aSlotcomponent. the Draggable Component is responsible for the dragging interaction, sending RPCs to the server, & keeping itself within the constraints. the Slot Component's purpose is to allow draggables to be attached to the panel, with an optional primitive string filter to only allow draggables with a matching filter in.Demo:
Drag-n-Drop.mp4
Receiving RPCs
Draggable's will send 1 of 2 RPC calls on the CommunityEntity depending on which action is performed:
the position Type
the Draggable Component comes with 4 seperate position send types, you might prefer one over the other depending on your scenario:
the JSON Implementation - Draggable
{ "type":"Draggable", // All thats required to make the panel draggable "maxDistance": -1, // how far the draggable is allowed to be dragged from its parent "anchorOffset": "0 0", // if the anchor should be offset from the draggable's initial position the offset can be specified here "limitToParent": false, // Limits the Draggable to the closest non-slot parent, does not work combined with maxDistance "parentLimitIndex": 1, // if limitToParent is true, this index allows you to specify how many non slot parents it should traverse before finding the limit "parentPadding": "0 0", // if limitToParent is true, specifies additional padding that the draggable should be contained. can be negative to allow the draggable to slightly travel outside the parent "dropAnywhere": true, // if false, the draggable will return to its last valid position (its initial position by default) unless swapped or attached to a slot "keepOnTop": false, // if true the draggable will stay detached from its parent, reccomended for unrestricted draggables "allowSwapping": false, // if true the draggable can be swapped with other draggables if dragged ontop of eachother "dragAlpha": 1, // if the alpha of the draggable's graphics should be lowered while being dragged. "positionRPC": "NormalizedScreen", // how the position should be processed before being sent via RPCs* "filter": null // the filter string this draggable should carry, see #Slots & Filtering }* Depending on other settings the default value for the positionRPC field may change.
RelativeAnchorNormalizedParentthe JSON Implementation - Slot
{ "type":"Draggable", // All thats required to make the panel a slot "filter": null, // if not null it will only allow draggables with a matching filter string }Slots & Filtering
Slots come with a built in filter system that allows you to specify what draggables can be attached.
this is how the filtering is evaluated:
if the slot has no filter, any draggable can be inserted. if the slot has a filter it only allows Draggables with a matching filter property. in the demo video this is shown with the green Draggable & Slots, the gray slots will accept any draggable while the green slot will only accept the matching Draggable. this is accomplished by setting the filter string
when building a system arround slots & the swapping of Draggables, its reccomended to set the
dropAnywheresetting to false to make Draggables return to their last position if a