Add the ability to drag and drop Doodads onto the level. The Doodad
buttons on the palette now trigger a Drag/Drop behavior when clicked,
and a "blueprint colored" version of the Doodad follows your cursor,
centered on it.
Actors are assigned a random UUID ID when they are placed into a level.
The Canvas gained a MaskColor property that forces all pixels in the
drawing to render as the same color. This is a visual-only effect, and
is used when dragging Doodads in so they render as "blueprints" instead
of their actual colors until they are dropped.
Fix the chunk bitmap cache system so it saves in the $XDG_CACHE_FOLDER
instead of /tmp and has better names. They go into
`~/.config/doodle/chunks/` and have UUID file names -- but they
disappear quickly! As soon as they are cached into SDL2 they are removed
from disk.
Other changes:
- UI: Add Hovering() method that returns the widgets that are beneath
a point (your cursor) and those that are not, for easy querying
for event propagation.
- UI: Add ability to return an ErrStopPropagation to tell the master
Scene (outside the UI) not to continue sending events to other
parts of the code, so that you don't draw pixels during a drag
event.
* Add a tab bar to the top of the Palette window that has two
radiobuttons for "Palette" and "Doodads"
* UI: add the concept of a Hidden() widget and the corresponding Hide()
and Show() methods. Hidden widgets are skipped over when evaluating
Frame packing, rendering, and event supervision.
* The Palette Window in editor mode now displays one of two tabs:
* Palette: the old color swatch palette now lives here.
* Doodads: the new Doodad palette.
* The Doodad Palette shows a grid of buttons (2 per row) showing the
available Doodad drawings in the user's config folder.
* The Doodad buttons act as radiobuttons for now and have no other
effect. TODO will be making them react to drag-drop events.
* UI: added a `Children()` method as the inverse of `Parent()` for
container widgets (like Frame, Window and Button) to expose their
children. The BaseWidget just returns an empty []Widget.
* Console: added a `repl` command that keeps the dev console open and
prefixes every command with `$` filled out -- for rapid JavaScript
console evaluation.
The `level.Canvas` is a widget that holds onto its Palette and Grid and
has interactions to allow scrolling and editing the grid using the
swatches available on the palette.
Thus all of the logic in the Editor Mode for drawing directly onto the
root SDL surface are now handled inside a level.Canvas instance.
The `level.Canvas` widget has the following properties:
* Like any widget it has an X,Y position and a width/height.
* It has a Scroll position to control which slice of its drawing will be
visible inside its bounding box.
* It supports levels having negative coordinates for their pixels. It
doesn't care. The default Scroll position is (0,0) at the top left
corner of the widget but you can scroll into the negatives and see the
negative pixels.
* Keyboard keys will scroll the viewport inside the canvas.
* The canvas draws only the pixels that are visible inside its bounding
box.
This feature will eventually pave the way toward:
* Doodads being dropped on top of your map, each Doodad being its own
Canvas widget.
* Using drawings as button icons for the user interface, as the Canvas
is a normal widget.
* Added `BoxSize()` to Widget that reports the full box size including
borders and margin.
* The Frame uses the `BoxSize()` of widgets to position them.
Reintroduces some padding issues (boxes on the GUI Test stick out of
bounds a bit) but is on the right track.
* Renamed `Padding` to `Margin` on the Widget object, since the Margin
is taken into consideration along with Outline and Border in computing
the widget's BoxSize.
* Restructured the Label widget to take a Text or TextVariable property
and the font settings (render.Text) are in a new `Font` property.
The Buttons can now be managed by a ui.Supervisor and be notified when
the mouse enters or leaves their bounding box and handle click events.
Current event handlers supported:
* MouseOver
* MouseOut
* MouseDown
* MouseUp
* Click
Each of those events are only fired when the state of the event has
changed, i.e. the first time the mouse enters the widget MouseOver is
called and then when the mouse leaves later, MouseOut is called.
A completed click event (mouse was released while pressed and hovering
the button) triggers both MouseOut and Click, so the button can pop
itself out and also run the click handler.