Table of Contents
Control Input
The pointer's events go to the control under the pointer, and the keys to the one with the keyboard focus, as in Godot; a control may drag what it shows and take what is dropped on it.
- Input: a control's class handles its input in a
gui-inputmethod. The pointer's events go to the topmost control under the pointer, in the control's coordinates, and on up to its parents ascontrol-pointer-filtersays::stop, the default, keeps them from its parents, and fromunhandled-input;:pass, a container's default, gives its parent those it does not handle;:ignorelets them through to what is under it. A control that takes a button press gets the pointer's events until every button is up, wherever the pointer goes. The control under the pointer hearspointer-enteredandpointer-exited, and the window shows itscontrol-cursor, such as:textor:pointer. A control of your own counts double and triple clicks withcount-click, in amake-clicksof its own, as the lists do. - Focus: keys, text and an input method's events go to the control
with the keyboard focus, and on up to its parents until one handles
them. A control takes the focus as
control-focus-modeallows::none, the default;:click, when the left button presses it;:all, also when Tab, Shift+Tab or an arrow key moves the focus to it. Tab goes through the tree's order; an arrow goes to the nearest control on its side. These are Godot's built-in actions,:ui-focus-next,:ui-focus-prev,:ui-leftand the rest, matched exactly, which a game may bind to other keys (see Input and Actions), as every control takes its keys: a button:ui-accept, a popup and a dialog:ui-cancel, a list and a tree the arrows', page and select actions, a text field the:ui-text-ones, the clipboard's and history's, each as Godot's control of the kind takes them.grab-focus,release-focus,control-has-focus-pandfocus-ownerdo the rest, and a control hearsfocus-enteredandfocus-exited. A click where no control is takes the focus away, so the keys go back to the game. Each of these callbacks is a signal of the same name too,gui-inputwith the event. - Drag and drop within a window, as Godot's: a press that moves
(drag-threshold)units, 10 unless set, asks the control pressed, and on up through its parents as their pointer filters pass the pointer on, for what it drags, in itscontrol-drag-datamethod; the first that gives something starts a drag of it, andset-drag-previewhas a control follow the pointer meanwhile. The control under the pointer, and on up, is asked withcan-drop-data-pwhether it takes it, the window showing:grabbingover one that does and:no-dropover one that does not, and gets it indrop-dataas the button comes up.:ui-cancel, Escape, or the right button cancels.dragging-p,dragged-dataanddrag-successful-ptell how it goes, every control of the window hearsdrag-begananddrag-ended, andforce-dragbegins a drag from code. Tab bars and tab containers move tabs by dragging with:drag-to-rearrange-enabled t, between those of one:tabs-rearrange-grouptoo; a tree shows where a drag would drop astree-drop-mode-flagsasks; and a line edit's selection drags as text.
A control takes input in its class's gui-input method. Turn the tiles
of the grid of Containers into lamps, which light up and go
out as they are clicked, or as Space is pressed while one has the
keyboard focus. A lamp draws the style box its state names, :on or
:off, from the theme the grid holds:
(sc:define-node lamp (ui:panel)
((lit :initform nil :accessor lamp-lit :type boolean)))
(defmethod s2d:draw ((lamp lamp) canvas)
(ui:draw-style-box (ui:control-style-box lamp (if (lamp-lit lamp) :on :off)) canvas
0 0 (ui:control-width lamp) (ui:control-height lamp)))
(defmethod ui:gui-input ((lamp lamp) event)
(when (or (and (typep event 'sc:button-event) (sc:event-pressed-p event)
(eq (sc:event-button event) :left))
(and (typep event 'sc:key-event) (sc:event-pressed-p event)
(eq (sc:event-key event) :space)))
(setf (lamp-lit lamp) (not (lamp-lit lamp))
(sc:event-handled-p event) t)
(s2d:queue-redraw lamp)))
(sc:call-in-tree *tree*
(lambda ()
(let ((grid (part *tree* "layout/columns/grid")))
(setf (ui:control-theme grid)
(make-instance 'ui:theme
:style-boxes `((lamp :off ,(rounded '(0.6 0.45 0.3))
:on ,(rounded '(1 0.85 0.4))))))
(dolist (tile (sc:node-children grid))
(sc:queue-free tile))
(dotimes (index 9)
(add grid (make-instance 'lamp :custom-minimum-height 60
:expand-horizontal t
:focus-mode :all :cursor :pointer))))))
Over a lamp the pointer is a hand. A click lights it and gives it the focus, which Tab and the arrow keys then move from lamp to lamp, and Space lights the lamp that has it.
A control class of your own drags and drops with three methods. Paint the tiles of the docks of Containers, which drag their colours and take colours dropped on them:
(sc:define-node paint (ui:panel) ())
(defun paint (color &rest initargs)
(apply #'make-instance 'paint :style-box-overrides (list :panel (rounded color)) initargs))
(defun paint-color (paint)
(ui:style-box-background-color (ui:control-style-box paint :panel)))
(defmethod ui:control-drag-data ((paint paint) x y)
(declare (ignore x y))
(ui:set-drag-preview paint (paint (paint-color paint) :offset-right 24 :offset-bottom 24))
(paint-color paint))
(defmethod ui:can-drop-data-p ((paint paint) x y data)
(declare (ignore x y))
(pyssel/2d:colorp data))
(defmethod ui:drop-data ((paint paint) x y color)
(declare (ignore x y))
(setf (ui:control-style-box paint :panel) (rounded color)))
(sc:call-in-tree *docks*
(lambda ()
(let ((flow (part *docks* "docks/flow")))
(dolist (tile (sc:node-children flow))
(sc:queue-free tile))
(dolist (color '((0.8 0.3 0.3) (0.3 0.7 0.4) (0.3 0.4 0.8) (0.9 0.8 0.3)))
(add flow (paint color :custom-minimum-width 80 :custom-minimum-height 60))))))
Drag a tile onto another: a square of its colour follows the pointer, the pointer shows whether the control under it takes the colour, and the tile under it takes it as the button comes up. Escape or the right button cancels the drag.
Getting started
The core
Drawing
Scenes
User interface
Games and the editor
- Playing a Game
- Projects
- The Editor
- The File System Dock
- The Script Screen
- The REPL
- The Debugger
- Lisp Text
- Code Services
- Project Manager
- Undo and Redo
- Exporting
The project