Implement the Wallpaper system into the levels and the concept of
Bounded and Unbounded levels.
The first wallpaper image is notepad.png which looks like standard ruled
notebook paper. On bounded levels, the top/left edges of the page look
as you would expect and the blue lines tile indefinitely in the positive
directions. On unbounded levels, you only get the repeating blue lines
but not the edge pieces.
A wallpaper is just a rectangular image file. The image is divided into
four equal quadrants to be the Corner, Top, Left and Repeat textures for
the wallpaper. The Repeat texture is ALWAYS used and fills all the empty
space behind the drawing. (Doodads draw with blank canvases as before
because only levels have wallpapers!)
Levels have four options of a "Page Type":
- Unbounded (default, infinite space)
- NoNegativeSpace (has a top left edge but can grow infinitely)
- Bounded (has a top left edge and bounded size)
- Bordered (bounded with bordered texture; NOT IMPLEMENTED!)
The scrollable viewport of a Canvas will respect the wallpaper and page
type settings of a Level loaded into it. That is, if the level has a top
left edge (not Unbounded) you can NOT scroll to see negative coordinates
below (0,0) -- and if the level has a max dimension set, you can't
scroll to see pixels outside those dimensions.
The Canvas property NoLimitScroll=true will override the scroll locking
and let you see outside the bounds, for debugging.
- Default map settings for New Level are now:
- Page Type: NoNegativeSpace
- Wallpaper: notepad.png (default)
- MaxWidth: 2550 (8.5" * 300 ppi)
- MaxHeight: 3300 ( 11" * 300 ppi)
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 the JSON format for embedding Actors (Doodad instances) inside of a
Level. I made a test map that manually inserted a couple of actors.
Actors are given to the Canvas responsible for the Level via the
function `InstallActors()`. So it means you'll call LoadLevel and then
InstallActors to hook everything up.
The Canvas creates sub-Canvas widgets from each Actor.
After drawing the main level geometry from the Canvas.Chunker, it calls
the drawActors() function which does the same but for Actors.
Levels keep a global map of all Actors that exist. For any Actors that
are visible within the Viewport, their sub-Canvas widgets are presented
appropriately on top of the parent Canvas. In case their sub-Canvas
overlaps the parent's boundaries, their sub-Canvas is resized and moved
appropriately.
- Allow the MainWindow to be resized at run time, and the UI
recalculates its sizing and position.
- Made the in-game Shell properties editable via environment variables.
The kirsle.env file sets a blue and pink color scheme.
- Begin the ground work for Levels and Doodads to embed files inside
their data via the level.FileSystem type.
- UI: Labels can now contain line break characters. It will
appropriately render multiple lines of render.Text and take into
account the proper BoxSize to contain them all.
- Add environment variable DOODLE_DEBUG_ALL=true that will turn on ALL
debug overlay and visualization options.
- Add debug overlay to "tag" each Canvas widget with some of its
details, like its Name and World Position. Can be enabled with the
environment variable DEBUG_CANVAS_LABEL=true
- Improved the FPS debug overlay to show in labeled columns and multiple
colors, with easy ability to add new data points to it.
Adds the first features to Edit Mode to support creation of Doodad
files! The "New Doodad" button pops up a prompt for a Doodad size
(default 100px) and configures the Canvas widget and makes a Doodad
struct instead of a Level to manage.
* Move the custom Canvas widget from `level.Canvas` to `uix.Canvas`
(the uix package is for our custom UI widgets now)
* Rename the `doodads.Doodad` interface (for runtime instances of
Doodads) to `doodads.Actor` and make `doodads.Doodad` describe the
file format and JSON schema instead.
* Rename the `EditLevel()` method to `EditDrawing()` and it inspects the
file extension to know whether to launch the Edit Mode for a Level or
for a Doodad drawing.
* Doodads can be edited by using the `-edit` CLI flag or using the
in-game file open features (including `edit` command of dev console).
* Add a `Scrollable` boolean to uix.Canvas to restrict the keyboard
being able to scroll the level, for editing Doodads which have a fixed
size.
* Edit Mode now uses the Level object itself to keep the drawing data
rather than pull its Palette and Chunks out, so it can hang on to more
information. The Canvas widget is given references to the
Level.Palette and Level.Chunker via Canvas.LoadLevel()
* Fix the handoff between Edit Mode and Play Mode. They pass the Level
object back and forth and the Filename, because it's not part of the
Level. You can save the map with its original settings after returning
from Play Mode.
* Fix the collision detection in Play Mode. It broke previously when
palettes were added because of the difference between a render.Point
and a level.Pixel and it couldn't easily look up coordinates. The new
Chunker system provides a render.Point lookup API.
* All pixels are solid for collision right now, TODO is to return Swatch
information from the pixels touching the player character and react
accordingly (non-solid, fire flag, etc.)
* Remove the level.Grid type as it has been replaced by the Chunker.
* Clean up some unused variables and functions.
Starts the implementation of the chunk-based pixel storage system for
levels and drawings.
Previously the levels had a Pixels structure which was just an array of
X,Y and palette index triplets. The new chunk system divides the map up
into square chunks, and lets each chunk manage its own memory layout.
The "MapAccessor" layout is implemented first which is a map of X,Y
coordinates to their Swatches (pointer to an index of the palette). When
serialized the MapAccessor maps the "X,Y": "index" similarly to the old
Pixels array.
The object hierarchy for the chunk system is like:
* Chunker: the manager of the chunks who keeps track of the ChunkSize
and a map of "chunk coordinates" to the chunk in charge of it.
* Chunk: a part of the drawing ChunkSize length square. A chunk has a
Type (of how it stores its data, 0 being a map[Point]Swatch and 1
being a [][]Swatch 2D array), and the chunk has an Accessor which
implements the underlying type.
* Accessor: an interface for a Chunk to provide access to its
pixels.
* MapAccessor: a "sparse map" of coordinates to their Swatches.
* GridAccessor: TBD, will be a "dense" 2D grid of Swatches.
The JSON files are loaded in two passes:
1. The chunks only load their swatch indexes from disk.
2. With the palette also loaded, the chunks are "inflated" and linked
to their swatch pointers.
Misc changes:
* The `level.Canvas` UI widget switches from the old Grid data type to
being able to directly use a `level.Chunker`
* The Chunker is a shared data type between the on-disk level format and
the actual renderer (level.Canvas), so saving the level is easy
because you can just pull the Chunker out from the canvas.
* ChunkSize is stored inside the level file and the default value is at
balance/numbers.go: 1000
* Add ui.Window to easily create reusable windows with titles.
* Add a palette window (panel) to the right edge of the Edit Mode.
* Has Radio Buttons listing the colors available in the palette.
* Add palette support to Edit Mode so when you draw pixels, they take
on the color and attributes of the currently selected Swatch in your
palette.
* Revise the on-disk format to better serialize the Palette object to
JSON.
* Break Play Mode: collision detection fails because the Grid key
elements are now full Pixel objects (which retain their Palette and
Swatch properties).
* The Grid will need to be re-worked to separate X,Y coordinates from
the Pixel metadata to just test "is something there, and what is
it?"
Known bugs:
* The Pixel format in the Grid has DX and DY attributes and
it wreaks havoc on collision detection in Play Mode when you
come straight from the editor. Reloading the map from disk to
play is OK cuz it lacks these attrs.
First pass at a level storage format to save and restore maps.
To save a map: press F12. It takes a screenshot PNG into the
screenshots/ folder and outputs a map JSON in the working directory.
To restore a map: "go run cmd/doodle/main.go map.json"