From ac490473b3aee0f7cc00bbee03924001775363e9 Mon Sep 17 00:00:00 2001 From: Noah Petherbridge Date: Sun, 5 May 2019 15:12:15 -0700 Subject: [PATCH] Load Doodads from System Path as well as User Path --- pkg/doodads/fmt_readwrite.go | 80 +++++++++++++++++++++++ pkg/editor_scene.go | 2 +- pkg/editor_ui.go | 8 ++- pkg/editor_ui_doodad.go | 7 +- pkg/{balance => filesystem}/filesystem.go | 14 ++-- pkg/level/fmt_binary.go | 6 +- pkg/level/fmt_readwrite.go | 4 +- pkg/play_scene.go | 2 +- pkg/uix/canvas_actors.go | 3 +- 9 files changed, 106 insertions(+), 20 deletions(-) create mode 100644 pkg/doodads/fmt_readwrite.go rename pkg/{balance => filesystem}/filesystem.go (88%) diff --git a/pkg/doodads/fmt_readwrite.go b/pkg/doodads/fmt_readwrite.go new file mode 100644 index 0000000..5034558 --- /dev/null +++ b/pkg/doodads/fmt_readwrite.go @@ -0,0 +1,80 @@ +package doodads + +import ( + "errors" + "fmt" + "io/ioutil" + "strings" + + "git.kirsle.net/apps/doodle/pkg/enum" + "git.kirsle.net/apps/doodle/pkg/filesystem" + "git.kirsle.net/apps/doodle/pkg/log" + "git.kirsle.net/apps/doodle/pkg/userdir" +) + +// ListDoodads returns a listing of all available doodads between all locations, +// including user doodads. +func ListDoodads() ([]string, error) { + var names []string + + // Read system-level doodads first. Ignore errors, if the system path is + // empty we still go on to read the user directory. + files, _ := ioutil.ReadDir(filesystem.SystemDoodadsPath) + + for _, file := range files { + name := file.Name() + if strings.HasSuffix(strings.ToLower(name), enum.DoodadExt) { + names = append(names, name) + } + } + + // Append user doodads. + userFiles, err := userdir.ListDoodads() + names = append(names, userFiles...) + return names, err +} + +// LoadFile reads a doodad file from disk, checking a few locations. +func LoadFile(filename string) (*Doodad, error) { + if !strings.HasSuffix(filename, enum.DoodadExt) { + filename += enum.DoodadExt + } + + // Search the system and user paths for this level. + filename, err := filesystem.FindFile(filename) + if err != nil { + return nil, fmt.Errorf("doodads.LoadFile(%s): %s", filename, err) + } + + // Load the JSON format. + if doodad, err := LoadJSON(filename); err == nil { + return doodad, nil + } else { + log.Warn(err.Error()) + } + + return nil, errors.New("invalid file type") +} + +// WriteFile saves a doodad to disk in the user's config directory. +func (d *Doodad) WriteFile(filename string) error { + if !strings.HasSuffix(filename, enum.DoodadExt) { + filename += enum.DoodadExt + } + + // bin, err := m.ToBinary() + bin, err := d.ToJSON() + if err != nil { + return err + } + + // Save it to their profile directory. + filename = userdir.DoodadPath(filename) + log.Info("Write Doodad: %s", filename) + err = ioutil.WriteFile(filename, bin, 0644) + if err != nil { + return fmt.Errorf("doodads.WriteFile: %s", err) + } + + return nil +} diff --git a/pkg/editor_scene.go b/pkg/editor_scene.go index d5ab0d0..4c1fd01 100644 --- a/pkg/editor_scene.go +++ b/pkg/editor_scene.go @@ -219,7 +219,7 @@ func (s *EditorScene) SaveLevel(filename string) error { func (s *EditorScene) LoadDoodad(filename string) error { s.filename = filename - doodad, err := doodads.LoadJSON(filename) + doodad, err := doodads.LoadFile(filename) if err != nil { return fmt.Errorf("EditorScene.LoadDoodad(%s): %s", filename, err) } diff --git a/pkg/editor_ui.go b/pkg/editor_ui.go index 71e2d0d..1664e6c 100644 --- a/pkg/editor_ui.go +++ b/pkg/editor_ui.go @@ -14,7 +14,6 @@ import ( "git.kirsle.net/apps/doodle/pkg/level" "git.kirsle.net/apps/doodle/pkg/log" "git.kirsle.net/apps/doodle/pkg/uix" - "git.kirsle.net/apps/doodle/pkg/userdir" ) // Width of the panel frame. @@ -261,7 +260,7 @@ func (u *EditorUI) SetupCanvas(d *Doodle) *uix.Canvas { // mode when you click an existing Doodad and it "pops" out of the canvas // and onto the cursor to be repositioned. drawing.OnDragStart = func(filename string) { - doodad, err := doodads.LoadJSON(userdir.DoodadPath(filename)) + doodad, err := doodads.LoadFile(filename) if err != nil { log.Error("drawing.OnDragStart: %s", err.Error()) } @@ -293,7 +292,10 @@ func (u *EditorUI) SetupCanvas(d *Doodle) *uix.Canvas { Filename: actor.doodad.Filename, }) - drawing.InstallActors(u.Scene.Level.Actors) + err := drawing.InstallActors(u.Scene.Level.Actors) + if err != nil { + log.Error("Error installing actor onDrop to canvas: %s", err) + } } }) u.Supervisor.Add(drawing) diff --git a/pkg/editor_ui_doodad.go b/pkg/editor_ui_doodad.go index 9f22342..4bae7d0 100644 --- a/pkg/editor_ui_doodad.go +++ b/pkg/editor_ui_doodad.go @@ -13,7 +13,6 @@ import ( "git.kirsle.net/apps/doodle/pkg/doodads" "git.kirsle.net/apps/doodle/pkg/log" "git.kirsle.net/apps/doodle/pkg/uix" - "git.kirsle.net/apps/doodle/pkg/userdir" ) // DraggableActor is a Doodad being dragged from the Doodad palette. @@ -50,10 +49,10 @@ func (u *EditorUI) setupDoodadFrame(e render.Engine, window *ui.Window) (*ui.Fra perRow = balance.UIDoodadsPerRow ) - doodadsAvailable, err := userdir.ListDoodads() + doodadsAvailable, err := doodads.ListDoodads() if err != nil { return frame, fmt.Errorf( - "setupDoodadFrame: userdir.ListDoodads: %s", + "setupDoodadFrame: doodads.ListDoodads: %s", err, ) } @@ -77,7 +76,7 @@ func (u *EditorUI) setupDoodadFrame(e render.Engine, window *ui.Window) (*ui.Fra } func(filename string) { - doodad, err := doodads.LoadJSON(userdir.DoodadPath(filename)) + doodad, err := doodads.LoadFile(filename) if err != nil { log.Error(err.Error()) doodad = doodads.New(balance.DoodadSize) diff --git a/pkg/balance/filesystem.go b/pkg/filesystem/filesystem.go similarity index 88% rename from pkg/balance/filesystem.go rename to pkg/filesystem/filesystem.go index 451b8c2..5b3dd39 100644 --- a/pkg/balance/filesystem.go +++ b/pkg/filesystem/filesystem.go @@ -1,4 +1,4 @@ -package balance +package filesystem import ( "errors" @@ -22,6 +22,12 @@ const ( BinDoodadType uint8 = 2 ) +// Paths to system-level assets bundled with the application. +var ( + SystemDoodadsPath = filepath.Join(".", "assets", "doodads") + SystemLevelsPath = filepath.Join(".", "assets", "levels") +) + // MakeHeader creates the binary file header. func MakeHeader(filetype uint8) []byte { header := make([]byte, len(BinMagic)+2) @@ -87,7 +93,7 @@ func FindFile(filename string) (string, error) { // Search level directories. if filetype == enum.LevelExt || filetype == "" { // system levels - candidate := filepath.Join(".", "assets", "levels", filename) + candidate := filepath.Join(SystemLevelsPath, filename) if _, err := os.Stat(candidate); !os.IsNotExist(err) { return candidate, nil } @@ -102,7 +108,7 @@ func FindFile(filename string) (string, error) { // Search doodad directories. if filetype == enum.DoodadExt || filetype == "" { // system doodads - candidate := filepath.Join(".", "assets", "doodads", filename) + candidate := filepath.Join(SystemDoodadsPath, filename) if _, err := os.Stat(candidate); !os.IsNotExist(err) { return candidate, nil } @@ -114,5 +120,5 @@ func FindFile(filename string) (string, error) { } } - return "", errors.New("file not found") + return filename, errors.New("file not found") } diff --git a/pkg/level/fmt_binary.go b/pkg/level/fmt_binary.go index bee89c7..d4293a2 100644 --- a/pkg/level/fmt_binary.go +++ b/pkg/level/fmt_binary.go @@ -6,13 +6,13 @@ import ( "io/ioutil" "os" - "git.kirsle.net/apps/doodle/pkg/balance" + "git.kirsle.net/apps/doodle/pkg/filesystem" "github.com/vmihailenco/msgpack" ) // ToBinary serializes the level to binary format. func (m *Level) ToBinary() ([]byte, error) { - header := balance.MakeHeader(balance.BinLevelType) + header := filesystem.MakeHeader(filesystem.BinLevelType) out := bytes.NewBuffer(header) encoder := msgpack.NewEncoder(out) err := encoder.Encode(m) @@ -43,7 +43,7 @@ func LoadBinary(filename string) (*Level, error) { defer fh.Close() // Read and verify the file header from the binary format. - err = balance.ReadHeader(balance.BinLevelType, fh) + err = filesystem.ReadHeader(filesystem.BinLevelType, fh) if err != nil { return nil, err } diff --git a/pkg/level/fmt_readwrite.go b/pkg/level/fmt_readwrite.go index 07bd774..8c4ab72 100644 --- a/pkg/level/fmt_readwrite.go +++ b/pkg/level/fmt_readwrite.go @@ -6,8 +6,8 @@ import ( "io/ioutil" "strings" - "git.kirsle.net/apps/doodle/pkg/balance" "git.kirsle.net/apps/doodle/pkg/enum" + "git.kirsle.net/apps/doodle/pkg/filesystem" "git.kirsle.net/apps/doodle/pkg/log" "git.kirsle.net/apps/doodle/pkg/userdir" ) @@ -19,7 +19,7 @@ func LoadFile(filename string) (*Level, error) { } // Search the system and user paths for this level. - filename, err := balance.FindFile(filename) + filename, err := filesystem.FindFile(filename) if err != nil { return nil, err } diff --git a/pkg/play_scene.go b/pkg/play_scene.go index 8b6f69d..b502e83 100644 --- a/pkg/play_scene.go +++ b/pkg/play_scene.go @@ -88,7 +88,7 @@ func (s *PlayScene) Setup(d *Doodle) error { } // Load in the player character. - player, err := doodads.LoadJSON("./assets/doodads/azu-blu.doodad") + player, err := doodads.LoadFile("./assets/doodads/azu-blu.doodad") if err != nil { log.Error("PlayScene.Setup: failed to load player doodad: %s", err) player = doodads.NewDummy(32) diff --git a/pkg/uix/canvas_actors.go b/pkg/uix/canvas_actors.go index 3a94b23..0ff0114 100644 --- a/pkg/uix/canvas_actors.go +++ b/pkg/uix/canvas_actors.go @@ -9,7 +9,6 @@ import ( "git.kirsle.net/apps/doodle/pkg/level" "git.kirsle.net/apps/doodle/pkg/log" "git.kirsle.net/apps/doodle/pkg/scripting" - "git.kirsle.net/apps/doodle/pkg/userdir" ) // InstallActors adds external Actors to the canvas to be superimposed on top @@ -17,7 +16,7 @@ import ( func (w *Canvas) InstallActors(actors level.ActorMap) error { w.actors = make([]*Actor, 0) for id, actor := range actors { - doodad, err := doodads.LoadJSON(userdir.DoodadPath(actor.Filename)) + doodad, err := doodads.LoadFile(actor.Filename) if err != nil { return fmt.Errorf("InstallActors: %s", err) }