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"
|
"syscall/js"
|
||||||
"time"
|
"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
|
// Engine implements a rendering engine targeting an HTML canvas for
|
||||||
|
@ -17,7 +17,7 @@ type Engine struct {
|
||||||
ticks uint32
|
ticks uint32
|
||||||
|
|
||||||
// Private fields.
|
// Private fields.
|
||||||
events *events.State
|
events *event.State
|
||||||
running bool
|
running bool
|
||||||
textures map[string]*Texture // cached texture PNG images
|
textures map[string]*Texture // cached texture PNG images
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ func New(canvasID string) (*Engine, error) {
|
||||||
engine := &Engine{
|
engine := &Engine{
|
||||||
canvas: canvas,
|
canvas: canvas,
|
||||||
startTime: time.Now(),
|
startTime: time.Now(),
|
||||||
events: events.New(),
|
events: event.NewState(),
|
||||||
width: canvas.ClientW(),
|
width: canvas.ClientW(),
|
||||||
height: canvas.ClientH(),
|
height: canvas.ClientH(),
|
||||||
queue: make(chan Event, 1024),
|
queue: make(chan Event, 1024),
|
||||||
|
|
|
@ -3,7 +3,7 @@ package canvas
|
||||||
import (
|
import (
|
||||||
"syscall/js"
|
"syscall/js"
|
||||||
|
|
||||||
"git.kirsle.net/apps/doodle/lib/events"
|
"git.kirsle.net/apps/doodle/lib/render/event"
|
||||||
)
|
)
|
||||||
|
|
||||||
// EventClass to categorize JavaScript events.
|
// EventClass to categorize JavaScript events.
|
||||||
|
@ -158,21 +158,21 @@ func (e *Engine) PollEvent() *Event {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Poll for events.
|
// Poll for events.
|
||||||
func (e *Engine) Poll() (*events.State, error) {
|
func (e *Engine) Poll() (*event.State, error) {
|
||||||
s := e.events
|
s := e.events
|
||||||
|
|
||||||
for event := e.PollEvent(); event != nil; event = e.PollEvent() {
|
for event := e.PollEvent(); event != nil; event = e.PollEvent() {
|
||||||
switch event.Class {
|
switch event.Class {
|
||||||
case WindowEvent:
|
case WindowEvent:
|
||||||
s.Resized.Push(true)
|
s.WindowResized = true
|
||||||
case MouseEvent:
|
case MouseEvent:
|
||||||
s.CursorX.Push(int32(event.X))
|
s.CursorX = event.X
|
||||||
s.CursorY.Push(int32(event.Y))
|
s.CursorY = event.Y
|
||||||
case ClickEvent:
|
case ClickEvent:
|
||||||
s.CursorX.Push(int32(event.X))
|
s.CursorX = event.X
|
||||||
s.CursorY.Push(int32(event.Y))
|
s.CursorY = event.Y
|
||||||
s.Button1.Push(event.LeftClick)
|
s.Button1 = event.LeftClick
|
||||||
s.Button2.Push(event.RightClick)
|
s.Button2 = event.RightClick
|
||||||
case KeyEvent:
|
case KeyEvent:
|
||||||
switch event.KeyName {
|
switch event.KeyName {
|
||||||
case "Escape":
|
case "Escape":
|
||||||
|
@ -180,45 +180,34 @@ func (e *Engine) Poll() (*events.State, error) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if event.State {
|
s.Escape = event.State
|
||||||
s.EscapeKey.Push(true)
|
|
||||||
}
|
|
||||||
case "Enter":
|
case "Enter":
|
||||||
if event.Repeat {
|
if event.Repeat {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if event.State {
|
s.Enter = event.State
|
||||||
s.EnterKey.Push(true)
|
|
||||||
}
|
|
||||||
case "F3":
|
case "F3":
|
||||||
if event.State {
|
s.SetKeyDown("F3", event.State)
|
||||||
s.KeyName.Push("F3")
|
|
||||||
}
|
|
||||||
case "ArrowUp":
|
case "ArrowUp":
|
||||||
s.Up.Push(event.State)
|
s.Up = event.State
|
||||||
case "ArrowLeft":
|
case "ArrowLeft":
|
||||||
s.Left.Push(event.State)
|
s.Left = event.State
|
||||||
case "ArrowRight":
|
case "ArrowRight":
|
||||||
s.Right.Push(event.State)
|
s.Right = event.State
|
||||||
case "ArrowDown":
|
case "ArrowDown":
|
||||||
s.Down.Push(event.State)
|
s.Down = event.State
|
||||||
case "Shift":
|
case "Shift":
|
||||||
s.ShiftActive.Push(event.State)
|
s.Shift = event.State
|
||||||
continue
|
continue
|
||||||
case "Alt":
|
case "Alt":
|
||||||
|
s.Alt = event.State
|
||||||
case "Control":
|
case "Control":
|
||||||
continue
|
s.Ctrl = event.State
|
||||||
case "Backspace":
|
case "Backspace":
|
||||||
if event.State {
|
s.SetKeyDown(`\b`, event.State)
|
||||||
s.KeyName.Push(`\b`)
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
if event.State {
|
s.SetKeyDown(event.KeyName, event.State)
|
||||||
s.KeyName.Push(event.KeyName)
|
|
||||||
} else {
|
|
||||||
s.KeyName.Push("")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,8 +7,6 @@ import (
|
||||||
"image/color"
|
"image/color"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/vmihailenco/msgpack"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -165,52 +163,6 @@ func (c *Color) UnmarshalJSON(b []byte) error {
|
||||||
return nil
|
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).
|
// IsZero returns if the color is all zeroes (invisible).
|
||||||
func (c Color) IsZero() bool {
|
func (c Color) IsZero() bool {
|
||||||
return c.Red+c.Green+c.Blue+c.Alpha == 0
|
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"
|
"fmt"
|
||||||
"image"
|
"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
|
// Engine is the interface for the rendering engine, keeping SDL-specific stuff
|
||||||
|
@ -13,7 +13,7 @@ type Engine interface {
|
||||||
Setup() error
|
Setup() error
|
||||||
|
|
||||||
// Poll for events like keypresses and mouse clicks.
|
// Poll for events like keypresses and mouse clicks.
|
||||||
Poll() (*events.State, error)
|
Poll() (*event.State, error)
|
||||||
GetTicks() uint32
|
GetTicks() uint32
|
||||||
WindowSize() (w, h int)
|
WindowSize() (w, h int)
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"git.kirsle.net/apps/doodle/lib/events"
|
"git.kirsle.net/apps/doodle/lib/render/event"
|
||||||
"github.com/veandco/go-sdl2/sdl"
|
"github.com/veandco/go-sdl2/sdl"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -12,19 +12,17 @@ import (
|
||||||
var (
|
var (
|
||||||
DebugWindowEvents = false
|
DebugWindowEvents = false
|
||||||
DebugMouseEvents = false
|
DebugMouseEvents = false
|
||||||
DebugClickEvents = false
|
DebugClickEvents = true
|
||||||
DebugKeyEvents = false
|
DebugKeyEvents = false
|
||||||
)
|
)
|
||||||
|
|
||||||
// Poll for events.
|
// Poll for events.
|
||||||
func (r *Renderer) Poll() (*events.State, error) {
|
func (r *Renderer) Poll() (*event.State, error) {
|
||||||
s := r.events
|
s := r.events
|
||||||
|
|
||||||
// helper function to push keyboard key names on keyDown events only.
|
// helper function to push keyboard key names on keyDown events only.
|
||||||
pushKey := func(name string, state uint8) {
|
pushKey := func(name string, state uint8) {
|
||||||
if state == 1 {
|
s.SetKeyDown(name, state == 1)
|
||||||
s.KeyName.Push(name)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for event := sdl.PollEvent(); event != nil; event = sdl.PollEvent() {
|
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:
|
case *sdl.MouseMotionEvent:
|
||||||
if DebugMouseEvents {
|
if DebugMouseEvents {
|
||||||
fmt.Printf("[%d ms] tick:%d MouseMotion type:%d id:%d x:%d y:%d xrel:%d yrel:%d",
|
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.
|
// Push the cursor position.
|
||||||
s.CursorX.Push(t.X)
|
s.CursorX = int(t.X)
|
||||||
s.CursorY.Push(t.Y)
|
s.CursorY = int(t.Y)
|
||||||
s.Button1.Push(t.State == 1)
|
|
||||||
case *sdl.MouseButtonEvent:
|
case *sdl.MouseButtonEvent:
|
||||||
if DebugClickEvents {
|
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,
|
t.Timestamp, r.ticks, t.Type, t.Which, t.X, t.Y, t.Button, t.State,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Push the cursor position.
|
// Push the cursor position.
|
||||||
s.CursorX.Push(t.X)
|
s.CursorX = int(t.X)
|
||||||
s.CursorY.Push(t.Y)
|
s.CursorY = int(t.Y)
|
||||||
|
|
||||||
// Is a mouse button pressed down?
|
// Store the clicked state of the mouse button.
|
||||||
checkDown := func(number uint8, target *events.BoolTick) bool {
|
if t.Button == 1 {
|
||||||
if t.Button == number {
|
s.Button1 = t.State == 1
|
||||||
var eventName string
|
} else if t.Button == 2 {
|
||||||
if t.State == 1 && target.Now == false {
|
s.Button2 = t.State == 1
|
||||||
eventName = "DOWN"
|
} else if t.Button == 3 {
|
||||||
} else if t.State == 0 && target.Now == true {
|
s.Button3 = t.State == 1
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
//
|
||||||
|
// // 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:
|
case *sdl.MouseWheelEvent:
|
||||||
if DebugMouseEvents {
|
if DebugMouseEvents {
|
||||||
fmt.Printf("[%d ms] tick:%d MouseWheel type:%d id:%d x:%d y:%d",
|
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 {
|
if t.Repeat == 1 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
s.EscapeKey.Push(t.State == 1)
|
s.Escape = t.State == 1
|
||||||
case sdl.SCANCODE_RETURN:
|
case sdl.SCANCODE_RETURN:
|
||||||
if t.Repeat == 1 {
|
if t.Repeat == 1 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
s.EnterKey.Push(t.State == 1)
|
s.Enter = t.State == 1
|
||||||
case sdl.SCANCODE_F1:
|
case sdl.SCANCODE_F1:
|
||||||
pushKey("F1", t.State)
|
pushKey("F1", t.State)
|
||||||
case sdl.SCANCODE_F2:
|
case sdl.SCANCODE_F2:
|
||||||
|
@ -136,33 +145,29 @@ func (r *Renderer) Poll() (*events.State, error) {
|
||||||
case sdl.SCANCODE_F12:
|
case sdl.SCANCODE_F12:
|
||||||
pushKey("F12", t.State)
|
pushKey("F12", t.State)
|
||||||
case sdl.SCANCODE_UP:
|
case sdl.SCANCODE_UP:
|
||||||
s.Up.Push(t.State == 1)
|
s.Up = t.State == 1
|
||||||
case sdl.SCANCODE_LEFT:
|
case sdl.SCANCODE_LEFT:
|
||||||
s.Left.Push(t.State == 1)
|
s.Left = t.State == 1
|
||||||
case sdl.SCANCODE_RIGHT:
|
case sdl.SCANCODE_RIGHT:
|
||||||
s.Right.Push(t.State == 1)
|
s.Right = t.State == 1
|
||||||
case sdl.SCANCODE_DOWN:
|
case sdl.SCANCODE_DOWN:
|
||||||
s.Down.Push(t.State == 1)
|
s.Down = t.State == 1
|
||||||
case sdl.SCANCODE_LSHIFT:
|
case sdl.SCANCODE_LSHIFT:
|
||||||
case sdl.SCANCODE_RSHIFT:
|
case sdl.SCANCODE_RSHIFT:
|
||||||
s.ShiftActive.Push(t.State == 1)
|
s.Shift = t.State == 1
|
||||||
case sdl.SCANCODE_LALT:
|
case sdl.SCANCODE_LALT:
|
||||||
case sdl.SCANCODE_RALT:
|
case sdl.SCANCODE_RALT:
|
||||||
continue
|
s.Alt = t.State == 1
|
||||||
case sdl.SCANCODE_LCTRL:
|
case sdl.SCANCODE_LCTRL:
|
||||||
s.ControlActive.Push(t.State == 1)
|
s.Ctrl = t.State == 1
|
||||||
case sdl.SCANCODE_RCTRL:
|
case sdl.SCANCODE_RCTRL:
|
||||||
s.ControlActive.Push(t.State == 1)
|
s.Ctrl = t.State == 1
|
||||||
case sdl.SCANCODE_BACKSPACE:
|
case sdl.SCANCODE_BACKSPACE:
|
||||||
// Make it a key event with "\b" as the sequence.
|
// Make it a key event with "\b" as the sequence.
|
||||||
if t.State == 1 || t.Repeat == 1 {
|
s.SetKeyDown(`\b`, t.State == 1 || t.Repeat == 1)
|
||||||
s.KeyName.Push(`\b`)
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
// Push the string value of the key.
|
// Push the string value of the key.
|
||||||
if t.State == 1 {
|
s.SetKeyDown(string(t.Keysym.Sym), t.State == 1)
|
||||||
s.KeyName.Push(string(t.Keysym.Sym))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,8 +5,8 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.kirsle.net/apps/doodle/lib/events"
|
|
||||||
"git.kirsle.net/apps/doodle/lib/render"
|
"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/sdl"
|
||||||
"github.com/veandco/go-sdl2/ttf"
|
"github.com/veandco/go-sdl2/ttf"
|
||||||
)
|
)
|
||||||
|
@ -20,7 +20,7 @@ type Renderer struct {
|
||||||
startTime time.Time
|
startTime time.Time
|
||||||
|
|
||||||
// Private fields.
|
// Private fields.
|
||||||
events *events.State
|
events *event.State
|
||||||
window *sdl.Window
|
window *sdl.Window
|
||||||
renderer *sdl.Renderer
|
renderer *sdl.Renderer
|
||||||
running bool
|
running bool
|
||||||
|
@ -34,7 +34,7 @@ type Renderer struct {
|
||||||
// New creates the SDL renderer.
|
// New creates the SDL renderer.
|
||||||
func New(title string, width, height int) *Renderer {
|
func New(title string, width, height int) *Renderer {
|
||||||
return &Renderer{
|
return &Renderer{
|
||||||
events: events.New(),
|
events: event.NewState(),
|
||||||
title: title,
|
title: title,
|
||||||
width: int32(width),
|
width: int32(width),
|
||||||
height: int32(height),
|
height: int32(height),
|
||||||
|
|
|
@ -2,10 +2,8 @@ package sdl
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"git.kirsle.net/apps/doodle/lib/events"
|
|
||||||
"git.kirsle.net/apps/doodle/lib/render"
|
"git.kirsle.net/apps/doodle/lib/render"
|
||||||
"github.com/veandco/go-sdl2/sdl"
|
"github.com/veandco/go-sdl2/sdl"
|
||||||
"github.com/veandco/go-sdl2/ttf"
|
"github.com/veandco/go-sdl2/ttf"
|
||||||
|
@ -77,20 +75,6 @@ func LoadFont(filename string, size int) (*ttf.Font, error) {
|
||||||
return font, nil
|
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
|
// ComputeTextRect computes and returns a Rect for how large the text would
|
||||||
// appear if rendered.
|
// appear if rendered.
|
||||||
func (r *Renderer) ComputeTextRect(text render.Text) (render.Rect, error) {
|
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)
|
return fmt.Errorf("event poll error: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if ev.Resized.Now {
|
if ev.WindowResized {
|
||||||
w, h := mw.engine.WindowSize()
|
w, h := mw.engine.WindowSize()
|
||||||
if w != mw.w || h != mw.h {
|
if w != mw.w || h != mw.h {
|
||||||
mw.w = w
|
mw.w = w
|
||||||
|
|
|
@ -4,8 +4,8 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"git.kirsle.net/apps/doodle/lib/events"
|
|
||||||
"git.kirsle.net/apps/doodle/lib/render"
|
"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.
|
// Event is a named event that the supervisor will send.
|
||||||
|
@ -79,11 +79,11 @@ var (
|
||||||
//
|
//
|
||||||
// Useful errors returned by this may be:
|
// Useful errors returned by this may be:
|
||||||
// - ErrStopPropagation
|
// - ErrStopPropagation
|
||||||
func (s *Supervisor) Loop(ev *events.State) error {
|
func (s *Supervisor) Loop(ev *event.State) error {
|
||||||
var (
|
var (
|
||||||
XY = render.Point{
|
XY = render.Point{
|
||||||
X: ev.CursorX.Now,
|
X: int32(ev.CursorX),
|
||||||
Y: ev.CursorY.Now,
|
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
|
// 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!
|
// to other widgets but DO notify any widget we dropped on top of!
|
||||||
if s.dd.IsDragging() {
|
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?
|
// The mouse has been released. TODO: make mouse button important?
|
||||||
for _, child := range hovering {
|
for _, child := range hovering {
|
||||||
child.widget.Event(Drop, XY)
|
child.widget.Event(Drop, XY)
|
||||||
|
@ -121,7 +121,7 @@ func (s *Supervisor) Loop(ev *events.State) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
_, isClicked := s.clicked[id]
|
_, isClicked := s.clicked[id]
|
||||||
if ev.Button1.Now {
|
if ev.Button1 {
|
||||||
if !isClicked {
|
if !isClicked {
|
||||||
w.Event(MouseDown, XY)
|
w.Event(MouseDown, XY)
|
||||||
s.clicked[id] = nil
|
s.clicked[id] = nil
|
||||||
|
|
|
@ -2,7 +2,7 @@ package doodads
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"git.kirsle.net/apps/doodle/lib/render"
|
"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.
|
// 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.
|
// an empty ID string, it will make a random UUIDv4 ID.
|
||||||
func NewDrawing(id string, doodad *Doodad) Drawing {
|
func NewDrawing(id string, doodad *Doodad) Drawing {
|
||||||
if id == "" {
|
if id == "" {
|
||||||
id = uuid.Must(uuid.NewV4()).String()
|
id = uuid.Must(uuid.NewRandom()).String()
|
||||||
}
|
}
|
||||||
return Drawing{
|
return Drawing{
|
||||||
id: id,
|
id: id,
|
||||||
|
|
|
@ -6,8 +6,8 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.kirsle.net/apps/doodle/lib/events"
|
|
||||||
"git.kirsle.net/apps/doodle/lib/render"
|
"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/balance"
|
||||||
"git.kirsle.net/apps/doodle/pkg/branding"
|
"git.kirsle.net/apps/doodle/pkg/branding"
|
||||||
"git.kirsle.net/apps/doodle/pkg/enum"
|
"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.
|
// Easy access to the event state, for the debug overlay to use.
|
||||||
// Might not be thread safe.
|
// Might not be thread safe.
|
||||||
event *events.State
|
event *event.State
|
||||||
|
|
||||||
startTime time.Time
|
startTime time.Time
|
||||||
running bool
|
running bool
|
||||||
|
@ -113,7 +113,8 @@ func (d *Doodle) Run() error {
|
||||||
|
|
||||||
// Poll for events.
|
// Poll for events.
|
||||||
ev, err := d.Engine.Poll()
|
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 {
|
if err != nil {
|
||||||
log.Error("event poll error: %s", err)
|
log.Error("event poll error: %s", err)
|
||||||
d.running = false
|
d.running = false
|
||||||
|
@ -123,23 +124,24 @@ func (d *Doodle) Run() error {
|
||||||
|
|
||||||
// Command line shell.
|
// Command line shell.
|
||||||
if d.shell.Open {
|
if d.shell.Open {
|
||||||
} else if ev.EnterKey.Read() {
|
} else if ev.Enter {
|
||||||
log.Debug("Shell: opening shell")
|
log.Debug("Shell: opening shell")
|
||||||
d.shell.Open = true
|
d.shell.Open = true
|
||||||
|
ev.Enter = false
|
||||||
} else {
|
} else {
|
||||||
// Global event handlers.
|
// Global event handlers.
|
||||||
if ev.EscapeKey.Read() {
|
if ev.Escape {
|
||||||
log.Error("Escape key pressed, shutting down")
|
log.Error("Escape key pressed, shutting down")
|
||||||
d.running = false
|
d.running = false
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
if ev.KeyName.Now == "F3" {
|
if ev.KeyDown("F3") {
|
||||||
DebugOverlay = !DebugOverlay
|
DebugOverlay = !DebugOverlay
|
||||||
ev.KeyName.Read()
|
ev.SetKeyDown("F3", false)
|
||||||
} else if ev.KeyName.Now == "F4" {
|
} else if ev.KeyDown("F4") {
|
||||||
DebugCollision = !DebugCollision
|
DebugCollision = !DebugCollision
|
||||||
ev.KeyName.Read()
|
ev.SetKeyDown("F4", false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run the scene's logic.
|
// Run the scene's logic.
|
||||||
|
@ -186,7 +188,7 @@ func (d *Doodle) Run() error {
|
||||||
d.TrackFPS(delay)
|
d.TrackFPS(delay)
|
||||||
|
|
||||||
// Consume any lingering key sym.
|
// Consume any lingering key sym.
|
||||||
ev.KeyName.Read()
|
ev.ResetKeyDown()
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Warn("Main Loop Exited! Shutting down...")
|
log.Warn("Main Loop Exited! Shutting down...")
|
||||||
|
|
|
@ -6,8 +6,8 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"git.kirsle.net/apps/doodle/lib/events"
|
|
||||||
"git.kirsle.net/apps/doodle/lib/render"
|
"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/balance"
|
||||||
"git.kirsle.net/apps/doodle/pkg/doodads"
|
"git.kirsle.net/apps/doodle/pkg/doodads"
|
||||||
"git.kirsle.net/apps/doodle/pkg/drawtool"
|
"git.kirsle.net/apps/doodle/pkg/drawtool"
|
||||||
|
@ -161,14 +161,14 @@ func (s *EditorScene) Playtest() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loop the editor scene.
|
// 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.
|
// Update debug overlay values.
|
||||||
*s.debTool = s.UI.Canvas.Tool.String()
|
*s.debTool = s.UI.Canvas.Tool.String()
|
||||||
*s.debSwatch = s.UI.Canvas.Palette.ActiveSwatch.Name
|
*s.debSwatch = s.UI.Canvas.Palette.ActiveSwatch.Name
|
||||||
*s.debWorldIndex = s.UI.Canvas.WorldIndexAt(s.UI.cursor).String()
|
*s.debWorldIndex = s.UI.Canvas.WorldIndexAt(s.UI.cursor).String()
|
||||||
|
|
||||||
// Has the window been resized?
|
// Has the window been resized?
|
||||||
if resized := ev.Resized.Read(); resized {
|
if ev.WindowResized {
|
||||||
w, h := d.Engine.WindowSize()
|
w, h := d.Engine.WindowSize()
|
||||||
if w != d.width || h != d.height {
|
if w != d.width || h != d.height {
|
||||||
// Not a false alarm.
|
// Not a false alarm.
|
||||||
|
@ -180,11 +180,10 @@ func (s *EditorScene) Loop(d *Doodle, ev *events.State) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Undo/Redo key bindings.
|
// Undo/Redo key bindings.
|
||||||
if ev.ControlActive.Now {
|
if ev.Ctrl {
|
||||||
key := ev.KeyName.Read()
|
if ev.KeyDown("z") {
|
||||||
if key == "z" {
|
|
||||||
s.UI.Canvas.UndoStroke()
|
s.UI.Canvas.UndoStroke()
|
||||||
} else if key == "y" {
|
} else if ev.KeyDown("y") {
|
||||||
s.UI.Canvas.RedoStroke()
|
s.UI.Canvas.RedoStroke()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -192,18 +191,17 @@ func (s *EditorScene) Loop(d *Doodle, ev *events.State) error {
|
||||||
s.UI.Loop(ev)
|
s.UI.Loop(ev)
|
||||||
|
|
||||||
// Switching to Play Mode?
|
// Switching to Play Mode?
|
||||||
switch ev.KeyName.Read() {
|
if ev.KeyDown("p") {
|
||||||
case "p":
|
|
||||||
s.Playtest()
|
s.Playtest()
|
||||||
case "l":
|
} else if ev.KeyDown("l") {
|
||||||
d.Flash("Line Tool selected.")
|
d.Flash("Line Tool selected.")
|
||||||
s.UI.Canvas.Tool = drawtool.LineTool
|
s.UI.Canvas.Tool = drawtool.LineTool
|
||||||
s.UI.activeTool = s.UI.Canvas.Tool.String()
|
s.UI.activeTool = s.UI.Canvas.Tool.String()
|
||||||
case "f":
|
} else if ev.KeyDown("f") {
|
||||||
d.Flash("Pencil Tool selected.")
|
d.Flash("Pencil Tool selected.")
|
||||||
s.UI.Canvas.Tool = drawtool.PencilTool
|
s.UI.Canvas.Tool = drawtool.PencilTool
|
||||||
s.UI.activeTool = s.UI.Canvas.Tool.String()
|
s.UI.activeTool = s.UI.Canvas.Tool.String()
|
||||||
case "r":
|
} else if ev.KeyDown("r") {
|
||||||
d.Flash("Rectangle Tool selected.")
|
d.Flash("Rectangle Tool selected.")
|
||||||
s.UI.Canvas.Tool = drawtool.RectTool
|
s.UI.Canvas.Tool = drawtool.RectTool
|
||||||
s.UI.activeTool = s.UI.Canvas.Tool.String()
|
s.UI.activeTool = s.UI.Canvas.Tool.String()
|
||||||
|
|
|
@ -5,8 +5,8 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"git.kirsle.net/apps/doodle/lib/events"
|
|
||||||
"git.kirsle.net/apps/doodle/lib/render"
|
"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/lib/ui"
|
||||||
"git.kirsle.net/apps/doodle/pkg/balance"
|
"git.kirsle.net/apps/doodle/pkg/balance"
|
||||||
"git.kirsle.net/apps/doodle/pkg/branding"
|
"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.
|
// Loop to process events and update the UI.
|
||||||
func (u *EditorUI) Loop(ev *events.State) error {
|
func (u *EditorUI) Loop(ev *event.State) error {
|
||||||
u.cursor = render.NewPoint(ev.CursorX.Now, ev.CursorY.Now)
|
u.cursor = render.NewPoint(int32(ev.CursorX), int32(ev.CursorY))
|
||||||
|
|
||||||
// Loop the UI and see whether we're told to stop event propagation.
|
// Loop the UI and see whether we're told to stop event propagation.
|
||||||
var stopPropagation bool
|
var stopPropagation bool
|
||||||
|
@ -230,8 +230,8 @@ func (u *EditorUI) Loop(ev *events.State) error {
|
||||||
// Update status bar labels.
|
// Update status bar labels.
|
||||||
{
|
{
|
||||||
u.StatusMouseText = fmt.Sprintf("Rel:(%d,%d) Abs:(%s)",
|
u.StatusMouseText = fmt.Sprintf("Rel:(%d,%d) Abs:(%s)",
|
||||||
ev.CursorX.Now,
|
ev.CursorX,
|
||||||
ev.CursorY.Now,
|
ev.CursorY,
|
||||||
*u.Scene.debWorldIndex,
|
*u.Scene.debWorldIndex,
|
||||||
)
|
)
|
||||||
u.StatusPaletteText = fmt.Sprintf("%s Tool",
|
u.StatusPaletteText = fmt.Sprintf("%s Tool",
|
||||||
|
|
|
@ -68,7 +68,7 @@ func (d *Doodle) DrawDebugOverlay() {
|
||||||
values = []string{
|
values = []string{
|
||||||
fmt.Sprintf("%d %s", fpsCurrent, framesSkipped),
|
fmt.Sprintf("%d %s", fpsCurrent, framesSkipped),
|
||||||
d.Scene.Name(),
|
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 (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"git.kirsle.net/apps/doodle/lib/events"
|
|
||||||
"git.kirsle.net/apps/doodle/lib/render"
|
"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/lib/ui"
|
||||||
"git.kirsle.net/apps/doodle/pkg/balance"
|
"git.kirsle.net/apps/doodle/pkg/balance"
|
||||||
"git.kirsle.net/apps/doodle/pkg/branding"
|
"git.kirsle.net/apps/doodle/pkg/branding"
|
||||||
|
@ -248,7 +248,7 @@ func (s *GUITestScene) Setup(d *Doodle) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loop the editor scene.
|
// 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)
|
s.Supervisor.Loop(ev)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ package level
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"git.kirsle.net/apps/doodle/lib/render"
|
"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.
|
// 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.
|
// given a random UUIDv4 ID.
|
||||||
func (m ActorMap) Add(a *Actor) {
|
func (m ActorMap) Add(a *Actor) {
|
||||||
if a.id == "" {
|
if a.id == "" {
|
||||||
a.id = uuid.Must(uuid.NewV4()).String()
|
a.id = uuid.Must(uuid.NewRandom()).String()
|
||||||
}
|
}
|
||||||
m[a.id] = a
|
m[a.id] = a
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ import (
|
||||||
"git.kirsle.net/apps/doodle/pkg/balance"
|
"git.kirsle.net/apps/doodle/pkg/balance"
|
||||||
"git.kirsle.net/apps/doodle/pkg/log"
|
"git.kirsle.net/apps/doodle/pkg/log"
|
||||||
"git.kirsle.net/apps/doodle/pkg/shmem"
|
"git.kirsle.net/apps/doodle/pkg/shmem"
|
||||||
"github.com/satori/go.uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/vmihailenco/msgpack"
|
"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.
|
// Generate a unique name for this chunk cache.
|
||||||
var name string
|
var name string
|
||||||
if c.uuid == uuid.Nil {
|
if c.uuid == uuid.Nil {
|
||||||
c.uuid = uuid.Must(uuid.NewV4())
|
c.uuid = uuid.Must(uuid.NewRandom())
|
||||||
}
|
}
|
||||||
name = c.uuid.String()
|
name = c.uuid.String()
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package doodle
|
package doodle
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"git.kirsle.net/apps/doodle/lib/events"
|
|
||||||
"git.kirsle.net/apps/doodle/lib/render"
|
"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/lib/ui"
|
||||||
"git.kirsle.net/apps/doodle/pkg/balance"
|
"git.kirsle.net/apps/doodle/pkg/balance"
|
||||||
"git.kirsle.net/apps/doodle/pkg/branding"
|
"git.kirsle.net/apps/doodle/pkg/branding"
|
||||||
|
@ -113,7 +113,7 @@ func (s *MainScene) SetupDemoLevel(d *Doodle) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loop the editor scene.
|
// 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)
|
s.Supervisor.Loop(ev)
|
||||||
|
|
||||||
if err := s.scripting.Loop(); err != nil {
|
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)
|
s.canvas.Loop(ev)
|
||||||
|
|
||||||
if resized := ev.Resized.Read(); resized {
|
if ev.WindowResized {
|
||||||
w, h := d.Engine.WindowSize()
|
w, h := d.Engine.WindowSize()
|
||||||
d.width = w
|
d.width = w
|
||||||
d.height = h
|
d.height = h
|
||||||
|
|
|
@ -3,8 +3,8 @@ package doodle
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"git.kirsle.net/apps/doodle/lib/events"
|
|
||||||
"git.kirsle.net/apps/doodle/lib/render"
|
"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/lib/ui"
|
||||||
"git.kirsle.net/apps/doodle/pkg/balance"
|
"git.kirsle.net/apps/doodle/pkg/balance"
|
||||||
"git.kirsle.net/apps/doodle/pkg/enum"
|
"git.kirsle.net/apps/doodle/pkg/enum"
|
||||||
|
@ -493,7 +493,7 @@ func (s *MenuScene) setupLoadWindow(d *Doodle) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loop the editor scene.
|
// 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)
|
s.Supervisor.Loop(ev)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,8 @@ package doodle
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"git.kirsle.net/apps/doodle/lib/events"
|
|
||||||
"git.kirsle.net/apps/doodle/lib/render"
|
"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/lib/ui"
|
||||||
"git.kirsle.net/apps/doodle/pkg/balance"
|
"git.kirsle.net/apps/doodle/pkg/balance"
|
||||||
"git.kirsle.net/apps/doodle/pkg/collision"
|
"git.kirsle.net/apps/doodle/pkg/collision"
|
||||||
|
@ -303,9 +303,9 @@ func (s *PlayScene) DieByFire() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loop the editor scene.
|
// 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.
|
// 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.debPosition = s.Player.Position().String() + " vel " + s.Player.Velocity().String()
|
||||||
*s.debViewport = s.drawing.Viewport().String()
|
*s.debViewport = s.drawing.Viewport().String()
|
||||||
*s.debScroll = s.drawing.Scroll.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)
|
s.supervisor.Loop(ev)
|
||||||
|
|
||||||
// Has the window been resized?
|
// Has the window been resized?
|
||||||
if resized := ev.Resized.Now; resized {
|
if ev.WindowResized {
|
||||||
w, h := d.Engine.WindowSize()
|
w, h := d.Engine.WindowSize()
|
||||||
if w != d.width || h != d.height {
|
if w != d.width || h != d.height {
|
||||||
d.width = w
|
d.width = w
|
||||||
|
@ -324,7 +324,7 @@ func (s *PlayScene) Loop(d *Doodle, ev *events.State) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Switching to Edit Mode?
|
// Switching to Edit Mode?
|
||||||
if s.CanEdit && ev.KeyName.Read() == "e" {
|
if s.CanEdit && ev.KeyDown("e") {
|
||||||
s.EditLevel()
|
s.EditLevel()
|
||||||
return nil
|
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.
|
// 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 playerSpeed = int32(balance.PlayerMaxVelocity)
|
||||||
// var gravity = int32(balance.Gravity)
|
// var gravity = int32(balance.Gravity)
|
||||||
|
|
||||||
var velocity render.Point
|
var velocity render.Point
|
||||||
|
|
||||||
if ev.Left.Now {
|
if ev.Left {
|
||||||
velocity.X = -playerSpeed
|
velocity.X = -playerSpeed
|
||||||
}
|
}
|
||||||
if ev.Right.Now {
|
if ev.Right {
|
||||||
velocity.X = playerSpeed
|
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
|
velocity.Y = -playerSpeed
|
||||||
|
|
||||||
if s.Player.Grounded() {
|
if s.Player.Grounded() {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package doodle
|
package doodle
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"git.kirsle.net/apps/doodle/lib/events"
|
"git.kirsle.net/apps/doodle/lib/render/event"
|
||||||
"git.kirsle.net/apps/doodle/pkg/log"
|
"git.kirsle.net/apps/doodle/pkg/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ type Scene interface {
|
||||||
Destroy() error
|
Destroy() error
|
||||||
|
|
||||||
// Loop should update the scene's state but not draw anything.
|
// 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
|
// Draw should use the scene's state to figure out what pixels need
|
||||||
// to draw to the screen.
|
// to draw to the screen.
|
||||||
|
|
|
@ -3,7 +3,7 @@ package scripting
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
"git.kirsle.net/apps/doodle/lib/events"
|
"git.kirsle.net/apps/doodle/lib/render/event"
|
||||||
"github.com/robertkrimen/otto"
|
"github.com/robertkrimen/otto"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ func (e *Events) OnKeypress(call otto.FunctionCall) otto.Value {
|
||||||
}
|
}
|
||||||
|
|
||||||
// RunKeypress invokes the OnCollide handler function.
|
// 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)
|
return e.run(KeypressEvent, ev)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
19
pkg/shell.go
19
pkg/shell.go
|
@ -5,8 +5,8 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"git.kirsle.net/apps/doodle/lib/events"
|
|
||||||
"git.kirsle.net/apps/doodle/lib/render"
|
"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/lib/ui"
|
||||||
"git.kirsle.net/apps/doodle/pkg/balance"
|
"git.kirsle.net/apps/doodle/pkg/balance"
|
||||||
"git.kirsle.net/apps/doodle/pkg/log"
|
"git.kirsle.net/apps/doodle/pkg/log"
|
||||||
|
@ -206,16 +206,16 @@ func (s *Shell) Parse(input string) Command {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw the shell.
|
// 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.
|
// Compute the line height we can draw.
|
||||||
lineHeight := balance.ShellFontSize + int(balance.ShellPadding)
|
lineHeight := balance.ShellFontSize + int(balance.ShellPadding)
|
||||||
|
|
||||||
// If the console is open, draw the console.
|
// If the console is open, draw the console.
|
||||||
if s.Open {
|
if s.Open {
|
||||||
if ev.EscapeKey.Read() {
|
if ev.Escape {
|
||||||
s.Close()
|
s.Close()
|
||||||
return nil
|
return nil
|
||||||
} else if ev.EnterKey.Read() || ev.EscapeKey.Read() {
|
} else if ev.Enter {
|
||||||
s.Execute(s.Text)
|
s.Execute(s.Text)
|
||||||
|
|
||||||
// Auto-close the console unless in REPL mode.
|
// Auto-close the console unless in REPL mode.
|
||||||
|
@ -223,8 +223,9 @@ func (s *Shell) Draw(d *Doodle, ev *events.State) error {
|
||||||
s.Close()
|
s.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ev.Enter = false
|
||||||
return nil
|
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.
|
// Paging through history.
|
||||||
if !s.historyPaging {
|
if !s.historyPaging {
|
||||||
s.historyPaging = true
|
s.historyPaging = true
|
||||||
|
@ -232,8 +233,9 @@ func (s *Shell) Draw(d *Doodle, ev *events.State) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Consume the inputs and make convenient variables.
|
// Consume the inputs and make convenient variables.
|
||||||
ev.Down.Read()
|
isUp := ev.Up
|
||||||
isUp := ev.Up.Read()
|
ev.Down = false
|
||||||
|
ev.Up = false
|
||||||
|
|
||||||
// Scroll through the input history.
|
// Scroll through the input history.
|
||||||
if isUp {
|
if isUp {
|
||||||
|
@ -263,7 +265,7 @@ func (s *Shell) Draw(d *Doodle, ev *events.State) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read a character from the keyboard.
|
// Read a character from the keyboard.
|
||||||
if key := ev.ReadKey(); key != "" {
|
for _, key := range ev.KeysDown(true) {
|
||||||
// Backspace?
|
// Backspace?
|
||||||
if key == `\b` {
|
if key == `\b` {
|
||||||
if len(s.Text) > 0 {
|
if len(s.Text) > 0 {
|
||||||
|
@ -272,6 +274,7 @@ func (s *Shell) Draw(d *Doodle, ev *events.State) error {
|
||||||
} else {
|
} else {
|
||||||
s.Text += key
|
s.Text += key
|
||||||
}
|
}
|
||||||
|
ev.SetKeyDown(key, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// How tall is the box?
|
// How tall is the box?
|
||||||
|
|
|
@ -6,11 +6,13 @@ import (
|
||||||
"image/png"
|
"image/png"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
"runtime"
|
||||||
|
|
||||||
"git.kirsle.net/apps/doodle/lib/render"
|
"git.kirsle.net/apps/doodle/lib/render"
|
||||||
"git.kirsle.net/apps/doodle/lib/ui"
|
"git.kirsle.net/apps/doodle/lib/ui"
|
||||||
"git.kirsle.net/apps/doodle/pkg/bindata"
|
"git.kirsle.net/apps/doodle/pkg/bindata"
|
||||||
"git.kirsle.net/apps/doodle/pkg/log"
|
"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
|
// 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
|
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.
|
// Then try the file system.
|
||||||
if _, err := os.Stat(filename); !os.IsNotExist(err) {
|
if _, err := os.Stat(filename); !os.IsNotExist(err) {
|
||||||
log.Debug("sprites.LoadImage: %s from filesystem", filename)
|
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/lib/render"
|
||||||
"git.kirsle.net/apps/doodle/pkg/doodads"
|
"git.kirsle.net/apps/doodle/pkg/doodads"
|
||||||
"git.kirsle.net/apps/doodle/pkg/level"
|
"git.kirsle.net/apps/doodle/pkg/level"
|
||||||
|
"github.com/google/uuid"
|
||||||
"github.com/robertkrimen/otto"
|
"github.com/robertkrimen/otto"
|
||||||
uuid "github.com/satori/go.uuid"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Actor is an object that marries together the three things that make a
|
// 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.
|
// If the id is blank, a new UUIDv4 is generated.
|
||||||
func NewActor(id string, levelActor *level.Actor, doodad *doodads.Doodad) *Actor {
|
func NewActor(id string, levelActor *level.Actor, doodad *doodads.Doodad) *Actor {
|
||||||
if id == "" {
|
if id == "" {
|
||||||
id = uuid.Must(uuid.NewV4()).String()
|
id = uuid.Must(uuid.NewRandom()).String()
|
||||||
}
|
}
|
||||||
|
|
||||||
size := int32(doodad.Layers[0].Chunker.Size)
|
size := int32(doodad.Layers[0].Chunker.Size)
|
||||||
|
|
|
@ -6,8 +6,8 @@ import (
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"git.kirsle.net/apps/doodle/lib/events"
|
|
||||||
"git.kirsle.net/apps/doodle/lib/render"
|
"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/lib/ui"
|
||||||
"git.kirsle.net/apps/doodle/pkg/balance"
|
"git.kirsle.net/apps/doodle/pkg/balance"
|
||||||
"git.kirsle.net/apps/doodle/pkg/bindata"
|
"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
|
// Loop is called on the scene's event loop to handle mouse interaction with
|
||||||
// the canvas, i.e. to edit it.
|
// 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.
|
// Process the arrow keys scrolling the level in Edit Mode.
|
||||||
// canvas_scrolling.go
|
// canvas_scrolling.go
|
||||||
w.loopEditorScroll(ev)
|
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 the canvas is editable, only care if it's over our space.
|
||||||
if w.Editable {
|
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)) {
|
if cursor.Inside(ui.AbsoluteRect(w)) {
|
||||||
return w.loopEditable(ev)
|
return w.loopEditable(ev)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package uix
|
package uix
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"git.kirsle.net/apps/doodle/lib/events"
|
|
||||||
"git.kirsle.net/apps/doodle/lib/render"
|
"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/lib/ui"
|
||||||
"git.kirsle.net/apps/doodle/pkg/drawtool"
|
"git.kirsle.net/apps/doodle/pkg/drawtool"
|
||||||
"git.kirsle.net/apps/doodle/pkg/level"
|
"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.
|
// 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
|
// Get the absolute position of the canvas on screen to accurately match
|
||||||
// it up to mouse clicks.
|
// it up to mouse clicks.
|
||||||
var (
|
var (
|
||||||
P = ui.AbsolutePosition(w)
|
P = ui.AbsolutePosition(w)
|
||||||
cursor = render.Point{
|
cursor = render.Point{
|
||||||
X: ev.CursorX.Now - P.X - w.Scroll.X,
|
X: int32(ev.CursorX) - P.X - w.Scroll.X,
|
||||||
Y: ev.CursorY.Now - P.Y - w.Scroll.Y,
|
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.
|
// Clicking? Log all the pixels while doing so.
|
||||||
if ev.Button1.Now {
|
if ev.Button1 {
|
||||||
// Initialize a new Stroke for this atomic drawing operation?
|
// Initialize a new Stroke for this atomic drawing operation?
|
||||||
if w.currentStroke == nil {
|
if w.currentStroke == nil {
|
||||||
w.currentStroke = drawtool.NewStroke(drawtool.Freehand, w.Palette.ActiveSwatch.Color)
|
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.
|
// Clicking? Log all the pixels while doing so.
|
||||||
if ev.Button1.Now {
|
if ev.Button1 {
|
||||||
// Initialize a new Stroke for this atomic drawing operation?
|
// Initialize a new Stroke for this atomic drawing operation?
|
||||||
if w.currentStroke == nil {
|
if w.currentStroke == nil {
|
||||||
w.currentStroke = drawtool.NewStroke(drawtool.Line, w.Palette.ActiveSwatch.Color)
|
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.
|
// Clicking? Log all the pixels while doing so.
|
||||||
if ev.Button1.Now {
|
if ev.Button1 {
|
||||||
// Initialize a new Stroke for this atomic drawing operation?
|
// Initialize a new Stroke for this atomic drawing operation?
|
||||||
if w.currentStroke == nil {
|
if w.currentStroke == nil {
|
||||||
w.currentStroke = drawtool.NewStroke(drawtool.Rectangle, w.Palette.ActiveSwatch.Color)
|
w.currentStroke = drawtool.NewStroke(drawtool.Rectangle, w.Palette.ActiveSwatch.Color)
|
||||||
|
@ -215,7 +215,7 @@ func (w *Canvas) loopEditable(ev *events.State) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if ev.Button1.Now {
|
if ev.Button1 {
|
||||||
if w.currentStroke == nil {
|
if w.currentStroke == nil {
|
||||||
w.currentStroke = drawtool.NewStroke(drawtool.Ellipse, w.Palette.ActiveSwatch.Color)
|
w.currentStroke = drawtool.NewStroke(drawtool.Ellipse, w.Palette.ActiveSwatch.Color)
|
||||||
w.currentStroke.Thickness = w.BrushSize
|
w.currentStroke.Thickness = w.BrushSize
|
||||||
|
@ -230,7 +230,7 @@ func (w *Canvas) loopEditable(ev *events.State) error {
|
||||||
}
|
}
|
||||||
case drawtool.EraserTool:
|
case drawtool.EraserTool:
|
||||||
// Clicking? Log all the pixels while doing so.
|
// Clicking? Log all the pixels while doing so.
|
||||||
if ev.Button1.Now {
|
if ev.Button1 {
|
||||||
// Initialize a new Stroke for this atomic drawing operation?
|
// Initialize a new Stroke for this atomic drawing operation?
|
||||||
if w.currentStroke == nil {
|
if w.currentStroke == nil {
|
||||||
// The color is white, will look like white-out that covers the
|
// 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
|
// Check for a mouse down event to begin dragging this
|
||||||
// canvas around.
|
// canvas around.
|
||||||
if ev.Button1.Read() {
|
if ev.Button1 {
|
||||||
// Pop this canvas out for the drag/drop.
|
// Pop this canvas out for the drag/drop.
|
||||||
if w.OnDragStart != nil {
|
if w.OnDragStart != nil {
|
||||||
deleteActors = append(deleteActors, actor.Actor)
|
deleteActors = append(deleteActors, actor.Actor)
|
||||||
w.OnDragStart(actor.Actor)
|
w.OnDragStart(actor.Actor)
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
} else if ev.Button2.Read() {
|
} else if ev.Button2 {
|
||||||
// Right click to delete an actor.
|
// Right click to delete an actor.
|
||||||
deleteActors = append(deleteActors, actor.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.
|
// Click handler to start linking this actor.
|
||||||
if ev.Button1.Read() {
|
if ev.Button1 {
|
||||||
if err := w.LinkAdd(actor); err != nil {
|
if err := w.LinkAdd(actor); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,8 +4,8 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"git.kirsle.net/apps/doodle/lib/events"
|
|
||||||
"git.kirsle.net/apps/doodle/lib/render"
|
"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/balance"
|
||||||
"git.kirsle.net/apps/doodle/pkg/level"
|
"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
|
The debug boolean `NoLimitScroll=true` will override the bounded level scroll
|
||||||
restriction and allow scrolling into out-of-bounds areas of the level.
|
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 {
|
if !w.Scrollable {
|
||||||
return errors.New("canvas not scrollable")
|
return errors.New("canvas not scrollable")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Arrow keys to scroll the view.
|
// Arrow keys to scroll the view.
|
||||||
scrollBy := render.Point{}
|
scrollBy := render.Point{}
|
||||||
if ev.Right.Now {
|
if ev.Right {
|
||||||
scrollBy.X -= balance.CanvasScrollSpeed
|
scrollBy.X -= balance.CanvasScrollSpeed
|
||||||
} else if ev.Left.Now {
|
} else if ev.Left {
|
||||||
scrollBy.X += balance.CanvasScrollSpeed
|
scrollBy.X += balance.CanvasScrollSpeed
|
||||||
}
|
}
|
||||||
if ev.Down.Now {
|
if ev.Down {
|
||||||
scrollBy.Y -= balance.CanvasScrollSpeed
|
scrollBy.Y -= balance.CanvasScrollSpeed
|
||||||
} else if ev.Up.Now {
|
} else if ev.Up {
|
||||||
scrollBy.Y += balance.CanvasScrollSpeed
|
scrollBy.Y += balance.CanvasScrollSpeed
|
||||||
}
|
}
|
||||||
if !scrollBy.IsZero() {
|
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
|
to follow. If the actor exists, the Canvas will scroll to keep it on the
|
||||||
screen.
|
screen.
|
||||||
*/
|
*/
|
||||||
func (w *Canvas) loopFollowActor(ev *events.State) error {
|
func (w *Canvas) loopFollowActor(ev *event.State) error {
|
||||||
// Are we following an actor?
|
// Are we following an actor?
|
||||||
if w.FollowActor == "" {
|
if w.FollowActor == "" {
|
||||||
return nil
|
return nil
|
||||||
|
|
Loading…
Reference in New Issue
Block a user