Chunker size to uint8 and Rectangular Doodads #84
|
@ -15,6 +15,7 @@ import (
|
||||||
"git.kirsle.net/SketchyMaze/doodle/pkg/doodads"
|
"git.kirsle.net/SketchyMaze/doodle/pkg/doodads"
|
||||||
"git.kirsle.net/SketchyMaze/doodle/pkg/level"
|
"git.kirsle.net/SketchyMaze/doodle/pkg/level"
|
||||||
"git.kirsle.net/SketchyMaze/doodle/pkg/log"
|
"git.kirsle.net/SketchyMaze/doodle/pkg/log"
|
||||||
|
"git.kirsle.net/SketchyMaze/doodle/pkg/native"
|
||||||
"git.kirsle.net/go/render"
|
"git.kirsle.net/go/render"
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
"golang.org/x/image/bmp"
|
"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.
|
// Read the source images. Ensure they all have the same boundaries.
|
||||||
var (
|
var (
|
||||||
imageBounds image.Point
|
imageBounds image.Point
|
||||||
chunkSize uint8 // the square shape for the Doodad chunk size
|
|
||||||
width int // dimensions of the incoming image
|
width int // dimensions of the incoming image
|
||||||
height int
|
height int
|
||||||
images []image.Image
|
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.
|
// Validate all images are the same size.
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
imageBounds = imageSize
|
imageBounds = imageSize
|
||||||
if imageSize.X > imageSize.Y {
|
|
||||||
width = imageSize.X
|
width = imageSize.X
|
||||||
} else {
|
|
||||||
height = imageSize.Y
|
height = imageSize.Y
|
||||||
}
|
|
||||||
} else if imageSize != imageBounds {
|
} else if imageSize != imageBounds {
|
||||||
return cli.Exit("your source images are not all the same dimensions", 1)
|
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.
|
// Generate the output drawing file.
|
||||||
switch strings.ToLower(filepath.Ext(outputFile)) {
|
switch strings.ToLower(filepath.Ext(outputFile)) {
|
||||||
case extDoodad:
|
case extDoodad:
|
||||||
log.Info("Output is a Doodad file (chunk size %d): %s", chunkSize, outputFile)
|
|
||||||
doodad := doodads.New(width, height)
|
doodad := doodads.New(width, height)
|
||||||
doodad.GameVersion = branding.Version
|
doodad.GameVersion = branding.Version
|
||||||
doodad.Title = c.String("title")
|
doodad.Title = c.String("title")
|
||||||
if doodad.Title == "" {
|
if doodad.Title == "" {
|
||||||
doodad.Title = "Converted Doodad"
|
doodad.Title = "Converted Doodad"
|
||||||
}
|
}
|
||||||
doodad.Author = os.Getenv("USER")
|
doodad.Author = native.DefaultAuthor()
|
||||||
|
|
||||||
// Write the first layer and gather its palette.
|
// Write the first layer and gather its palette.
|
||||||
log.Info("Converting first layer to drawing and getting the 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)
|
palette, layer0 := imageToChunker(images[0], chroma, nil, chunkSize)
|
||||||
doodad.Palette = palette
|
doodad.Palette = palette
|
||||||
doodad.Layers[0].Chunker = layer0
|
doodad.Layers[0].Chunker = layer0
|
||||||
|
@ -197,7 +195,7 @@ func imageToDrawing(c *cli.Context, chroma render.Color, inputFiles []string, ou
|
||||||
if lvl.Title == "" {
|
if lvl.Title == "" {
|
||||||
lvl.Title = "Converted Level"
|
lvl.Title = "Converted Level"
|
||||||
}
|
}
|
||||||
lvl.Author = os.Getenv("USER")
|
lvl.Author = native.DefaultAuthor()
|
||||||
palette, chunker := imageToChunker(images[0], chroma, nil, lvl.Chunker.Size)
|
palette, chunker := imageToChunker(images[0], chroma, nil, lvl.Chunker.Size)
|
||||||
lvl.Palette = palette
|
lvl.Palette = palette
|
||||||
lvl.Chunker = chunker
|
lvl.Chunker = chunker
|
||||||
|
|
|
@ -42,23 +42,29 @@ You can give it one or two values for dimensions:
|
||||||
func New(dimensions ...int) *Doodad {
|
func New(dimensions ...int) *Doodad {
|
||||||
var (
|
var (
|
||||||
// Defaults
|
// Defaults
|
||||||
size = balance.DoodadSize
|
size int
|
||||||
chunkSize = balance.ChunkSize
|
chunkSize uint8
|
||||||
width int
|
width int
|
||||||
height int
|
height int
|
||||||
)
|
)
|
||||||
|
|
||||||
switch len(dimensions) {
|
switch len(dimensions) {
|
||||||
case 1:
|
case 1:
|
||||||
size = dimensions[0]
|
width, height = dimensions[0], dimensions[0]
|
||||||
case 2:
|
case 2:
|
||||||
width, height = dimensions[0], dimensions[1]
|
width, height = dimensions[0], dimensions[1]
|
||||||
}
|
}
|
||||||
|
|
||||||
// If no width/height, make it a classic square doodad.
|
// Set the desired chunkSize to be the largest dimension.
|
||||||
if width+height == 0 {
|
if width > height {
|
||||||
width = size
|
size = width
|
||||||
height = size
|
} 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
|
// Pick an optimal chunk size - if our doodad size
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package doodads
|
package doodads
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"git.kirsle.net/SketchyMaze/doodle/pkg/log"
|
|
||||||
"git.kirsle.net/go/render"
|
"git.kirsle.net/go/render"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
)
|
)
|
||||||
|
@ -25,7 +24,6 @@ func NewDrawing(id string, doodad *Doodad) *Drawing {
|
||||||
if id == "" {
|
if id == "" {
|
||||||
id = uuid.Must(uuid.NewUUID()).String()
|
id = uuid.Must(uuid.NewUUID()).String()
|
||||||
}
|
}
|
||||||
log.Warn("NewDraging(%s): doodad.Rect=%s doodad.Size=%s", doodad.Title, doodad.Rect(), doodad.Size)
|
|
||||||
return &Drawing{
|
return &Drawing{
|
||||||
id: id,
|
id: id,
|
||||||
Doodad: doodad,
|
Doodad: doodad,
|
||||||
|
|
|
@ -6,8 +6,8 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"git.kirsle.net/SketchyMaze/doodle/pkg/balance"
|
|
||||||
"git.kirsle.net/SketchyMaze/doodle/pkg/log"
|
"git.kirsle.net/SketchyMaze/doodle/pkg/log"
|
||||||
|
"git.kirsle.net/go/render"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ToZipfile serializes the doodad into zipfile format.
|
// ToZipfile serializes the doodad into zipfile format.
|
||||||
|
@ -63,7 +63,7 @@ func (d *Doodad) ToZipfile() ([]byte, error) {
|
||||||
// FromZipfile reads a doodad from zipfile format.
|
// FromZipfile reads a doodad from zipfile format.
|
||||||
func FromZipfile(data []byte) (*Doodad, error) {
|
func FromZipfile(data []byte) (*Doodad, error) {
|
||||||
var (
|
var (
|
||||||
doodad = New(balance.DoodadSize)
|
doodad = New(0)
|
||||||
err = doodad.populateFromZipfile(data)
|
err = doodad.populateFromZipfile(data)
|
||||||
)
|
)
|
||||||
return doodad, err
|
return doodad, err
|
||||||
|
@ -109,6 +109,13 @@ func (d *Doodad) populateFromZipfile(data []byte) error {
|
||||||
// Re-inflate data after saving a new zipfile.
|
// Re-inflate data after saving a new zipfile.
|
||||||
d.Inflate()
|
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
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,6 @@ package doodle
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -19,6 +18,7 @@ import (
|
||||||
"git.kirsle.net/SketchyMaze/doodle/pkg/log"
|
"git.kirsle.net/SketchyMaze/doodle/pkg/log"
|
||||||
"git.kirsle.net/SketchyMaze/doodle/pkg/modal"
|
"git.kirsle.net/SketchyMaze/doodle/pkg/modal"
|
||||||
"git.kirsle.net/SketchyMaze/doodle/pkg/modal/loadscreen"
|
"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/usercfg"
|
||||||
"git.kirsle.net/SketchyMaze/doodle/pkg/userdir"
|
"git.kirsle.net/SketchyMaze/doodle/pkg/userdir"
|
||||||
"git.kirsle.net/SketchyMaze/doodle/pkg/windows"
|
"git.kirsle.net/SketchyMaze/doodle/pkg/windows"
|
||||||
|
@ -512,7 +512,7 @@ func (s *EditorScene) SaveLevel(filename string) error {
|
||||||
m.Title = "Alpha"
|
m.Title = "Alpha"
|
||||||
}
|
}
|
||||||
if m.Author == "" {
|
if m.Author == "" {
|
||||||
m.Author = os.Getenv("USER")
|
m.Author = native.DefaultAuthor()
|
||||||
}
|
}
|
||||||
|
|
||||||
m.Palette = s.UI.Canvas.Palette
|
m.Palette = s.UI.Canvas.Palette
|
||||||
|
@ -595,7 +595,7 @@ func (s *EditorScene) SaveDoodad(filename string) error {
|
||||||
d.Title = "Untitled Doodad"
|
d.Title = "Untitled Doodad"
|
||||||
}
|
}
|
||||||
if d.Author == "" {
|
if d.Author == "" {
|
||||||
d.Author = os.Getenv("USER")
|
d.Author = native.DefaultAuthor()
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: is this copying necessary?
|
// TODO: is this copying necessary?
|
||||||
|
|
|
@ -4,12 +4,12 @@ import (
|
||||||
"archive/zip"
|
"archive/zip"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
|
||||||
|
|
||||||
"git.kirsle.net/SketchyMaze/doodle/pkg/balance"
|
"git.kirsle.net/SketchyMaze/doodle/pkg/balance"
|
||||||
"git.kirsle.net/SketchyMaze/doodle/pkg/drawtool"
|
"git.kirsle.net/SketchyMaze/doodle/pkg/drawtool"
|
||||||
"git.kirsle.net/SketchyMaze/doodle/pkg/enum"
|
"git.kirsle.net/SketchyMaze/doodle/pkg/enum"
|
||||||
"git.kirsle.net/SketchyMaze/doodle/pkg/log"
|
"git.kirsle.net/SketchyMaze/doodle/pkg/log"
|
||||||
|
"git.kirsle.net/SketchyMaze/doodle/pkg/native"
|
||||||
"git.kirsle.net/go/render"
|
"git.kirsle.net/go/render"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -83,7 +83,7 @@ func New() *Level {
|
||||||
Base: Base{
|
Base: Base{
|
||||||
Version: 1,
|
Version: 1,
|
||||||
Title: "Untitled",
|
Title: "Untitled",
|
||||||
Author: os.Getenv("USER"),
|
Author: native.DefaultAuthor(),
|
||||||
Files: NewFileSystem(),
|
Files: NewFileSystem(),
|
||||||
},
|
},
|
||||||
Chunker: NewChunker(balance.ChunkSize),
|
Chunker: NewChunker(balance.ChunkSize),
|
||||||
|
|
29
pkg/native/username.go
Normal file
29
pkg/native/username.go
Normal 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")
|
||||||
|
}
|
|
@ -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
|
// SetPlayerCharacter changes the doodad used for the player, by destroying the
|
||||||
// current player character and making it from scratch.
|
// current player character and making it from scratch.
|
||||||
func (s *PlayScene) SetPlayerCharacter(filename string) {
|
func (s *PlayScene) SetPlayerCharacter(filename string) {
|
||||||
|
|
|
@ -164,7 +164,7 @@ func (a *Actor) SetWet(v bool) {
|
||||||
|
|
||||||
// Size returns the size of the actor, from the underlying doodads.Drawing.
|
// Size returns the size of the actor, from the underlying doodads.Drawing.
|
||||||
func (a *Actor) Size() render.Rect {
|
func (a *Actor) Size() render.Rect {
|
||||||
return a.Drawing.Size()
|
return a.Drawing.Doodad.Size
|
||||||
}
|
}
|
||||||
|
|
||||||
// Velocity returns the actor's current velocity vector.
|
// Velocity returns the actor's current velocity vector.
|
||||||
|
|
|
@ -36,6 +36,11 @@ type Canvas struct {
|
||||||
Scrollable bool // Cursor keys will scroll the viewport of this canvas.
|
Scrollable bool // Cursor keys will scroll the viewport of this canvas.
|
||||||
Zoom int // Zoom level on the 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.
|
// Toogle for doodad canvases in the Level Editor to show their buttons.
|
||||||
ShowDoodadButtons bool
|
ShowDoodadButtons bool
|
||||||
doodadButtonFrame ui.Widget // lazy init
|
doodadButtonFrame ui.Widget // lazy init
|
||||||
|
|
|
@ -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.
|
// Hitting the left edge. Cap the X coord and shrink the width.
|
||||||
delta := p.X - drawAt.X // positive number
|
delta := p.X - drawAt.X // positive number
|
||||||
drawAt.X = p.X
|
drawAt.X = p.X
|
||||||
// scrollTo.X -= delta // TODO
|
scrollTo.X -= delta
|
||||||
resizeTo.W -= 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.
|
// Hitting the top edge. Cap the Y coord and shrink the height.
|
||||||
delta := p.Y - drawAt.Y
|
delta := p.Y - drawAt.Y
|
||||||
drawAt.Y = p.Y
|
drawAt.Y = p.Y
|
||||||
|
scrollTo.Y -= delta
|
||||||
resizeTo.H -= delta
|
resizeTo.H -= delta
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
26
pkg/uix/canvas_debug.go
Normal file
26
pkg/uix/canvas_debug.go
Normal 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...)
|
||||||
|
}
|
|
@ -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.
|
// into which it will render, cap the source width and height.
|
||||||
// This is especially useful for Doodad buttons because the drawing
|
// This is especially useful for Doodad buttons because the drawing
|
||||||
// is bigger than the button.
|
// 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 {
|
if src.W > S.W {
|
||||||
src.W = S.W
|
src.W = S.W
|
||||||
}
|
}
|
||||||
if src.H > S.H {
|
if src.H > S.H {
|
||||||
src.H = S.H
|
src.H = S.H
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var size = int(chunk.Size)
|
var size = int(chunk.Size)
|
||||||
dst := render.Rect{
|
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
|
// 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
|
// If the destination width will cause it to overflow the widget
|
||||||
// box, trim off the right edge of the destination rect.
|
// 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)
|
dst.W = S.W - w.BoxThickness(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
// When zooming OUT, make sure the source rect is at least the
|
// When zooming OUT, make sure the source rect is at least the
|
||||||
// full size of the chunk texture; otherwise the ZoomMultiplies
|
// full size of the chunk texture; otherwise the ZoomMultiplies
|
||||||
// above do correctly scale e.g. 128x128 to 64x64, but it only
|
// above do correctly scale e.g. 128x128 to 64x64, but it only
|
||||||
|
|
|
@ -262,6 +262,7 @@ func makeDoodadTab(config DoodadDropper, frame *ui.Frame, size render.Rect, cate
|
||||||
canvases = append(canvases, can)
|
canvases = append(canvases, can)
|
||||||
|
|
||||||
btn := ui.NewButton(doodad.Title, can)
|
btn := ui.NewButton(doodad.Title, can)
|
||||||
|
can.CroppedSize = true
|
||||||
btn.Resize(render.NewRect(
|
btn.Resize(render.NewRect(
|
||||||
buttonSize-2, // TODO: without the -2 the button border
|
buttonSize-2, // TODO: without the -2 the button border
|
||||||
buttonSize-2, // rests on top of the window border
|
buttonSize-2, // rests on top of the window border
|
||||||
|
|
Loading…
Reference in New Issue
Block a user