Missing InputEnded after Plugin:StartDrag

If I start a drag-and-drop operation from a Studio plugin by a call to Plugin:StartDrag from an InputBegan event for MouseButton1, it seems the first MouseButton1 event doesn’t “end”, until a second click in the same plugin GUI “finishes” it.

Sample plugin code:

local win = plugin:CreateDockWidgetPluginGui(
	"StartDragTest_Window",
    DockWidgetPluginGuiInfo.new(Enum.InitialDockState.Float, true, true)
)
win.Name = "StartDragTest_Window"
win.Title = "StartDrag Test"
local frame = Instance.new("Frame", win)
frame.Size = UDim2.new(1,0,1,0)
local square = Instance.new("Frame", frame)
square.Size = UDim2.new(.5,0,.5,0)
square.BackgroundColor3 = Color3.new(.1, 1, .1)

win.PluginDragEntered:Connect(function() print "DragEntered" end)
win.PluginDragMoved:Connect(function() print "DragMoved" end)
win.PluginDragLeft:Connect(function() print "DragLeft" end)
win.PluginDragDropped:Connect(function() print "DragDropped" end)

local function InputToStr(input)
	return "{type=" .. input.UserInputType.Name ..
		", state=" .. input.UserInputState.Name .. "}"
end

frame.InputBegan:Connect(function (input)
	if input.UserInputType == Enum.UserInputType.MouseButton1 then
		print("InputBegan ", InputToStr(input))
		if input.Position.X <= square.AbsoluteSize.X and
		   input.Position.Y <= square.AbsoluteSize.Y then
		    plugin:StartDrag({})
		end
	end
end)
frame.InputChanged:Connect(function (input)
	if not (input.UserInputType == Enum.UserInputType.MouseMovement and
			input.UserInputState == Enum.UserInputState.Change) then
		print("InputChanged ", InputToStr(input))
	end
end)
frame.InputEnded:Connect(function (input)
	print("InputEnded", InputToStr(input))
end)

The plugin creates a window which is mostly gray containing a green square, and sets up some debug traces of input events. Click, or click-and-drag, on the gray region to see the events from the normal case:

Press and hold mouse button 1 over the gray area:
  InputBegan {type=MouseButton1, state=Begin}
Move the mouse - not traced.
Release mouse button 1:
  InputEnded {type=MouseButton1, state=End}

Clicking on the green square adds the call to plugin:StartDrag({}) during the InputBegan. In that case, there’s no InputEnded when I’d expect, and a following click on the gray area doesn’t behave right at all:

Press and hold mouse button 1 over the green square:
  InputBegan {type=MouseButton1, state=Begin}
Move the mouse:
  DragEntered
  DragMoved (xN)
Release mouse button 1:
  DragDropped
  InputEnded {type=MouseMovement, state=End}
Press and hold mouse button 1 over the gray area:
  InputChanged {type=MouseButton1, state=Begin}
Release mouse button 1:
  InputEnded {type=MouseButton1, state=End}

It seems the argument to Plugin:StartDrag should be a Lua table optionally containing keys like the properties of a PluginDragEvent. A copy of this table is passed back to the PluginDrag* event handlers, except that when a property is missing, there’s instead a table element with the property’s name and an empty string or zero vector value. So I just passed the empty table {}.

It’s possible I’m missing some important step, since Plugin:StartDrag, PluginGui.PluginDragDropped, PluginGui.PluginDragEntered, PluginGui.PluginDragLeft, and PluginGui.PluginDragMoved have essentially no documentation. But this seems like the changes to the second click’s behavior shouldn’t happen in any case.

Somewhat related, if a drag-and-drop starts and the user moves the mouse outside and releases the mouse button while not pointing at any plugin window at all, I don’t see any way to detect when the mouse button was released.

1 Like