183 lines
3.6 KiB
Go
183 lines
3.6 KiB
Go
package main
|
|
|
|
import (
|
|
"flag"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"time"
|
|
|
|
"github.com/FooSoft/lazarus/formats/dat"
|
|
"github.com/FooSoft/lazarus/formats/dc6"
|
|
"github.com/FooSoft/lazarus/graphics"
|
|
"github.com/FooSoft/lazarus/math"
|
|
"github.com/FooSoft/lazarus/platform"
|
|
"github.com/FooSoft/lazarus/platform/imgui"
|
|
)
|
|
|
|
func loadPalette(path string) (*dat.Palette, error) {
|
|
fp, err := os.Open(path)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer fp.Close()
|
|
return dat.NewFromReader(fp)
|
|
}
|
|
|
|
func loadAnimation(path string) (*dc6.Animation, error) {
|
|
fp, err := os.Open(path)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer fp.Close()
|
|
return dc6.NewFromReader(fp)
|
|
}
|
|
|
|
type scene struct {
|
|
animation *dc6.Animation
|
|
palette *dat.Palette
|
|
texture graphics.Texture
|
|
|
|
directionIndex int
|
|
frameIndex int
|
|
}
|
|
|
|
func (s *scene) Name() string {
|
|
return "viewer"
|
|
}
|
|
|
|
func (s *scene) Destroy() error {
|
|
if s.texture != nil {
|
|
return s.texture.Destroy()
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (s *scene) Advance() error {
|
|
var (
|
|
directionIndex = s.directionIndex
|
|
frameIndex = s.frameIndex
|
|
)
|
|
|
|
if s.texture == nil {
|
|
if err := s.updateTexture(); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
imgui.SetNextWindowSize(math.Vec2i{X: 300, Y: 400})
|
|
|
|
imgui.Begin("DC6 Viewer")
|
|
imgui.Image(s.texture)
|
|
direction := s.animation.Directions[directionIndex]
|
|
if imgui.SliderInt("Direction", &directionIndex, 0, len(s.animation.Directions)-1) {
|
|
frameIndex = 0
|
|
}
|
|
frame := direction.Frames[frameIndex]
|
|
imgui.SliderInt("Frame", &frameIndex, 0, len(direction.Frames)-1)
|
|
imgui.Columns(2)
|
|
imgui.Text("Size")
|
|
imgui.NextColumn()
|
|
imgui.Text("%+v", frame.Size)
|
|
imgui.NextColumn()
|
|
imgui.Text("Offset")
|
|
imgui.NextColumn()
|
|
imgui.Text("%+v", frame.Offset)
|
|
imgui.End()
|
|
|
|
if directionIndex != s.directionIndex || frameIndex != s.frameIndex {
|
|
s.directionIndex = directionIndex
|
|
s.frameIndex = frameIndex
|
|
s.updateTexture()
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (s *scene) updateTexture() error {
|
|
frame := s.animation.Directions[s.directionIndex].Frames[s.frameIndex]
|
|
colors := make([]math.Color3b, frame.Size.X*frame.Size.Y)
|
|
for y := 0; y < frame.Size.Y; y++ {
|
|
for x := 0; x < frame.Size.X; x++ {
|
|
colors[y*frame.Size.X+x] = s.palette.Colors[frame.Data[y*frame.Size.X+x]]
|
|
}
|
|
}
|
|
|
|
if s.texture != nil {
|
|
if err := s.texture.Destroy(); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
var err error
|
|
s.texture, err = platform.NewTextureFromRgb(colors, frame.Size)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func main() {
|
|
var (
|
|
palettePath = flag.String("palette", "", "path to palette file")
|
|
)
|
|
|
|
flag.Usage = func() {
|
|
fmt.Fprintf(os.Stderr, "Usage: %s [options] file\n", filepath.Base(os.Args[0]))
|
|
fmt.Fprintf(os.Stderr, "Parameters:\n\n")
|
|
flag.PrintDefaults()
|
|
}
|
|
|
|
flag.Parse()
|
|
|
|
if flag.NArg() < 1 {
|
|
flag.Usage()
|
|
os.Exit(2)
|
|
}
|
|
|
|
if err := platform.Initialize(); err != nil {
|
|
fmt.Fprintln(os.Stderr, err)
|
|
os.Exit(1)
|
|
}
|
|
defer platform.Shutdown()
|
|
|
|
animation, err := loadAnimation(flag.Arg(0))
|
|
if err != nil {
|
|
fmt.Fprintln(os.Stderr, err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
var palette *dat.Palette
|
|
if len(*palettePath) > 0 {
|
|
palette, err = loadPalette(*palettePath)
|
|
if err != nil {
|
|
fmt.Fprintln(os.Stderr, err)
|
|
os.Exit(1)
|
|
}
|
|
} else {
|
|
palette = dat.NewFromGrayscale()
|
|
}
|
|
|
|
scene := &scene{animation: animation, palette: palette}
|
|
if err := platform.WindowCreate("Viewer", math.Vec2i{X: 1024, Y: 768}, scene); err != nil {
|
|
fmt.Fprintln(os.Stderr, err)
|
|
os.Exit(1)
|
|
}
|
|
defer platform.WindowDestroy()
|
|
|
|
for {
|
|
run, err := platform.Advance()
|
|
if err != nil {
|
|
fmt.Fprintln(os.Stderr, err)
|
|
os.Exit(1)
|
|
}
|
|
if !run {
|
|
break
|
|
}
|
|
|
|
<-time.After(time.Millisecond * 25)
|
|
}
|
|
}
|