Chunker size to uint8 and Rectangular Doodads #84

Merged
kirsle merged 3 commits from file-format-optimization into master 2023-02-18 05:49:49 +00:00
14 changed files with 173 additions and 87 deletions
Showing only changes of commit 31097881ff - Show all commits

View File

@ -15,6 +15,7 @@ import (
"git.kirsle.net/SketchyMaze/doodle/pkg/doodads"
"git.kirsle.net/SketchyMaze/doodle/pkg/level"
"git.kirsle.net/SketchyMaze/doodle/pkg/log"
"git.kirsle.net/SketchyMaze/doodle/pkg/native"
"git.kirsle.net/go/render"
"github.com/urfave/cli/v2"
"golang.org/x/image/bmp"
@ -104,7 +105,6 @@ func imageToDrawing(c *cli.Context, chroma render.Color, inputFiles []string, ou
// Read the source images. Ensure they all have the same boundaries.
var (
imageBounds image.Point
chunkSize uint8 // the square shape for the Doodad chunk size
width int // dimensions of the incoming image
height int
images []image.Image
@ -131,11 +131,8 @@ func imageToDrawing(c *cli.Context, chroma render.Color, inputFiles []string, ou
// Validate all images are the same size.
if i == 0 {
imageBounds = imageSize
if imageSize.X > imageSize.Y {
width = imageSize.X
} else {
height = imageSize.Y
}
} else if imageSize != imageBounds {
return cli.Exit("your source images are not all the same dimensions", 1)
}
@ -152,17 +149,18 @@ func imageToDrawing(c *cli.Context, chroma render.Color, inputFiles []string, ou
// Generate the output drawing file.
switch strings.ToLower(filepath.Ext(outputFile)) {
case extDoodad:
log.Info("Output is a Doodad file (chunk size %d): %s", chunkSize, outputFile)
doodad := doodads.New(width, height)
doodad.GameVersion = branding.Version
doodad.Title = c.String("title")
if doodad.Title == "" {
doodad.Title = "Converted Doodad"
}
doodad.Author = os.Getenv("USER")
doodad.Author = native.DefaultAuthor()
// Write the first layer and gather its palette.
log.Info("Converting first layer to drawing and getting the palette")
var chunkSize = doodad.ChunkSize8()
log.Info("Output is a Doodad file (%dx%d): %s", width, height, outputFile)
palette, layer0 := imageToChunker(images[0], chroma, nil, chunkSize)
doodad.Palette = palette
doodad.Layers[0].Chunker = layer0
@ -197,7 +195,7 @@ func imageToDrawing(c *cli.Context, chroma render.Color, inputFiles []string, ou
if lvl.Title == "" {
lvl.Title = "Converted Level"
}
lvl.Author = os.Getenv("USER")
lvl.Author = native.DefaultAuthor()
palette, chunker := imageToChunker(images[0], chroma, nil, lvl.Chunker.Size)
lvl.Palette = palette
lvl.Chunker = chunker

View File

@ -42,23 +42,29 @@ You can give it one or two values for dimensions:
func New(dimensions ...int) *Doodad {
var (
// Defaults
size = balance.DoodadSize
chunkSize = balance.ChunkSize
size int
chunkSize uint8
width int
height int
)
switch len(dimensions) {
case 1:
size = dimensions[0]
width, height = dimensions[0], dimensions[0]
case 2:
width, height = dimensions[0], dimensions[1]
}
// If no width/height, make it a classic square doodad.
if width+height == 0 {
width = size
height = size
// Set the desired chunkSize to be the largest dimension.
if width > height {
size = width
} else {
size = height
}
// If no size at all, fall back on the default.
if size == 0 {
size = int(balance.ChunkSize)
}
// Pick an optimal chunk size - if our doodad size

View File

@ -1,7 +1,6 @@
package doodads
import (
"git.kirsle.net/SketchyMaze/doodle/pkg/log"
"git.kirsle.net/go/render"
"github.com/google/uuid"
)
@ -25,7 +24,6 @@ func NewDrawing(id string, doodad *Doodad) *Drawing {
if id == "" {
id = uuid.Must(uuid.NewUUID()).String()
}
log.Warn("NewDraging(%s): doodad.Rect=%s doodad.Size=%s", doodad.Title, doodad.Rect(), doodad.Size)
return &Drawing{
id: id,
Doodad: doodad,

View File

@ -6,8 +6,8 @@ import (
"encoding/json"
"fmt"
"git.kirsle.net/SketchyMaze/doodle/pkg/balance"
"git.kirsle.net/SketchyMaze/doodle/pkg/log"
"git.kirsle.net/go/render"
)
// ToZipfile serializes the doodad into zipfile format.
@ -63,7 +63,7 @@ func (d *Doodad) ToZipfile() ([]byte, error) {
// FromZipfile reads a doodad from zipfile format.
func FromZipfile(data []byte) (*Doodad, error) {
var (
doodad = New(balance.DoodadSize)
doodad = New(0)
err = doodad.populateFromZipfile(data)
)
return doodad, err
@ -109,6 +109,13 @@ func (d *Doodad) populateFromZipfile(data []byte) error {
// Re-inflate data after saving a new zipfile.
d.Inflate()
// If we are a legacy doodad and don't have a Size (width x height),
// set it from the chunk size.
if d.Size.IsZero() {
var size = d.ChunkSize()
d.Size = render.NewRect(size, size)
}
return err
}

View File

@ -3,7 +3,6 @@ package doodle
import (
"errors"
"fmt"
"os"
"strings"
"time"
@ -19,6 +18,7 @@ import (
"git.kirsle.net/SketchyMaze/doodle/pkg/log"
"git.kirsle.net/SketchyMaze/doodle/pkg/modal"
"git.kirsle.net/SketchyMaze/doodle/pkg/modal/loadscreen"
"git.kirsle.net/SketchyMaze/doodle/pkg/native"
"git.kirsle.net/SketchyMaze/doodle/pkg/usercfg"
"git.kirsle.net/SketchyMaze/doodle/pkg/userdir"
"git.kirsle.net/SketchyMaze/doodle/pkg/windows"
@ -512,7 +512,7 @@ func (s *EditorScene) SaveLevel(filename string) error {
m.Title = "Alpha"
}
if m.Author == "" {
m.Author = os.Getenv("USER")
m.Author = native.DefaultAuthor()
}
m.Palette = s.UI.Canvas.Palette
@ -595,7 +595,7 @@ func (s *EditorScene) SaveDoodad(filename string) error {
d.Title = "Untitled Doodad"
}
if d.Author == "" {
d.Author = os.Getenv("USER")
d.Author = native.DefaultAuthor()
}
// TODO: is this copying necessary?

View File

@ -4,12 +4,12 @@ import (
"archive/zip"
"encoding/json"
"fmt"
"os"
"git.kirsle.net/SketchyMaze/doodle/pkg/balance"
"git.kirsle.net/SketchyMaze/doodle/pkg/drawtool"
"git.kirsle.net/SketchyMaze/doodle/pkg/enum"
"git.kirsle.net/SketchyMaze/doodle/pkg/log"
"git.kirsle.net/SketchyMaze/doodle/pkg/native"
"git.kirsle.net/go/render"
)
@ -83,7 +83,7 @@ func New() *Level {
Base: Base{
Version: 1,
Title: "Untitled",
Author: os.Getenv("USER"),
Author: native.DefaultAuthor(),
Files: NewFileSystem(),
},
Chunker: NewChunker(balance.ChunkSize),

29
pkg/native/username.go Normal file
View File

@ -0,0 +1,29 @@
package native
import (
"os"
"git.kirsle.net/SketchyMaze/doodle/pkg/license"
)
var USER string = os.Getenv("USER")
/*
DefaultAuthor will return the local user's name to be the default Author
for levels and doodads they create.
If they have registered the game, use the name from their license JWT token.
Otherwise fall back to their native operating system user.
*/
func DefaultAuthor() string {
// Are we registered?
if license.IsRegistered() {
if reg, err := license.GetRegistration(); err == nil {
return reg.Name
}
}
// Return OS username
return os.Getenv("USER")
}

View File

@ -348,6 +348,11 @@ func (s *PlayScene) PlaceResizeCanvas() {
})
}
// Canvas returns the main level canvas - useful to call from the debug console as `d.Scene.Canvas()`
func (s *PlayScene) Canvas() *uix.Canvas {
return s.drawing
}
// SetPlayerCharacter changes the doodad used for the player, by destroying the
// current player character and making it from scratch.
func (s *PlayScene) SetPlayerCharacter(filename string) {

View File

@ -164,7 +164,7 @@ func (a *Actor) SetWet(v bool) {
// Size returns the size of the actor, from the underlying doodads.Drawing.
func (a *Actor) Size() render.Rect {
return a.Drawing.Size()
return a.Drawing.Doodad.Size
}
// Velocity returns the actor's current velocity vector.

View File

@ -36,6 +36,11 @@ type Canvas struct {
Scrollable bool // Cursor keys will scroll the viewport of this canvas.
Zoom int // Zoom level on the canvas.
// Set this if your Canvas is a small fixed size (e.g. in doodad dropper),
// so that doodads will crop their texture (if chunk size larger than your
// Canvas) as to not overflow the canvas bounds. Not needed for Level canvases.
CroppedSize bool
// Toogle for doodad canvases in the Level Editor to show their buttons.
ShowDoodadButtons bool
doodadButtonFrame ui.Widget // lazy init

View File

@ -220,7 +220,7 @@ func (w *Canvas) drawActors(e render.Engine, p render.Point) {
// Hitting the left edge. Cap the X coord and shrink the width.
delta := p.X - drawAt.X // positive number
drawAt.X = p.X
// scrollTo.X -= delta // TODO
scrollTo.X -= delta
resizeTo.W -= delta
}
@ -232,6 +232,7 @@ func (w *Canvas) drawActors(e render.Engine, p render.Point) {
// Hitting the top edge. Cap the Y coord and shrink the height.
delta := p.Y - drawAt.Y
drawAt.Y = p.Y
scrollTo.Y -= delta
resizeTo.H -= delta
}

26
pkg/uix/canvas_debug.go Normal file
View File

@ -0,0 +1,26 @@
package uix
import "strings"
// Some debugging functions for the Canvas reachable via dev console in-game.
// GetCanvasesByActorName searches a (level) canvas's installed actors and returns any of
// them having this Title or Filename, with filename being more precise.
func (c *Canvas) GetCanvasesByActorName(filename string) []*Canvas {
var (
byFilename = []*Canvas{}
byTitle = []*Canvas{}
lower = strings.ToLower(filename)
)
for _, a := range c.actors {
var doodad = a.Doodad()
if doodad.Filename == filename {
byFilename = append(byFilename, a.Canvas)
} else if strings.ToLower(doodad.Title) == lower {
byTitle = append(byTitle, a.Canvas)
}
}
return append(byFilename, byTitle...)
}

View File

@ -114,12 +114,16 @@ func (w *Canvas) Present(e render.Engine, p render.Point) {
// into which it will render, cap the source width and height.
// This is especially useful for Doodad buttons because the drawing
// is bigger than the button.
if w.CroppedSize {
// NOTE: this is a concern mainly for the Doodad Dropper so that
// the doodads won't overflow the button size they appear in.
if src.W > S.W {
src.W = S.W
}
if src.H > S.H {
src.H = S.H
}
}
var size = int(chunk.Size)
dst := render.Rect{
@ -135,6 +139,10 @@ func (w *Canvas) Present(e render.Engine, p render.Point) {
// TODO: all this shit is in TrimBox(), make it DRY
// wtf? don't need all this code anymore??
_ = ParentPosition
/*
// If the destination width will cause it to overflow the widget
// box, trim off the right edge of the destination rect.
//
@ -192,6 +200,8 @@ func (w *Canvas) Present(e render.Engine, p render.Point) {
dst.W = S.W - w.BoxThickness(1)
}
*/
// When zooming OUT, make sure the source rect is at least the
// full size of the chunk texture; otherwise the ZoomMultiplies
// above do correctly scale e.g. 128x128 to 64x64, but it only

View File

@ -262,6 +262,7 @@ func makeDoodadTab(config DoodadDropper, frame *ui.Frame, size render.Rect, cate
canvases = append(canvases, can)
btn := ui.NewButton(doodad.Title, can)
can.CroppedSize = true
btn.Resize(render.NewRect(
buttonSize-2, // TODO: without the -2 the button border
buttonSize-2, // rests on top of the window border