diff --git a/cmd/view-menu/main.go b/cmd/view-menu/main.go index 8ebb192..1e587cc 100644 --- a/cmd/view-menu/main.go +++ b/cmd/view-menu/main.go @@ -3,13 +3,12 @@ package main import ( "flag" "fmt" + "image" "log" "os" "path/filepath" - "github.com/faiface/pixel" - "github.com/faiface/pixel/pixelgl" - "golang.org/x/image/colornames" + "github.com/hajimehoshi/ebiten" "ur.gs/ordoor/internal/conv" "ur.gs/ordoor/internal/data" @@ -26,41 +25,53 @@ var ( type env struct { menu *menus.Menu objects []*conv.Object - batch *pixel.Batch - fonts []*conv.Font - fontObjs []*conv.Object - fontBatch *pixel.Batch + fonts []*conv.Font + fontObjs []*conv.Object + + step int + state state + lastState state } type state struct { - env *env - cam pixel.Matrix - - step int // Redraw the window if these change - winPos pixel.Vec - winBounds pixel.Rect + winBounds image.Rectangle } -func loadObjects(names ...string) ([]*conv.Object, *pixel.Batch) { - var raw []*data.Object +func loadObjects(names ...string) ([]*conv.Object, error) { + objs := make([]*conv.Object, 0, len(names)) for _, name := range names { objFile := filepath.Join(filepath.Dir(*menuFile), name) - obj, err := data.LoadObject(objFile) + rawObj, err := data.LoadObject(objFile) if err != nil { log.Fatalf("Failed to load %s: %v", name, err) } - obj.Name = name - raw = append(raw, obj) + obj, err := conv.ConvertObject(rawObj, name) + if err != nil { + return nil, err + } + + objs = append(objs, obj) } - objects, spritesheet := conv.ConvertObjects(raw) - batch := pixel.NewBatch(&pixel.TrianglesData{}, spritesheet) + return objs, nil +} - return objects, batch +func loadFonts(names ...string) ([]*conv.Font, error) { + var out []*conv.Font + for _, name := range names { + fnt, err := fonts.LoadFont(filepath.Join(*gamePath, "Fonts", name+".fnt")) + if err != nil { + return nil, fmt.Errorf("%v: %v", name, err) + } + + out = append(out, conv.ConvertFont(fnt)) + } + + return out, nil } func main() { @@ -87,61 +98,36 @@ func main() { log.Fatalf("Failed to load font: %v", err) } - menuObjs, menuBatch := loadObjects(menu.ObjectFiles...) + menuObjs, err := loadObjects(menu.ObjectFiles...) + if err != nil { + log.Fatalf("Failed to load objects: %v", err) + } + state := state{} env := &env{ - menu: menu, objects: menuObjs, batch: menuBatch, - fonts: loadedFonts, + menu: menu, + objects: menuObjs, + fonts: loadedFonts, + state: state, + lastState: state, } - // The main thread now belongs to pixelgl - pixelgl.Run(env.run) -} - -func loadFonts(names ...string) ([]*conv.Font, error) { - var out []*conv.Font - for _, name := range names { - fnt, err := fonts.LoadFont(filepath.Join(*gamePath, "Fonts", name+".fnt")) - if err != nil { - return nil, fmt.Errorf("%v: %v", name, err) - } - - out = append(out, conv.ConvertFont(fnt)) - } - - return out, nil -} - -func (e *env) run() { win, err := ui.NewWindow("View Menu: " + *menuFile) if err != nil { log.Fatal("Couldn't create window: %v", err) } - pWin := win.PixelWindow - state := &state{env: e} - - // For now, just try to display the various objects - // left + right to change object, up + down to change frame - win.Run(func() { - oldState := *state - state = state.runStep(pWin) - - if oldState != *state || oldState.step == 0 { - state.present(pWin) - } - - state.step += 1 - }) + if err := win.Run(env.Update, env.Draw); err != nil { + log.Fatal(err) + } } -func (s *state) runStep(pWin *pixelgl.Window) *state { - newState := *s - newState.winPos = pWin.GetPos() - newState.winBounds = pWin.Bounds() - newState.handleKeys(pWin) +func (e *env) Update() error { + // No behaviour yet - return &newState + e.step += 1 + e.lastState = e.state + return nil } const ( @@ -149,35 +135,29 @@ const ( origY = 480.0 ) -func (s *state) present(pWin *pixelgl.Window) { - pWin.Clear(colornames.Black) - s.env.batch.Clear() - +func (e *env) Draw(screen *ebiten.Image) error { // The menus expect to be drawn to a 640x480 screen. We need to scale and // project that so it fills the window appropriately. This is a combination // of translate + zoom - winSize := pWin.Bounds().Max - scaleFactor := pixel.Vec{winSize.X / origX, winSize.Y / origY} + winSize := screen.Bounds().Max + scaleX := float64(winSize.X) / float64(origX) + scaleY := float64(winSize.Y) / float64(origY) - cam := pixel.IM - cam = cam.ScaledXY(pixel.ZV, pixel.Vec{1.0, -1.0}) // invert the Y axis - cam = cam.Moved(pixel.Vec{origX / 2, origY / 2}) - cam = cam.ScaledXY(pixel.ZV, scaleFactor) - s.cam = cam - s.env.batch.SetMatrix(cam) + cam := ebiten.GeoM{} + cam.Scale(scaleX, scaleY) - textCanvas := pixelgl.NewCanvas(pWin.Bounds()) - textCanvas.SetMatrix(pixel.IM.ScaledXY(pixel.ZV, scaleFactor)) - - for _, record := range s.env.menu.Records { - s.drawRecord(record, s.env.batch, textCanvas) + for _, record := range e.menu.Records { + if err := e.drawRecord(record, screen, cam); err != nil { + return err + } } - s.env.batch.Draw(pWin) - textCanvas.Draw(pWin, pixel.IM) + return nil } -func (s *state) drawRecord(record *menus.Record, target, textTarget pixel.Target) { +func (e *env) drawRecord(record *menus.Record, screen *ebiten.Image, offset ebiten.GeoM) error { + origOffset := offset + // Draw this record if it's valid to do so. FIXME: lots to learn if len(record.SpriteId) >= 0 { spriteId := record.SpriteId[0] @@ -210,59 +190,25 @@ func (s *state) drawRecord(record *menus.Record, target, textTarget pixel.Target ) // FIXME: Need to handle multiple objects - offset := pixel.V(x, y) - obj := s.env.objects[0] + obj := e.objects[0] sprite := obj.Sprites[spriteId] - sprite.Spr.Draw(target, pixel.IM.Moved(offset)) + + offset.Translate(x, y) + screen.DrawImage(sprite.Image, &ebiten.DrawImageOptions{GeoM: offset}) // FIXME: we probably shouldn't draw everything? // FIXME: handle multiple fonts - if len(s.env.fonts) > 0 && record.Desc != "" { - s.env.fonts[0].Output(textTarget, pixel.IM.Moved(offset), record.Desc) + if len(e.fonts) > 0 && record.Desc != "" { + e.fonts[0].Output(screen, origOffset, record.Desc) } } out: // Draw all children of this record for _, child := range record.Children { - s.drawRecord(child, target, textTarget) - } -} - -func (s *state) handleKeys(pWin *pixelgl.Window) { - if pWin.JustPressed(pixelgl.MouseButton1) { - log.Printf("cam: %#v", s.cam) - - pos := s.cam.Unproject(pWin.MousePosition()) - log.Printf("X=%v Y=%v", pos.X, pos.Y) + if err := e.drawRecord(child, screen, offset); err != nil { + return err + } } - /* - if pWin.JustPressed(pixelgl.KeyLeft) { - if s.objIdx > 0 { - s.objIdx -= 1 - s.spriteIdx = 0 - } - } - - if pWin.JustPressed(pixelgl.KeyRight) { - if s.objIdx < s.env.set.Count()-1 { - s.objIdx += 1 - s.spriteIdx = 0 - } - } - - if pWin.JustPressed(pixelgl.KeyDown) { - if s.spriteIdx > 0 { - s.spriteIdx -= 1 - } - } - - if pWin.JustPressed(pixelgl.KeyUp) { - if s.spriteIdx < len(s.curObject().Sprites)-1 { - s.spriteIdx += 1 - } - } - // Zoom in and out with the mouse wheel - s.zoom *= math.Pow(1.2, pWin.MouseScroll().Y) - */ + return nil } diff --git a/internal/conv/font.go b/internal/conv/font.go index 2137f01..1a869c2 100644 --- a/internal/conv/font.go +++ b/internal/conv/font.go @@ -3,35 +3,21 @@ package conv import ( "fmt" - "github.com/faiface/pixel" - "github.com/faiface/pixel/text" - "golang.org/x/image/colornames" - "golang.org/x/image/font/basicfont" - "ur.gs/ordoor/internal/fonts" ) type Font struct { Name string - Atlas *text.Atlas - Text *text.Text } -func (f *Font) Output(to pixel.Target, m pixel.Matrix, format string, args ...interface{}) { - text := text.New(pixel.V(0.0, 0.0), f.Atlas) - text.Color = colornames.White +func (f *Font) Output(to interface{}, m interface{}, format string, args ...interface{}) { - fmt.Fprintf(text, format, args...) + // FIXME: actually output some text onto screen - text.Draw(to, m) + fmt.Printf(format+"\n", args...) } func ConvertFont(font *fonts.Font) *Font { // FIXME: actually use the pixel data in font - atlas := text.NewAtlas(basicfont.Face7x13, text.ASCII) - - return &Font{ - Name: font.Name, - Atlas: atlas, - } + return &Font{Name: font.Name} }