render: Refactor Events System to Make Module Standalone
* Refactor the events used in lib/render/sdl to be more general-purpose to make librender a stand-alone library separate from Doodle.
This commit is contained in:
parent
3634577f19
commit
7355778a39
7
lib/render/README.md
Normal file
7
lib/render/README.md
Normal file
|
@ -0,0 +1,7 @@
|
|||
# Render: Go Graphics Library
|
||||
|
||||
Render is a graphics library written in Go which targets desktop applications on
|
||||
Windows, MacOS and Linux as well as WebAssembly to run in the browser.
|
||||
|
||||
For desktop systems it uses SDL2 under the hood, and in WebAssembly it interacts
|
||||
with an HTML Canvas element for drawing.
|
|
@ -4,7 +4,7 @@ import (
|
|||
"syscall/js"
|
||||
"time"
|
||||
|
||||
"git.kirsle.net/apps/doodle/lib/events"
|
||||
"git.kirsle.net/apps/doodle/lib/render/event"
|
||||
)
|
||||
|
||||
// Engine implements a rendering engine targeting an HTML canvas for
|
||||
|
@ -17,7 +17,7 @@ type Engine struct {
|
|||
ticks uint32
|
||||
|
||||
// Private fields.
|
||||
events *events.State
|
||||
events *event.State
|
||||
running bool
|
||||
textures map[string]*Texture // cached texture PNG images
|
||||
|
||||
|
@ -34,7 +34,7 @@ func New(canvasID string) (*Engine, error) {
|
|||
engine := &Engine{
|
||||
canvas: canvas,
|
||||
startTime: time.Now(),
|
||||
events: events.New(),
|
||||
events: event.NewState(),
|
||||
width: canvas.ClientW(),
|
||||
height: canvas.ClientH(),
|
||||
queue: make(chan Event, 1024),
|
||||
|
|
|
@ -3,7 +3,7 @@ package canvas
|
|||
import (
|
||||
"syscall/js"
|
||||
|
||||
"git.kirsle.net/apps/doodle/lib/events"
|
||||
"git.kirsle.net/apps/doodle/lib/render/event"
|
||||
)
|
||||
|
||||
// EventClass to categorize JavaScript events.
|
||||
|
@ -158,21 +158,21 @@ func (e *Engine) PollEvent() *Event {
|
|||
}
|
||||
|
||||
// Poll for events.
|
||||
func (e *Engine) Poll() (*events.State, error) {
|
||||
func (e *Engine) Poll() (*event.State, error) {
|
||||
s := e.events
|
||||
|
||||
for event := e.PollEvent(); event != nil; event = e.PollEvent() {
|
||||
switch event.Class {
|
||||
case WindowEvent:
|
||||
s.Resized.Push(true)
|
||||
s.WindowResized = true
|
||||
case MouseEvent:
|
||||
s.CursorX.Push(int32(event.X))
|
||||
s.CursorY.Push(int32(event.Y))
|
||||
s.CursorX = event.X
|
||||
s.CursorY = event.Y
|
||||
case ClickEvent:
|
||||
s.CursorX.Push(int32(event.X))
|
||||
s.CursorY.Push(int32(event.Y))
|
||||
s.Button1.Push(event.LeftClick)
|
||||
s.Button2.Push(event.RightClick)
|
||||
s.CursorX = event.X
|
||||
s.CursorY = event.Y
|
||||
s.Button1 = event.LeftClick
|
||||
s.Button2 = event.RightClick
|
||||
case KeyEvent:
|
||||
switch event.KeyName {
|
||||
case "Escape":
|
||||
|
@ -180,45 +180,34 @@ func (e *Engine) Poll() (*events.State, error) {
|
|||
continue
|
||||
}
|
||||
|
||||
if event.State {
|
||||
s.EscapeKey.Push(true)
|
||||
}
|
||||
s.Escape = event.State
|
||||
case "Enter":
|
||||
if event.Repeat {
|
||||
continue
|
||||
}
|
||||
|
||||
if event.State {
|
||||
s.EnterKey.Push(true)
|
||||
}
|
||||
s.Enter = event.State
|
||||
case "F3":
|
||||
if event.State {
|
||||
s.KeyName.Push("F3")
|
||||
}
|
||||
s.SetKeyDown("F3", event.State)
|
||||
case "ArrowUp":
|
||||
s.Up.Push(event.State)
|
||||
s.Up = event.State
|
||||
case "ArrowLeft":
|
||||
s.Left.Push(event.State)
|
||||
s.Left = event.State
|
||||
case "ArrowRight":
|
||||
s.Right.Push(event.State)
|
||||
s.Right = event.State
|
||||
case "ArrowDown":
|
||||
s.Down.Push(event.State)
|
||||
s.Down = event.State
|
||||
case "Shift":
|
||||
s.ShiftActive.Push(event.State)
|
||||
s.Shift = event.State
|
||||
continue
|
||||
case "Alt":
|
||||
s.Alt = event.State
|
||||
case "Control":
|
||||
continue
|
||||
s.Ctrl = event.State
|
||||
case "Backspace":
|
||||
if event.State {
|
||||
s.KeyName.Push(`\b`)
|
||||
}
|
||||
s.SetKeyDown(`\b`, event.State)
|
||||
default:
|
||||
if event.State {
|
||||
s.KeyName.Push(event.KeyName)
|
||||
} else {
|
||||
s.KeyName.Push("")
|
||||
}
|
||||
s.SetKeyDown(event.KeyName, event.State)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,8 +7,6 @@ import (
|
|||
"image/color"
|
||||
"regexp"
|
||||
"strconv"
|
||||
|
||||
"github.com/vmihailenco/msgpack"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -165,52 +163,6 @@ func (c *Color) UnmarshalJSON(b []byte) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c Color) EncodeMsgpack(enc *msgpack.Encoder) error {
|
||||
return enc.EncodeString(fmt.Sprintf(
|
||||
`"#%02x%02x%02x"`,
|
||||
c.Red, c.Green, c.Blue,
|
||||
))
|
||||
}
|
||||
|
||||
func (c Color) DecodeMsgpack(dec *msgpack.Decoder) error {
|
||||
hex, err := dec.DecodeString()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Color.DecodeMsgpack: %s", err)
|
||||
}
|
||||
|
||||
parsed, err := HexColor(hex)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Color.DecodeMsgpack: HexColor: %s", err)
|
||||
}
|
||||
|
||||
c.Red = parsed.Red
|
||||
c.Blue = parsed.Blue
|
||||
c.Green = parsed.Green
|
||||
c.Alpha = parsed.Alpha
|
||||
return nil
|
||||
}
|
||||
|
||||
// // MarshalMsgpack serializes the Color for msgpack.
|
||||
// func (c Color) MarshalMsgpack() ([]byte, error) {
|
||||
// data := []uint8{
|
||||
// c.Red, c.Green, c.Blue, c.Alpha,
|
||||
// }
|
||||
// return msgpack.Marshal(data)
|
||||
// }
|
||||
//
|
||||
// // UnmarshalMsgpack decodes a Color from msgpack format.
|
||||
// func (c *Color) UnmarshalMsgpack(b []byte) error {
|
||||
// var data []uint8
|
||||
// if err := msgpack.Unmarshal(data, b); err != nil {
|
||||
// return err
|
||||
// }
|
||||
// c.Red = 255
|
||||
// c.Green = data[1]
|
||||
// c.Blue = data[2]
|
||||
// c.Alpha = data[3]
|
||||
// return nil
|
||||
// }
|
||||
|
||||
// IsZero returns if the color is all zeroes (invisible).
|
||||
func (c Color) IsZero() bool {
|
||||
return c.Red+c.Green+c.Blue+c.Alpha == 0
|
||||
|
|
109
lib/render/event/event.go
Normal file
109
lib/render/event/event.go
Normal file
|
@ -0,0 +1,109 @@
|
|||
package event
|
||||
|
||||
import "strings"
|
||||
|
||||
// State holds the current state of key/mouse events.
|
||||
type State struct {
|
||||
// Mouse buttons.
|
||||
Button1 bool // Left
|
||||
Button2 bool // Middle
|
||||
Button3 bool // Right
|
||||
|
||||
// Special keys
|
||||
Escape bool
|
||||
Enter bool
|
||||
Shift bool
|
||||
Ctrl bool
|
||||
Alt bool
|
||||
Up bool
|
||||
Left bool
|
||||
Right bool
|
||||
Down bool
|
||||
|
||||
// Pressed keys.
|
||||
keydown map[string]interface{}
|
||||
|
||||
// Cursor position
|
||||
CursorX int
|
||||
CursorY int
|
||||
|
||||
// Window resized
|
||||
WindowResized bool
|
||||
}
|
||||
|
||||
// NewState creates a new event.State.
|
||||
func NewState() *State {
|
||||
return &State{
|
||||
keydown: map[string]interface{}{},
|
||||
}
|
||||
}
|
||||
|
||||
// SetKeyDown sets that a named key is pressed down.
|
||||
func (s *State) SetKeyDown(name string, down bool) {
|
||||
if down {
|
||||
s.keydown[name] = nil
|
||||
} else {
|
||||
delete(s.keydown, name)
|
||||
}
|
||||
}
|
||||
|
||||
// KeyDown returns whether a named key is currently pressed.
|
||||
func (s *State) KeyDown(name string) bool {
|
||||
_, ok := s.keydown[name]
|
||||
return ok
|
||||
}
|
||||
|
||||
// KeysDown returns a list of all key names currently pressed down.
|
||||
// Set shifted to True to return the key symbols correctly shifted
|
||||
// (uppercase, or symbols on number keys, etc.)
|
||||
func (s *State) KeysDown(shifted bool) []string {
|
||||
var (
|
||||
result = make([]string, len(s.keydown))
|
||||
i = 0
|
||||
)
|
||||
|
||||
for key := range s.keydown {
|
||||
if shifted && s.Shift {
|
||||
if symbol, ok := shiftMap[key]; ok {
|
||||
result[i] = symbol
|
||||
} else {
|
||||
result[i] = strings.ToUpper(key)
|
||||
}
|
||||
} else {
|
||||
result[i] = key
|
||||
}
|
||||
|
||||
i++
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// ResetKeyDown clears all key-down states.
|
||||
func (s *State) ResetKeyDown() {
|
||||
s.keydown = map[string]interface{}{}
|
||||
}
|
||||
|
||||
// shiftMap maps keys to their Shift versions.
|
||||
var shiftMap = map[string]string{
|
||||
"`": "~",
|
||||
"1": "!",
|
||||
"2": "@",
|
||||
"3": "#",
|
||||
"4": "$",
|
||||
"5": "%",
|
||||
"6": "^",
|
||||
"7": "&",
|
||||
"8": "*",
|
||||
"9": "(",
|
||||
"0": ")",
|
||||
"-": "_",
|
||||
"=": "+",
|
||||
"[": "{",
|
||||
"]": "}",
|
||||
`\`: "|",
|
||||
";": ":",
|
||||
`'`: `"`,
|
||||
",": "<",
|
||||
".": ">",
|
||||
"/": "?",
|
||||
}
|
|
@ -4,7 +4,7 @@ import (
|
|||
"fmt"
|
||||
"image"
|
||||
|
||||
"git.kirsle.net/apps/doodle/lib/events"
|
||||
"git.kirsle.net/apps/doodle/lib/render/event"
|
||||
)
|
||||
|
||||
// Engine is the interface for the rendering engine, keeping SDL-specific stuff
|
||||
|
@ -13,7 +13,7 @@ type Engine interface {
|
|||
Setup() error
|
||||
|
||||
// Poll for events like keypresses and mouse clicks.
|
||||
Poll() (*events.State, error)
|
||||
Poll() (*event.State, error)
|
||||
GetTicks() uint32
|
||||
WindowSize() (w, h int)
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
|
||||
"git.kirsle.net/apps/doodle/lib/events"
|
||||
"git.kirsle.net/apps/doodle/lib/render/event"
|
||||
"github.com/veandco/go-sdl2/sdl"
|
||||
)
|
||||
|
||||
|
@ -12,19 +12,17 @@ import (
|
|||
var (
|
||||
DebugWindowEvents = false
|
||||
DebugMouseEvents = false
|
||||
DebugClickEvents = false
|
||||
DebugClickEvents = true
|
||||
DebugKeyEvents = false
|
||||
)
|
||||
|
||||
// Poll for events.
|
||||
func (r *Renderer) Poll() (*events.State, error) {
|
||||
func (r *Renderer) Poll() (*event.State, error) {
|
||||
s := r.events
|
||||
|
||||
// helper function to push keyboard key names on keyDown events only.
|
||||
pushKey := func(name string, state uint8) {
|
||||
if state == 1 {
|
||||
s.KeyName.Push(name)
|
||||
}
|
||||
s.SetKeyDown(name, state == 1)
|
||||
}
|
||||
|
||||
for event := sdl.PollEvent(); event != nil; event = sdl.PollEvent() {
|
||||
|
@ -42,7 +40,10 @@ func (r *Renderer) Poll() (*events.State, error) {
|
|||
)
|
||||
}
|
||||
}
|
||||
s.Resized.Push(true)
|
||||
|
||||
if t.Event == sdl.WINDOWEVENT_RESIZED {
|
||||
s.WindowResized = true
|
||||
}
|
||||
case *sdl.MouseMotionEvent:
|
||||
if DebugMouseEvents {
|
||||
fmt.Printf("[%d ms] tick:%d MouseMotion type:%d id:%d x:%d y:%d xrel:%d yrel:%d",
|
||||
|
@ -51,42 +52,50 @@ func (r *Renderer) Poll() (*events.State, error) {
|
|||
}
|
||||
|
||||
// Push the cursor position.
|
||||
s.CursorX.Push(t.X)
|
||||
s.CursorY.Push(t.Y)
|
||||
s.Button1.Push(t.State == 1)
|
||||
s.CursorX = int(t.X)
|
||||
s.CursorY = int(t.Y)
|
||||
case *sdl.MouseButtonEvent:
|
||||
if DebugClickEvents {
|
||||
fmt.Printf("[%d ms] tick:%d MouseButton type:%d id:%d x:%d y:%d button:%d state:%d",
|
||||
fmt.Printf("[%d ms] tick:%d MouseButton type:%d id:%d x:%d y:%d button:%d state:%d\n",
|
||||
t.Timestamp, r.ticks, t.Type, t.Which, t.X, t.Y, t.Button, t.State,
|
||||
)
|
||||
}
|
||||
|
||||
// Push the cursor position.
|
||||
s.CursorX.Push(t.X)
|
||||
s.CursorY.Push(t.Y)
|
||||
s.CursorX = int(t.X)
|
||||
s.CursorY = int(t.Y)
|
||||
|
||||
// Is a mouse button pressed down?
|
||||
checkDown := func(number uint8, target *events.BoolTick) bool {
|
||||
if t.Button == number {
|
||||
var eventName string
|
||||
if t.State == 1 && target.Now == false {
|
||||
eventName = "DOWN"
|
||||
} else if t.State == 0 && target.Now == true {
|
||||
eventName = "UP"
|
||||
}
|
||||
|
||||
if eventName != "" {
|
||||
target.Push(eventName == "DOWN")
|
||||
}
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
if checkDown(1, s.Button1) || checkDown(3, s.Button2) || checkDown(2, s.Button3) {
|
||||
// Return the event immediately.
|
||||
return s, nil
|
||||
// Store the clicked state of the mouse button.
|
||||
if t.Button == 1 {
|
||||
s.Button1 = t.State == 1
|
||||
} else if t.Button == 2 {
|
||||
s.Button2 = t.State == 1
|
||||
} else if t.Button == 3 {
|
||||
s.Button3 = t.State == 1
|
||||
}
|
||||
//
|
||||
// // Is a mouse button pressed down?
|
||||
// checkDown := func(number uint8, target *events.BoolTick) bool {
|
||||
// if t.Button == number {
|
||||
// var eventName string
|
||||
// if t.State == 1 && target.Now == false {
|
||||
// eventName = "DOWN"
|
||||
// } else if t.State == 0 && target.Now == true {
|
||||
// eventName = "UP"
|
||||
// }
|
||||
//
|
||||
// if eventName != "" {
|
||||
// target.Push(eventName == "DOWN")
|
||||
// }
|
||||
// return true
|
||||
// }
|
||||
// return false
|
||||
// }
|
||||
//
|
||||
// if checkDown(1, s.Button1) || checkDown(3, s.Button2) || checkDown(2, s.Button3) {
|
||||
// // Return the event immediately.
|
||||
// return s, nil
|
||||
// }
|
||||
case *sdl.MouseWheelEvent:
|
||||
if DebugMouseEvents {
|
||||
fmt.Printf("[%d ms] tick:%d MouseWheel type:%d id:%d x:%d y:%d",
|
||||
|
@ -105,12 +114,12 @@ func (r *Renderer) Poll() (*events.State, error) {
|
|||
if t.Repeat == 1 {
|
||||
continue
|
||||
}
|
||||
s.EscapeKey.Push(t.State == 1)
|
||||
s.Escape = t.State == 1
|
||||
case sdl.SCANCODE_RETURN:
|
||||
if t.Repeat == 1 {
|
||||
continue
|
||||
}
|
||||
s.EnterKey.Push(t.State == 1)
|
||||
s.Enter = t.State == 1
|
||||
case sdl.SCANCODE_F1:
|
||||
pushKey("F1", t.State)
|
||||
case sdl.SCANCODE_F2:
|
||||
|
@ -136,33 +145,29 @@ func (r *Renderer) Poll() (*events.State, error) {
|
|||
case sdl.SCANCODE_F12:
|
||||
pushKey("F12", t.State)
|
||||
case sdl.SCANCODE_UP:
|
||||
s.Up.Push(t.State == 1)
|
||||
s.Up = t.State == 1
|
||||
case sdl.SCANCODE_LEFT:
|
||||
s.Left.Push(t.State == 1)
|
||||
s.Left = t.State == 1
|
||||
case sdl.SCANCODE_RIGHT:
|
||||
s.Right.Push(t.State == 1)
|
||||
s.Right = t.State == 1
|
||||
case sdl.SCANCODE_DOWN:
|
||||
s.Down.Push(t.State == 1)
|
||||
s.Down = t.State == 1
|
||||
case sdl.SCANCODE_LSHIFT:
|
||||
case sdl.SCANCODE_RSHIFT:
|
||||
s.ShiftActive.Push(t.State == 1)
|
||||
s.Shift = t.State == 1
|
||||
case sdl.SCANCODE_LALT:
|
||||
case sdl.SCANCODE_RALT:
|
||||
continue
|
||||
s.Alt = t.State == 1
|
||||
case sdl.SCANCODE_LCTRL:
|
||||
s.ControlActive.Push(t.State == 1)
|
||||
s.Ctrl = t.State == 1
|
||||
case sdl.SCANCODE_RCTRL:
|
||||
s.ControlActive.Push(t.State == 1)
|
||||
s.Ctrl = t.State == 1
|
||||
case sdl.SCANCODE_BACKSPACE:
|
||||
// Make it a key event with "\b" as the sequence.
|
||||
if t.State == 1 || t.Repeat == 1 {
|
||||
s.KeyName.Push(`\b`)
|
||||
}
|
||||
s.SetKeyDown(`\b`, t.State == 1 || t.Repeat == 1)
|
||||
default:
|
||||
// Push the string value of the key.
|
||||
if t.State == 1 {
|
||||
s.KeyName.Push(string(t.Keysym.Sym))
|
||||
}
|
||||
s.SetKeyDown(string(t.Keysym.Sym), t.State == 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,8 +5,8 @@ import (
|
|||
"fmt"
|
||||
"time"
|
||||
|
||||
"git.kirsle.net/apps/doodle/lib/events"
|
||||
"git.kirsle.net/apps/doodle/lib/render"
|
||||
"git.kirsle.net/apps/doodle/lib/render/event"
|
||||
"github.com/veandco/go-sdl2/sdl"
|
||||
"github.com/veandco/go-sdl2/ttf"
|
||||
)
|
||||
|
@ -20,7 +20,7 @@ type Renderer struct {
|
|||
startTime time.Time
|
||||
|
||||
// Private fields.
|
||||
events *events.State
|
||||
events *event.State
|
||||
window *sdl.Window
|
||||
renderer *sdl.Renderer
|
||||
running bool
|
||||
|
@ -34,7 +34,7 @@ type Renderer struct {
|
|||
// New creates the SDL renderer.
|
||||
func New(title string, width, height int) *Renderer {
|
||||
return &Renderer{
|
||||
events: events.New(),
|
||||
events: event.NewState(),
|
||||
title: title,
|
||||
width: int32(width),
|
||||
height: int32(height),
|
||||
|
|
|
@ -2,10 +2,8 @@ package sdl
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"git.kirsle.net/apps/doodle/lib/events"
|
||||
"git.kirsle.net/apps/doodle/lib/render"
|
||||
"github.com/veandco/go-sdl2/sdl"
|
||||
"github.com/veandco/go-sdl2/ttf"
|
||||
|
@ -77,20 +75,6 @@ func LoadFont(filename string, size int) (*ttf.Font, error) {
|
|||
return font, nil
|
||||
}
|
||||
|
||||
// Keysym returns the current key pressed, taking into account the Shift
|
||||
// key modifier.
|
||||
func (r *Renderer) Keysym(ev *events.State) string {
|
||||
if key := ev.KeyName.Read(); key != "" {
|
||||
if ev.ShiftActive.Pressed() {
|
||||
if symbol, ok := shiftMap[key]; ok {
|
||||
return symbol
|
||||
}
|
||||
return strings.ToUpper(key)
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// ComputeTextRect computes and returns a Rect for how large the text would
|
||||
// appear if rendered.
|
||||
func (r *Renderer) ComputeTextRect(text render.Text) (render.Rect, error) {
|
||||
|
|
|
@ -100,7 +100,7 @@ func (mw *MainWindow) Loop() error {
|
|||
return fmt.Errorf("event poll error: %s", err)
|
||||
}
|
||||
|
||||
if ev.Resized.Now {
|
||||
if ev.WindowResized {
|
||||
w, h := mw.engine.WindowSize()
|
||||
if w != mw.w || h != mw.h {
|
||||
mw.w = w
|
||||
|
|
|
@ -4,8 +4,8 @@ import (
|
|||
"errors"
|
||||
"sync"
|
||||
|
||||
"git.kirsle.net/apps/doodle/lib/events"
|
||||
"git.kirsle.net/apps/doodle/lib/render"
|
||||
"git.kirsle.net/apps/doodle/lib/render/event"
|
||||
)
|
||||
|
||||
// Event is a named event that the supervisor will send.
|
||||
|
@ -79,11 +79,11 @@ var (
|
|||
//
|
||||
// Useful errors returned by this may be:
|
||||
// - ErrStopPropagation
|
||||
func (s *Supervisor) Loop(ev *events.State) error {
|
||||
func (s *Supervisor) Loop(ev *event.State) error {
|
||||
var (
|
||||
XY = render.Point{
|
||||
X: ev.CursorX.Now,
|
||||
Y: ev.CursorY.Now,
|
||||
X: int32(ev.CursorX),
|
||||
Y: int32(ev.CursorY),
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -93,7 +93,7 @@ func (s *Supervisor) Loop(ev *events.State) error {
|
|||
// If we are dragging something around, do not trigger any mouse events
|
||||
// to other widgets but DO notify any widget we dropped on top of!
|
||||
if s.dd.IsDragging() {
|
||||
if !ev.Button1.Now && !ev.Button2.Now {
|
||||
if !ev.Button1 && !ev.Button3 {
|
||||
// The mouse has been released. TODO: make mouse button important?
|
||||
for _, child := range hovering {
|
||||
child.widget.Event(Drop, XY)
|
||||
|
@ -121,7 +121,7 @@ func (s *Supervisor) Loop(ev *events.State) error {
|
|||
}
|
||||
|
||||
_, isClicked := s.clicked[id]
|
||||
if ev.Button1.Now {
|
||||
if ev.Button1 {
|
||||
if !isClicked {
|
||||
w.Event(MouseDown, XY)
|
||||
s.clicked[id] = nil
|
||||
|
|
|
@ -2,7 +2,7 @@ package doodads
|
|||
|
||||
import (
|
||||
"git.kirsle.net/apps/doodle/lib/render"
|
||||
uuid "github.com/satori/go.uuid"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
// Drawing is a Doodad Actor that is based on drawings made inside the game.
|
||||
|
@ -22,7 +22,7 @@ type Drawing struct {
|
|||
// an empty ID string, it will make a random UUIDv4 ID.
|
||||
func NewDrawing(id string, doodad *Doodad) Drawing {
|
||||
if id == "" {
|
||||
id = uuid.Must(uuid.NewV4()).String()
|
||||
id = uuid.Must(uuid.NewRandom()).String()
|
||||
}
|
||||
return Drawing{
|
||||
id: id,
|
||||
|
|
|
@ -6,8 +6,8 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"git.kirsle.net/apps/doodle/lib/events"
|
||||
"git.kirsle.net/apps/doodle/lib/render"
|
||||
"git.kirsle.net/apps/doodle/lib/render/event"
|
||||
"git.kirsle.net/apps/doodle/pkg/balance"
|
||||
"git.kirsle.net/apps/doodle/pkg/branding"
|
||||
"git.kirsle.net/apps/doodle/pkg/enum"
|
||||
|
@ -32,7 +32,7 @@ type Doodle struct {
|
|||
|
||||
// Easy access to the event state, for the debug overlay to use.
|
||||
// Might not be thread safe.
|
||||
event *events.State
|
||||
event *event.State
|
||||
|
||||
startTime time.Time
|
||||
running bool
|
||||
|
@ -113,7 +113,8 @@ func (d *Doodle) Run() error {
|
|||
|
||||
// Poll for events.
|
||||
ev, err := d.Engine.Poll()
|
||||
shmem.Cursor = render.NewPoint(ev.CursorX.Now, ev.CursorY.Now)
|
||||
// log.Error("Button1 is: %+v", ev.Button1)
|
||||
shmem.Cursor = render.NewPoint(int32(ev.CursorX), int32(ev.CursorY))
|
||||
if err != nil {
|
||||
log.Error("event poll error: %s", err)
|
||||
d.running = false
|
||||
|
@ -123,23 +124,24 @@ func (d *Doodle) Run() error {
|
|||
|
||||
// Command line shell.
|
||||
if d.shell.Open {
|
||||
} else if ev.EnterKey.Read() {
|
||||
} else if ev.Enter {
|
||||
log.Debug("Shell: opening shell")
|
||||
d.shell.Open = true
|
||||
ev.Enter = false
|
||||
} else {
|
||||
// Global event handlers.
|
||||
if ev.EscapeKey.Read() {
|
||||
if ev.Escape {
|
||||
log.Error("Escape key pressed, shutting down")
|
||||
d.running = false
|
||||
break
|
||||
}
|
||||
|
||||
if ev.KeyName.Now == "F3" {
|
||||
if ev.KeyDown("F3") {
|
||||
DebugOverlay = !DebugOverlay
|
||||
ev.KeyName.Read()
|
||||
} else if ev.KeyName.Now == "F4" {
|
||||
ev.SetKeyDown("F3", false)
|
||||
} else if ev.KeyDown("F4") {
|
||||
DebugCollision = !DebugCollision
|
||||
ev.KeyName.Read()
|
||||
ev.SetKeyDown("F4", false)
|
||||
}
|
||||
|
||||
// Run the scene's logic.
|
||||
|
@ -186,7 +188,7 @@ func (d *Doodle) Run() error {
|
|||
d.TrackFPS(delay)
|
||||
|
||||
// Consume any lingering key sym.
|
||||
ev.KeyName.Read()
|
||||
ev.ResetKeyDown()
|
||||
}
|
||||
|
||||
log.Warn("Main Loop Exited! Shutting down...")
|
||||
|
|
|
@ -6,8 +6,8 @@ import (
|
|||
"os"
|
||||
"strings"
|
||||
|
||||
"git.kirsle.net/apps/doodle/lib/events"
|
||||
"git.kirsle.net/apps/doodle/lib/render"
|
||||
"git.kirsle.net/apps/doodle/lib/render/event"
|
||||
"git.kirsle.net/apps/doodle/pkg/balance"
|
||||
"git.kirsle.net/apps/doodle/pkg/doodads"
|
||||
"git.kirsle.net/apps/doodle/pkg/drawtool"
|
||||
|
@ -161,14 +161,14 @@ func (s *EditorScene) Playtest() {
|
|||
}
|
||||
|
||||
// Loop the editor scene.
|
||||
func (s *EditorScene) Loop(d *Doodle, ev *events.State) error {
|
||||
func (s *EditorScene) Loop(d *Doodle, ev *event.State) error {
|
||||
// Update debug overlay values.
|
||||
*s.debTool = s.UI.Canvas.Tool.String()
|
||||
*s.debSwatch = s.UI.Canvas.Palette.ActiveSwatch.Name
|
||||
*s.debWorldIndex = s.UI.Canvas.WorldIndexAt(s.UI.cursor).String()
|
||||
|
||||
// Has the window been resized?
|
||||
if resized := ev.Resized.Read(); resized {
|
||||
if ev.WindowResized {
|
||||
w, h := d.Engine.WindowSize()
|
||||
if w != d.width || h != d.height {
|
||||
// Not a false alarm.
|
||||
|
@ -180,11 +180,10 @@ func (s *EditorScene) Loop(d *Doodle, ev *events.State) error {
|
|||
}
|
||||
|
||||
// Undo/Redo key bindings.
|
||||
if ev.ControlActive.Now {
|
||||
key := ev.KeyName.Read()
|
||||
if key == "z" {
|
||||
if ev.Ctrl {
|
||||
if ev.KeyDown("z") {
|
||||
s.UI.Canvas.UndoStroke()
|
||||
} else if key == "y" {
|
||||
} else if ev.KeyDown("y") {
|
||||
s.UI.Canvas.RedoStroke()
|
||||
}
|
||||
}
|
||||
|
@ -192,18 +191,17 @@ func (s *EditorScene) Loop(d *Doodle, ev *events.State) error {
|
|||
s.UI.Loop(ev)
|
||||
|
||||
// Switching to Play Mode?
|
||||
switch ev.KeyName.Read() {
|
||||
case "p":
|
||||
if ev.KeyDown("p") {
|
||||
s.Playtest()
|
||||
case "l":
|
||||
} else if ev.KeyDown("l") {
|
||||
d.Flash("Line Tool selected.")
|
||||
s.UI.Canvas.Tool = drawtool.LineTool
|
||||
s.UI.activeTool = s.UI.Canvas.Tool.String()
|
||||
case "f":
|
||||
} else if ev.KeyDown("f") {
|
||||
d.Flash("Pencil Tool selected.")
|
||||
s.UI.Canvas.Tool = drawtool.PencilTool
|
||||
s.UI.activeTool = s.UI.Canvas.Tool.String()
|
||||
case "r":
|
||||
} else if ev.KeyDown("r") {
|
||||
d.Flash("Rectangle Tool selected.")
|
||||
s.UI.Canvas.Tool = drawtool.RectTool
|
||||
s.UI.activeTool = s.UI.Canvas.Tool.String()
|
||||
|
|
|
@ -5,8 +5,8 @@ import (
|
|||
"path/filepath"
|
||||
"strconv"
|
||||
|
||||
"git.kirsle.net/apps/doodle/lib/events"
|
||||
"git.kirsle.net/apps/doodle/lib/render"
|
||||
"git.kirsle.net/apps/doodle/lib/render/event"
|
||||
"git.kirsle.net/apps/doodle/lib/ui"
|
||||
"git.kirsle.net/apps/doodle/pkg/balance"
|
||||
"git.kirsle.net/apps/doodle/pkg/branding"
|
||||
|
@ -214,8 +214,8 @@ func (u *EditorUI) Resized(d *Doodle) {
|
|||
}
|
||||
|
||||
// Loop to process events and update the UI.
|
||||
func (u *EditorUI) Loop(ev *events.State) error {
|
||||
u.cursor = render.NewPoint(ev.CursorX.Now, ev.CursorY.Now)
|
||||
func (u *EditorUI) Loop(ev *event.State) error {
|
||||
u.cursor = render.NewPoint(int32(ev.CursorX), int32(ev.CursorY))
|
||||
|
||||
// Loop the UI and see whether we're told to stop event propagation.
|
||||
var stopPropagation bool
|
||||
|
@ -230,8 +230,8 @@ func (u *EditorUI) Loop(ev *events.State) error {
|
|||
// Update status bar labels.
|
||||
{
|
||||
u.StatusMouseText = fmt.Sprintf("Rel:(%d,%d) Abs:(%s)",
|
||||
ev.CursorX.Now,
|
||||
ev.CursorY.Now,
|
||||
ev.CursorX,
|
||||
ev.CursorY,
|
||||
*u.Scene.debWorldIndex,
|
||||
)
|
||||
u.StatusPaletteText = fmt.Sprintf("%s Tool",
|
||||
|
|
|
@ -68,7 +68,7 @@ func (d *Doodle) DrawDebugOverlay() {
|
|||
values = []string{
|
||||
fmt.Sprintf("%d %s", fpsCurrent, framesSkipped),
|
||||
d.Scene.Name(),
|
||||
fmt.Sprintf("%d,%d", d.event.CursorX.Now, d.event.CursorY.Now),
|
||||
fmt.Sprintf("%d,%d", d.event.CursorX, d.event.CursorY),
|
||||
}
|
||||
)
|
||||
|
||||
|
|
|
@ -3,8 +3,8 @@ package doodle
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
"git.kirsle.net/apps/doodle/lib/events"
|
||||
"git.kirsle.net/apps/doodle/lib/render"
|
||||
"git.kirsle.net/apps/doodle/lib/render/event"
|
||||
"git.kirsle.net/apps/doodle/lib/ui"
|
||||
"git.kirsle.net/apps/doodle/pkg/balance"
|
||||
"git.kirsle.net/apps/doodle/pkg/branding"
|
||||
|
@ -248,7 +248,7 @@ func (s *GUITestScene) Setup(d *Doodle) error {
|
|||
}
|
||||
|
||||
// Loop the editor scene.
|
||||
func (s *GUITestScene) Loop(d *Doodle, ev *events.State) error {
|
||||
func (s *GUITestScene) Loop(d *Doodle, ev *event.State) error {
|
||||
s.Supervisor.Loop(ev)
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ package level
|
|||
|
||||
import (
|
||||
"git.kirsle.net/apps/doodle/lib/render"
|
||||
uuid "github.com/satori/go.uuid"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
// ActorMap holds the doodad information by their ID in the level data.
|
||||
|
@ -19,7 +19,7 @@ func (m ActorMap) Inflate() {
|
|||
// given a random UUIDv4 ID.
|
||||
func (m ActorMap) Add(a *Actor) {
|
||||
if a.id == "" {
|
||||
a.id = uuid.Must(uuid.NewV4()).String()
|
||||
a.id = uuid.Must(uuid.NewRandom()).String()
|
||||
}
|
||||
m[a.id] = a
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ import (
|
|||
"git.kirsle.net/apps/doodle/pkg/balance"
|
||||
"git.kirsle.net/apps/doodle/pkg/log"
|
||||
"git.kirsle.net/apps/doodle/pkg/shmem"
|
||||
"github.com/satori/go.uuid"
|
||||
"github.com/google/uuid"
|
||||
"github.com/vmihailenco/msgpack"
|
||||
)
|
||||
|
||||
|
@ -109,7 +109,7 @@ func (c *Chunk) toBitmap(mask render.Color) (render.Texturer, error) {
|
|||
// Generate a unique name for this chunk cache.
|
||||
var name string
|
||||
if c.uuid == uuid.Nil {
|
||||
c.uuid = uuid.Must(uuid.NewV4())
|
||||
c.uuid = uuid.Must(uuid.NewRandom())
|
||||
}
|
||||
name = c.uuid.String()
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package doodle
|
||||
|
||||
import (
|
||||
"git.kirsle.net/apps/doodle/lib/events"
|
||||
"git.kirsle.net/apps/doodle/lib/render"
|
||||
"git.kirsle.net/apps/doodle/lib/render/event"
|
||||
"git.kirsle.net/apps/doodle/lib/ui"
|
||||
"git.kirsle.net/apps/doodle/pkg/balance"
|
||||
"git.kirsle.net/apps/doodle/pkg/branding"
|
||||
|
@ -113,7 +113,7 @@ func (s *MainScene) SetupDemoLevel(d *Doodle) error {
|
|||
}
|
||||
|
||||
// Loop the editor scene.
|
||||
func (s *MainScene) Loop(d *Doodle, ev *events.State) error {
|
||||
func (s *MainScene) Loop(d *Doodle, ev *event.State) error {
|
||||
s.Supervisor.Loop(ev)
|
||||
|
||||
if err := s.scripting.Loop(); err != nil {
|
||||
|
@ -122,7 +122,7 @@ func (s *MainScene) Loop(d *Doodle, ev *events.State) error {
|
|||
|
||||
s.canvas.Loop(ev)
|
||||
|
||||
if resized := ev.Resized.Read(); resized {
|
||||
if ev.WindowResized {
|
||||
w, h := d.Engine.WindowSize()
|
||||
d.width = w
|
||||
d.height = h
|
||||
|
|
|
@ -3,8 +3,8 @@ package doodle
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
"git.kirsle.net/apps/doodle/lib/events"
|
||||
"git.kirsle.net/apps/doodle/lib/render"
|
||||
"git.kirsle.net/apps/doodle/lib/render/event"
|
||||
"git.kirsle.net/apps/doodle/lib/ui"
|
||||
"git.kirsle.net/apps/doodle/pkg/balance"
|
||||
"git.kirsle.net/apps/doodle/pkg/enum"
|
||||
|
@ -493,7 +493,7 @@ func (s *MenuScene) setupLoadWindow(d *Doodle) error {
|
|||
}
|
||||
|
||||
// Loop the editor scene.
|
||||
func (s *MenuScene) Loop(d *Doodle, ev *events.State) error {
|
||||
func (s *MenuScene) Loop(d *Doodle, ev *event.State) error {
|
||||
s.Supervisor.Loop(ev)
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -3,8 +3,8 @@ package doodle
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
"git.kirsle.net/apps/doodle/lib/events"
|
||||
"git.kirsle.net/apps/doodle/lib/render"
|
||||
"git.kirsle.net/apps/doodle/lib/render/event"
|
||||
"git.kirsle.net/apps/doodle/lib/ui"
|
||||
"git.kirsle.net/apps/doodle/pkg/balance"
|
||||
"git.kirsle.net/apps/doodle/pkg/collision"
|
||||
|
@ -303,9 +303,9 @@ func (s *PlayScene) DieByFire() {
|
|||
}
|
||||
|
||||
// Loop the editor scene.
|
||||
func (s *PlayScene) Loop(d *Doodle, ev *events.State) error {
|
||||
func (s *PlayScene) Loop(d *Doodle, ev *event.State) error {
|
||||
// Update debug overlay values.
|
||||
*s.debWorldIndex = s.drawing.WorldIndexAt(render.NewPoint(ev.CursorX.Now, ev.CursorY.Now)).String()
|
||||
*s.debWorldIndex = s.drawing.WorldIndexAt(render.NewPoint(int32(ev.CursorX), int32(ev.CursorY))).String()
|
||||
*s.debPosition = s.Player.Position().String() + " vel " + s.Player.Velocity().String()
|
||||
*s.debViewport = s.drawing.Viewport().String()
|
||||
*s.debScroll = s.drawing.Scroll.String()
|
||||
|
@ -313,7 +313,7 @@ func (s *PlayScene) Loop(d *Doodle, ev *events.State) error {
|
|||
s.supervisor.Loop(ev)
|
||||
|
||||
// Has the window been resized?
|
||||
if resized := ev.Resized.Now; resized {
|
||||
if ev.WindowResized {
|
||||
w, h := d.Engine.WindowSize()
|
||||
if w != d.width || h != d.height {
|
||||
d.width = w
|
||||
|
@ -324,7 +324,7 @@ func (s *PlayScene) Loop(d *Doodle, ev *events.State) error {
|
|||
}
|
||||
|
||||
// Switching to Edit Mode?
|
||||
if s.CanEdit && ev.KeyName.Read() == "e" {
|
||||
if s.CanEdit && ev.KeyDown("e") {
|
||||
s.EditLevel()
|
||||
return nil
|
||||
}
|
||||
|
@ -381,19 +381,19 @@ func (s *PlayScene) Draw(d *Doodle) error {
|
|||
}
|
||||
|
||||
// movePlayer updates the player's X,Y coordinate based on key pressed.
|
||||
func (s *PlayScene) movePlayer(ev *events.State) {
|
||||
func (s *PlayScene) movePlayer(ev *event.State) {
|
||||
var playerSpeed = int32(balance.PlayerMaxVelocity)
|
||||
// var gravity = int32(balance.Gravity)
|
||||
|
||||
var velocity render.Point
|
||||
|
||||
if ev.Left.Now {
|
||||
if ev.Left {
|
||||
velocity.X = -playerSpeed
|
||||
}
|
||||
if ev.Right.Now {
|
||||
if ev.Right {
|
||||
velocity.X = playerSpeed
|
||||
}
|
||||
if ev.Up.Now && (s.Player.Grounded() || s.playerJumpCounter >= 0) {
|
||||
if ev.Up && (s.Player.Grounded() || s.playerJumpCounter >= 0) {
|
||||
velocity.Y = -playerSpeed
|
||||
|
||||
if s.Player.Grounded() {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package doodle
|
||||
|
||||
import (
|
||||
"git.kirsle.net/apps/doodle/lib/events"
|
||||
"git.kirsle.net/apps/doodle/lib/render/event"
|
||||
"git.kirsle.net/apps/doodle/pkg/log"
|
||||
)
|
||||
|
||||
|
@ -14,7 +14,7 @@ type Scene interface {
|
|||
Destroy() error
|
||||
|
||||
// Loop should update the scene's state but not draw anything.
|
||||
Loop(*Doodle, *events.State) error
|
||||
Loop(*Doodle, *event.State) error
|
||||
|
||||
// Draw should use the scene's state to figure out what pixels need
|
||||
// to draw to the screen.
|
||||
|
|
|
@ -3,7 +3,7 @@ package scripting
|
|||
import (
|
||||
"errors"
|
||||
|
||||
"git.kirsle.net/apps/doodle/lib/events"
|
||||
"git.kirsle.net/apps/doodle/lib/render/event"
|
||||
"github.com/robertkrimen/otto"
|
||||
)
|
||||
|
||||
|
@ -60,7 +60,7 @@ func (e *Events) OnKeypress(call otto.FunctionCall) otto.Value {
|
|||
}
|
||||
|
||||
// RunKeypress invokes the OnCollide handler function.
|
||||
func (e *Events) RunKeypress(ev *events.State) error {
|
||||
func (e *Events) RunKeypress(ev *event.State) error {
|
||||
return e.run(KeypressEvent, ev)
|
||||
}
|
||||
|
||||
|
|
19
pkg/shell.go
19
pkg/shell.go
|
@ -5,8 +5,8 @@ import (
|
|||
"fmt"
|
||||
"strings"
|
||||
|
||||
"git.kirsle.net/apps/doodle/lib/events"
|
||||
"git.kirsle.net/apps/doodle/lib/render"
|
||||
"git.kirsle.net/apps/doodle/lib/render/event"
|
||||
"git.kirsle.net/apps/doodle/lib/ui"
|
||||
"git.kirsle.net/apps/doodle/pkg/balance"
|
||||
"git.kirsle.net/apps/doodle/pkg/log"
|
||||
|
@ -206,16 +206,16 @@ func (s *Shell) Parse(input string) Command {
|
|||
}
|
||||
|
||||
// Draw the shell.
|
||||
func (s *Shell) Draw(d *Doodle, ev *events.State) error {
|
||||
func (s *Shell) Draw(d *Doodle, ev *event.State) error {
|
||||
// Compute the line height we can draw.
|
||||
lineHeight := balance.ShellFontSize + int(balance.ShellPadding)
|
||||
|
||||
// If the console is open, draw the console.
|
||||
if s.Open {
|
||||
if ev.EscapeKey.Read() {
|
||||
if ev.Escape {
|
||||
s.Close()
|
||||
return nil
|
||||
} else if ev.EnterKey.Read() || ev.EscapeKey.Read() {
|
||||
} else if ev.Enter {
|
||||
s.Execute(s.Text)
|
||||
|
||||
// Auto-close the console unless in REPL mode.
|
||||
|
@ -223,8 +223,9 @@ func (s *Shell) Draw(d *Doodle, ev *events.State) error {
|
|||
s.Close()
|
||||
}
|
||||
|
||||
ev.Enter = false
|
||||
return nil
|
||||
} else if (ev.Up.Now || ev.Down.Now) && len(s.History) > 0 {
|
||||
} else if (ev.Up || ev.Down) && len(s.History) > 0 {
|
||||
// Paging through history.
|
||||
if !s.historyPaging {
|
||||
s.historyPaging = true
|
||||
|
@ -232,8 +233,9 @@ func (s *Shell) Draw(d *Doodle, ev *events.State) error {
|
|||
}
|
||||
|
||||
// Consume the inputs and make convenient variables.
|
||||
ev.Down.Read()
|
||||
isUp := ev.Up.Read()
|
||||
isUp := ev.Up
|
||||
ev.Down = false
|
||||
ev.Up = false
|
||||
|
||||
// Scroll through the input history.
|
||||
if isUp {
|
||||
|
@ -263,7 +265,7 @@ func (s *Shell) Draw(d *Doodle, ev *events.State) error {
|
|||
}
|
||||
|
||||
// Read a character from the keyboard.
|
||||
if key := ev.ReadKey(); key != "" {
|
||||
for _, key := range ev.KeysDown(true) {
|
||||
// Backspace?
|
||||
if key == `\b` {
|
||||
if len(s.Text) > 0 {
|
||||
|
@ -272,6 +274,7 @@ func (s *Shell) Draw(d *Doodle, ev *events.State) error {
|
|||
} else {
|
||||
s.Text += key
|
||||
}
|
||||
ev.SetKeyDown(key, false)
|
||||
}
|
||||
|
||||
// How tall is the box?
|
||||
|
|
|
@ -6,11 +6,13 @@ import (
|
|||
"image/png"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"runtime"
|
||||
|
||||
"git.kirsle.net/apps/doodle/lib/render"
|
||||
"git.kirsle.net/apps/doodle/lib/ui"
|
||||
"git.kirsle.net/apps/doodle/pkg/bindata"
|
||||
"git.kirsle.net/apps/doodle/pkg/log"
|
||||
"git.kirsle.net/apps/doodle/pkg/wasm"
|
||||
)
|
||||
|
||||
// LoadImage loads a sprite as a ui.Image object. It checks Doodle's embedded
|
||||
|
@ -35,6 +37,26 @@ func LoadImage(e render.Engine, filename string) (*ui.Image, error) {
|
|||
return ui.ImageFromTexture(tex), nil
|
||||
}
|
||||
|
||||
// WASM: try the file over HTTP ajax request.
|
||||
if runtime.GOOS == "js" {
|
||||
data, err := wasm.HTTPGet(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
img, err := png.Decode(bytes.NewBuffer(data))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tex, err := e.StoreTexture(filename, img)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return ui.ImageFromTexture(tex), nil
|
||||
}
|
||||
|
||||
// Then try the file system.
|
||||
if _, err := os.Stat(filename); !os.IsNotExist(err) {
|
||||
log.Debug("sprites.LoadImage: %s from filesystem", filename)
|
||||
|
|
|
@ -7,8 +7,8 @@ import (
|
|||
"git.kirsle.net/apps/doodle/lib/render"
|
||||
"git.kirsle.net/apps/doodle/pkg/doodads"
|
||||
"git.kirsle.net/apps/doodle/pkg/level"
|
||||
"github.com/google/uuid"
|
||||
"github.com/robertkrimen/otto"
|
||||
uuid "github.com/satori/go.uuid"
|
||||
)
|
||||
|
||||
// Actor is an object that marries together the three things that make a
|
||||
|
@ -42,7 +42,7 @@ type Actor struct {
|
|||
// If the id is blank, a new UUIDv4 is generated.
|
||||
func NewActor(id string, levelActor *level.Actor, doodad *doodads.Doodad) *Actor {
|
||||
if id == "" {
|
||||
id = uuid.Must(uuid.NewV4()).String()
|
||||
id = uuid.Must(uuid.NewRandom()).String()
|
||||
}
|
||||
|
||||
size := int32(doodad.Layers[0].Chunker.Size)
|
||||
|
|
|
@ -6,8 +6,8 @@ import (
|
|||
"runtime"
|
||||
"strings"
|
||||
|
||||
"git.kirsle.net/apps/doodle/lib/events"
|
||||
"git.kirsle.net/apps/doodle/lib/render"
|
||||
"git.kirsle.net/apps/doodle/lib/render/event"
|
||||
"git.kirsle.net/apps/doodle/lib/ui"
|
||||
"git.kirsle.net/apps/doodle/pkg/balance"
|
||||
"git.kirsle.net/apps/doodle/pkg/bindata"
|
||||
|
@ -192,7 +192,7 @@ func (w *Canvas) setup() {
|
|||
|
||||
// Loop is called on the scene's event loop to handle mouse interaction with
|
||||
// the canvas, i.e. to edit it.
|
||||
func (w *Canvas) Loop(ev *events.State) error {
|
||||
func (w *Canvas) Loop(ev *event.State) error {
|
||||
// Process the arrow keys scrolling the level in Edit Mode.
|
||||
// canvas_scrolling.go
|
||||
w.loopEditorScroll(ev)
|
||||
|
@ -225,7 +225,7 @@ func (w *Canvas) Loop(ev *events.State) error {
|
|||
|
||||
// If the canvas is editable, only care if it's over our space.
|
||||
if w.Editable {
|
||||
cursor := render.NewPoint(ev.CursorX.Now, ev.CursorY.Now)
|
||||
cursor := render.NewPoint(int32(ev.CursorX), int32(ev.CursorY))
|
||||
if cursor.Inside(ui.AbsoluteRect(w)) {
|
||||
return w.loopEditable(ev)
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package uix
|
||||
|
||||
import (
|
||||
"git.kirsle.net/apps/doodle/lib/events"
|
||||
"git.kirsle.net/apps/doodle/lib/render"
|
||||
"git.kirsle.net/apps/doodle/lib/render/event"
|
||||
"git.kirsle.net/apps/doodle/lib/ui"
|
||||
"git.kirsle.net/apps/doodle/pkg/drawtool"
|
||||
"git.kirsle.net/apps/doodle/pkg/level"
|
||||
|
@ -96,14 +96,14 @@ func (w *Canvas) commitStroke(tool drawtool.Tool, addHistory bool) {
|
|||
}
|
||||
|
||||
// loopEditable handles the Loop() part for editable canvases.
|
||||
func (w *Canvas) loopEditable(ev *events.State) error {
|
||||
func (w *Canvas) loopEditable(ev *event.State) error {
|
||||
// Get the absolute position of the canvas on screen to accurately match
|
||||
// it up to mouse clicks.
|
||||
var (
|
||||
P = ui.AbsolutePosition(w)
|
||||
cursor = render.Point{
|
||||
X: ev.CursorX.Now - P.X - w.Scroll.X,
|
||||
Y: ev.CursorY.Now - P.Y - w.Scroll.Y,
|
||||
X: int32(ev.CursorX) - P.X - w.Scroll.X,
|
||||
Y: int32(ev.CursorY) - P.Y - w.Scroll.Y,
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -123,7 +123,7 @@ func (w *Canvas) loopEditable(ev *events.State) error {
|
|||
}
|
||||
|
||||
// Clicking? Log all the pixels while doing so.
|
||||
if ev.Button1.Now {
|
||||
if ev.Button1 {
|
||||
// Initialize a new Stroke for this atomic drawing operation?
|
||||
if w.currentStroke == nil {
|
||||
w.currentStroke = drawtool.NewStroke(drawtool.Freehand, w.Palette.ActiveSwatch.Color)
|
||||
|
@ -175,7 +175,7 @@ func (w *Canvas) loopEditable(ev *events.State) error {
|
|||
}
|
||||
|
||||
// Clicking? Log all the pixels while doing so.
|
||||
if ev.Button1.Now {
|
||||
if ev.Button1 {
|
||||
// Initialize a new Stroke for this atomic drawing operation?
|
||||
if w.currentStroke == nil {
|
||||
w.currentStroke = drawtool.NewStroke(drawtool.Line, w.Palette.ActiveSwatch.Color)
|
||||
|
@ -196,7 +196,7 @@ func (w *Canvas) loopEditable(ev *events.State) error {
|
|||
}
|
||||
|
||||
// Clicking? Log all the pixels while doing so.
|
||||
if ev.Button1.Now {
|
||||
if ev.Button1 {
|
||||
// Initialize a new Stroke for this atomic drawing operation?
|
||||
if w.currentStroke == nil {
|
||||
w.currentStroke = drawtool.NewStroke(drawtool.Rectangle, w.Palette.ActiveSwatch.Color)
|
||||
|
@ -215,7 +215,7 @@ func (w *Canvas) loopEditable(ev *events.State) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
if ev.Button1.Now {
|
||||
if ev.Button1 {
|
||||
if w.currentStroke == nil {
|
||||
w.currentStroke = drawtool.NewStroke(drawtool.Ellipse, w.Palette.ActiveSwatch.Color)
|
||||
w.currentStroke.Thickness = w.BrushSize
|
||||
|
@ -230,7 +230,7 @@ func (w *Canvas) loopEditable(ev *events.State) error {
|
|||
}
|
||||
case drawtool.EraserTool:
|
||||
// Clicking? Log all the pixels while doing so.
|
||||
if ev.Button1.Now {
|
||||
if ev.Button1 {
|
||||
// Initialize a new Stroke for this atomic drawing operation?
|
||||
if w.currentStroke == nil {
|
||||
// The color is white, will look like white-out that covers the
|
||||
|
@ -296,14 +296,14 @@ func (w *Canvas) loopEditable(ev *events.State) error {
|
|||
|
||||
// Check for a mouse down event to begin dragging this
|
||||
// canvas around.
|
||||
if ev.Button1.Read() {
|
||||
if ev.Button1 {
|
||||
// Pop this canvas out for the drag/drop.
|
||||
if w.OnDragStart != nil {
|
||||
deleteActors = append(deleteActors, actor.Actor)
|
||||
w.OnDragStart(actor.Actor)
|
||||
}
|
||||
break
|
||||
} else if ev.Button2.Read() {
|
||||
} else if ev.Button2 {
|
||||
// Right click to delete an actor.
|
||||
deleteActors = append(deleteActors, actor.Actor)
|
||||
}
|
||||
|
@ -347,7 +347,7 @@ func (w *Canvas) loopEditable(ev *events.State) error {
|
|||
})
|
||||
|
||||
// Click handler to start linking this actor.
|
||||
if ev.Button1.Read() {
|
||||
if ev.Button1 {
|
||||
if err := w.LinkAdd(actor); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -4,8 +4,8 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
|
||||
"git.kirsle.net/apps/doodle/lib/events"
|
||||
"git.kirsle.net/apps/doodle/lib/render"
|
||||
"git.kirsle.net/apps/doodle/lib/render/event"
|
||||
"git.kirsle.net/apps/doodle/pkg/balance"
|
||||
"git.kirsle.net/apps/doodle/pkg/level"
|
||||
)
|
||||
|
@ -22,21 +22,21 @@ constrained to fit the bounds of the level.
|
|||
The debug boolean `NoLimitScroll=true` will override the bounded level scroll
|
||||
restriction and allow scrolling into out-of-bounds areas of the level.
|
||||
*/
|
||||
func (w *Canvas) loopEditorScroll(ev *events.State) error {
|
||||
func (w *Canvas) loopEditorScroll(ev *event.State) error {
|
||||
if !w.Scrollable {
|
||||
return errors.New("canvas not scrollable")
|
||||
}
|
||||
|
||||
// Arrow keys to scroll the view.
|
||||
scrollBy := render.Point{}
|
||||
if ev.Right.Now {
|
||||
if ev.Right {
|
||||
scrollBy.X -= balance.CanvasScrollSpeed
|
||||
} else if ev.Left.Now {
|
||||
} else if ev.Left {
|
||||
scrollBy.X += balance.CanvasScrollSpeed
|
||||
}
|
||||
if ev.Down.Now {
|
||||
if ev.Down {
|
||||
scrollBy.Y -= balance.CanvasScrollSpeed
|
||||
} else if ev.Up.Now {
|
||||
} else if ev.Up {
|
||||
scrollBy.Y += balance.CanvasScrollSpeed
|
||||
}
|
||||
if !scrollBy.IsZero() {
|
||||
|
@ -103,7 +103,7 @@ Does nothing if w.FollowActor is an empty string. Set it to the ID of an Actor
|
|||
to follow. If the actor exists, the Canvas will scroll to keep it on the
|
||||
screen.
|
||||
*/
|
||||
func (w *Canvas) loopFollowActor(ev *events.State) error {
|
||||
func (w *Canvas) loopFollowActor(ev *event.State) error {
|
||||
// Are we following an actor?
|
||||
if w.FollowActor == "" {
|
||||
return nil
|
||||
|
|
Loading…
Reference in New Issue
Block a user