First pass at custom cursor display
This commit is contained in:
@@ -45,6 +45,13 @@ func main() {
|
|||||||
log.Fatal("Couldn't create window: %v", err)
|
log.Fatal("Couldn't create window: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: move this into driver. It will need to be able to change cursor.
|
||||||
|
cursor, err := assets.Cursor(assetstore.UltPointer)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Couldn't load cursor: %v", err)
|
||||||
|
}
|
||||||
|
win.SetCursor(cursor.Image)
|
||||||
|
|
||||||
if err := win.Run(); err != nil {
|
if err := win.Run(); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@@ -34,6 +34,9 @@ type AssetStore struct {
|
|||||||
entries entryMap
|
entries entryMap
|
||||||
|
|
||||||
// These members are used to store things we've already loaded
|
// These members are used to store things we've already loaded
|
||||||
|
cursorObj *Object
|
||||||
|
|
||||||
|
cursors map[CursorName]*Cursor
|
||||||
fonts map[string]*Font
|
fonts map[string]*Font
|
||||||
generic *data.Generic
|
generic *data.Generic
|
||||||
maps map[string]*Map
|
maps map[string]*Map
|
||||||
@@ -85,6 +88,8 @@ func (a *AssetStore) Refresh() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Refresh
|
// Refresh
|
||||||
|
a.cursorObj = nil
|
||||||
|
a.cursors = make(map[CursorName]*Cursor)
|
||||||
a.entries = newEntryMap
|
a.entries = newEntryMap
|
||||||
a.fonts = make(map[string]*Font)
|
a.fonts = make(map[string]*Font)
|
||||||
a.maps = make(map[string]*Map)
|
a.maps = make(map[string]*Map)
|
||||||
|
100
internal/assetstore/cursor.go
Normal file
100
internal/assetstore/cursor.go
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
package assetstore
|
||||||
|
|
||||||
|
import (
|
||||||
|
"image"
|
||||||
|
|
||||||
|
"github.com/hajimehoshi/ebiten"
|
||||||
|
)
|
||||||
|
|
||||||
|
// These are just offsets into the Cursors.cur file
|
||||||
|
type CursorName int
|
||||||
|
|
||||||
|
type Cursor struct {
|
||||||
|
Hotspot image.Point
|
||||||
|
Image *ebiten.Image
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
UltPointer CursorName = 0
|
||||||
|
ChaosPointer CursorName = 1
|
||||||
|
UltWaiter CursorName = 2
|
||||||
|
ChaosWaiter CursorName = 3
|
||||||
|
|
||||||
|
// I think these cursors are used in drag + drop
|
||||||
|
ChaosMarine1 CursorName = 4
|
||||||
|
ChaosMarine2 CursorName = 5
|
||||||
|
ChaosMarine3 CursorName = 6
|
||||||
|
|
||||||
|
UltMarine1 CursorName = 7
|
||||||
|
UltMarine2 CursorName = 8
|
||||||
|
UltMarine3 CursorName = 9
|
||||||
|
UltMarine4 CursorName = 10
|
||||||
|
UltMarine5 CursorName = 11
|
||||||
|
|
||||||
|
ChaosHeavy1 CursorName = 12
|
||||||
|
ChaosHeavy2 CursorName = 13
|
||||||
|
|
||||||
|
UltHeavy1 CursorName = 14
|
||||||
|
UltHeavy2 CursorName = 15
|
||||||
|
UltHeavy3 CursorName = 16
|
||||||
|
UltHeavy4 CursorName = 17
|
||||||
|
UltHeavy5 CursorName = 18
|
||||||
|
UltHeavy6 CursorName = 19
|
||||||
|
|
||||||
|
ChaosTerminator1 CursorName = 20
|
||||||
|
ChaosTerminator2 CursorName = 21
|
||||||
|
|
||||||
|
UltTerminator1 CursorName = 22
|
||||||
|
UltTerminator2 CursorName = 23
|
||||||
|
UltTerminator3 CursorName = 24
|
||||||
|
UltTerminator4 CursorName = 25
|
||||||
|
UltTerminator5 CursorName = 26
|
||||||
|
|
||||||
|
Deny CursorName = 27 // Red X
|
||||||
|
|
||||||
|
UltLogo CursorName = 28
|
||||||
|
UltSquadMarine CursorName = 29
|
||||||
|
UltSquadHeavy CursorName = 30
|
||||||
|
UltSquadAssault CursorName = 31
|
||||||
|
|
||||||
|
UltCaptain CursorName = 32
|
||||||
|
UltChaplain CursorName = 33 // (maybe?)
|
||||||
|
UltApothecary CursorName = 34
|
||||||
|
UltTechmarine CursorName = 35
|
||||||
|
UltLibrarian CursorName = 36
|
||||||
|
|
||||||
|
DenyAgain CursorName = 37 // Identical to Deny as far as I can see *shrug*
|
||||||
|
)
|
||||||
|
|
||||||
|
func (a *AssetStore) Cursor(name CursorName) (*Cursor, error) {
|
||||||
|
if cur, ok := a.cursors[name]; ok {
|
||||||
|
return cur, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if a.cursorObj == nil {
|
||||||
|
filename, err := a.lookup("Cursors.cur", "", "Cursor")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
obj, err := a.ObjectByPath(filename)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
a.cursorObj = obj
|
||||||
|
}
|
||||||
|
|
||||||
|
spr, err := a.cursorObj.Sprite(int(name))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: hotspot info. We're using Cursor.cur because it's object format,
|
||||||
|
// but we do also have .ani files that might contain hotspots.
|
||||||
|
cur := &Cursor{Image: spr.Image}
|
||||||
|
|
||||||
|
a.cursors[name] = cur
|
||||||
|
|
||||||
|
return cur, nil
|
||||||
|
}
|
@@ -93,6 +93,13 @@ func Run(configFile string, overrideX, overrideY int) error {
|
|||||||
return fmt.Errorf("Failed to create window: %v", err)
|
return fmt.Errorf("Failed to create window: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: move this into driver. It will need to be able to change cursor.
|
||||||
|
cursor, err := assets.Cursor(assetstore.UltPointer)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Couldn't load cursor: %v", err)
|
||||||
|
}
|
||||||
|
win.SetCursor(cursor.Image)
|
||||||
|
|
||||||
ordoor.win = win
|
ordoor.win = win
|
||||||
|
|
||||||
if err := ordoor.setupFlow(); err != nil {
|
if err := ordoor.setupFlow(); err != nil {
|
||||||
|
@@ -3,6 +3,7 @@ package ui
|
|||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"image"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
@@ -23,11 +24,16 @@ var (
|
|||||||
cpuprofile = flag.String("cpuprofile", "", "write cpu profile to `file`")
|
cpuprofile = flag.String("cpuprofile", "", "write cpu profile to `file`")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// TODO: move all scaling into Window, so drivers only need to cope with one
|
||||||
|
// coordinate space. This will allow us to draw custom mouse cursors in the
|
||||||
|
// window, rather than in the driver.
|
||||||
type Window struct {
|
type Window struct {
|
||||||
Title string
|
Title string
|
||||||
KeyUpHandlers map[ebiten.Key]func()
|
KeyUpHandlers map[ebiten.Key]func()
|
||||||
MouseWheelHandler func(float64, float64)
|
MouseWheelHandler func(float64, float64)
|
||||||
|
|
||||||
|
cursor *ebiten.Image
|
||||||
|
|
||||||
// Allow the "game" to be switched out at any time
|
// Allow the "game" to be switched out at any time
|
||||||
game Game
|
game Game
|
||||||
|
|
||||||
@@ -68,6 +74,17 @@ func (w *Window) Layout(_, _ int) (int, int) {
|
|||||||
return w.xRes, w.yRes
|
return w.xRes, w.yRes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *Window) SetCursor(cursor *ebiten.Image) {
|
||||||
|
w.cursor = cursor
|
||||||
|
|
||||||
|
// Hide the system cursor if we have a custom one
|
||||||
|
if cursor == nil {
|
||||||
|
ebiten.SetCursorMode(ebiten.CursorModeVisible)
|
||||||
|
} else {
|
||||||
|
ebiten.SetCursorMode(ebiten.CursorModeHidden)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (w *Window) Update(screen *ebiten.Image) (outErr error) {
|
func (w *Window) Update(screen *ebiten.Image) (outErr error) {
|
||||||
// Ebiten does not like it if we panic inside its main loop
|
// Ebiten does not like it if we panic inside its main loop
|
||||||
defer func() {
|
defer func() {
|
||||||
@@ -108,6 +125,16 @@ func (w *Window) Update(screen *ebiten.Image) (outErr error) {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if w.cursor != nil {
|
||||||
|
// TODO: account for scaling, including the hotspot.
|
||||||
|
pos := image.Pt(ebiten.CursorPosition())
|
||||||
|
op := ebiten.DrawImageOptions{}
|
||||||
|
op.GeoM.Translate(float64(pos.X), float64(pos.Y))
|
||||||
|
if err := screen.DrawImage(w.cursor, &op); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if w.debug {
|
if w.debug {
|
||||||
// Draw FPS, etc, to the screen
|
// Draw FPS, etc, to the screen
|
||||||
msg := fmt.Sprintf("tps=%0.2f fps=%0.2f", ebiten.CurrentTPS(), ebiten.CurrentFPS())
|
msg := fmt.Sprintf("tps=%0.2f fps=%0.2f", ebiten.CurrentTPS(), ebiten.CurrentFPS())
|
||||||
|
Reference in New Issue
Block a user