Resolve circular import errors for Doodle++ plugin

* pkg/plus/dpp is the main plugin bridge, and defines nothing but an interface
  that defines the Doodle++ surface area (referring to internal game types such
  as doodad.Doodad or level.Level), but not their implementations.
  * dpp.Driver (an interface) is the main API that other parts of the game will
    call, for example "dpp.Driver.IsLevelSigned()"
  * plus_dpp.go and plus_foss.go provide the dpp.Driver implementation for their
    build; with plus_dpp.go generally forwarding function calls directly to the
    proprietary dpp package and plus_foss.go generally returning false/errors.
  * The bootstrap package simply assigns the above stub function to dpp.Driver
* pkg/plus/bootstrap is a package directly imported by main (in the doodle and
  doodad programs) and it works around circular dependency issues: this package
  simply assigns dpp.Driver to the DPP or FOSS version.

Miscellaneous fixes:

* File->Open in the editor and PlayScene will use the new Open Level window
  instead of loading the legacy GotoLoadMenu scene.
* Deprecated legacy scenes: d.GotoLoadMenu() and d.GotoPlayMenu().
* The doodle-admin program depends on the private dpp package, so can not be
  compiled in FOSS mode.
pull/93/head
Noah 2024-04-18 22:12:56 -07:00
parent 7eb7f6148c
commit a06787411d
32 changed files with 253 additions and 129 deletions

View File

@ -10,6 +10,7 @@ import (
"git.kirsle.net/SketchyMaze/doodle/cmd/doodad/commands" "git.kirsle.net/SketchyMaze/doodle/cmd/doodad/commands"
"git.kirsle.net/SketchyMaze/doodle/pkg/branding/builds" "git.kirsle.net/SketchyMaze/doodle/pkg/branding/builds"
"git.kirsle.net/SketchyMaze/doodle/pkg/log" "git.kirsle.net/SketchyMaze/doodle/pkg/log"
"git.kirsle.net/SketchyMaze/doodle/pkg/plus/bootstrap"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
) )
@ -26,6 +27,8 @@ func init() {
} }
func main() { func main() {
bootstrap.InitPlugins()
app := cli.NewApp() app := cli.NewApp()
app.Name = "doodad" app.Name = "doodad"
app.Usage = "command line interface for Doodle" app.Usage = "command line interface for Doodle"

View File

@ -1,8 +1,8 @@
package command package command
import ( import (
"git.kirsle.net/SketchyMaze/doodle/pkg/license"
"git.kirsle.net/SketchyMaze/doodle/pkg/log" "git.kirsle.net/SketchyMaze/doodle/pkg/log"
"git.kirsle.net/SketchyMaze/dpp/license"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
) )

View File

@ -4,8 +4,8 @@ import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"git.kirsle.net/SketchyMaze/doodle/pkg/license"
"git.kirsle.net/SketchyMaze/doodle/pkg/log" "git.kirsle.net/SketchyMaze/doodle/pkg/log"
"git.kirsle.net/SketchyMaze/dpp/license"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
) )

View File

@ -6,8 +6,8 @@ import (
"git.kirsle.net/SketchyMaze/doodle/pkg/level" "git.kirsle.net/SketchyMaze/doodle/pkg/level"
"git.kirsle.net/SketchyMaze/doodle/pkg/levelpack" "git.kirsle.net/SketchyMaze/doodle/pkg/levelpack"
"git.kirsle.net/SketchyMaze/doodle/pkg/license" "git.kirsle.net/SketchyMaze/dpp/license"
"git.kirsle.net/SketchyMaze/doodle/pkg/license/levelsigning" "git.kirsle.net/SketchyMaze/dpp/license/levelsigning"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
) )

View File

@ -4,8 +4,8 @@ import (
"io/ioutil" "io/ioutil"
"time" "time"
"git.kirsle.net/SketchyMaze/doodle/pkg/license"
"git.kirsle.net/SketchyMaze/doodle/pkg/log" "git.kirsle.net/SketchyMaze/doodle/pkg/log"
"git.kirsle.net/SketchyMaze/dpp/license"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
) )

View File

@ -5,9 +5,9 @@ import (
"git.kirsle.net/SketchyMaze/doodle/pkg/level" "git.kirsle.net/SketchyMaze/doodle/pkg/level"
"git.kirsle.net/SketchyMaze/doodle/pkg/levelpack" "git.kirsle.net/SketchyMaze/doodle/pkg/levelpack"
"git.kirsle.net/SketchyMaze/doodle/pkg/license"
"git.kirsle.net/SketchyMaze/doodle/pkg/license/levelsigning"
"git.kirsle.net/SketchyMaze/doodle/pkg/log" "git.kirsle.net/SketchyMaze/doodle/pkg/log"
"git.kirsle.net/SketchyMaze/dpp/license"
"git.kirsle.net/SketchyMaze/dpp/license/levelsigning"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
) )

View File

@ -20,6 +20,7 @@ import (
"git.kirsle.net/SketchyMaze/doodle/pkg/gamepad" "git.kirsle.net/SketchyMaze/doodle/pkg/gamepad"
"git.kirsle.net/SketchyMaze/doodle/pkg/log" "git.kirsle.net/SketchyMaze/doodle/pkg/log"
"git.kirsle.net/SketchyMaze/doodle/pkg/native" "git.kirsle.net/SketchyMaze/doodle/pkg/native"
"git.kirsle.net/SketchyMaze/doodle/pkg/plus/bootstrap"
"git.kirsle.net/SketchyMaze/doodle/pkg/shmem" "git.kirsle.net/SketchyMaze/doodle/pkg/shmem"
"git.kirsle.net/SketchyMaze/doodle/pkg/sound" "git.kirsle.net/SketchyMaze/doodle/pkg/sound"
"git.kirsle.net/SketchyMaze/doodle/pkg/sprites" "git.kirsle.net/SketchyMaze/doodle/pkg/sprites"
@ -51,6 +52,8 @@ func init() {
func main() { func main() {
runtime.LockOSThread() runtime.LockOSThread()
bootstrap.InitPlugins()
app := cli.NewApp() app := cli.NewApp()
app.Name = "doodle" app.Name = "doodle"
app.Usage = fmt.Sprintf("%s - %s", branding.AppName, branding.Summary) app.Usage = fmt.Sprintf("%s - %s", branding.AppName, branding.Summary)

View File

@ -6,7 +6,7 @@ import (
"git.kirsle.net/SketchyMaze/doodle/pkg/balance" "git.kirsle.net/SketchyMaze/doodle/pkg/balance"
"git.kirsle.net/SketchyMaze/doodle/pkg/branding" "git.kirsle.net/SketchyMaze/doodle/pkg/branding"
"git.kirsle.net/SketchyMaze/doodle/pkg/license" "git.kirsle.net/SketchyMaze/doodle/pkg/plus/dpp"
) )
var ( var (
@ -26,7 +26,7 @@ var (
func init() { func init() {
if !balance.DPP { if !balance.DPP {
VersionSuffix = " (open source)" VersionSuffix = " (open source)"
} else if !license.IsRegistered() { } else if !dpp.Driver.IsRegistered() {
VersionSuffix = " (shareware)" VersionSuffix = " (shareware)"
} else { } else {
VersionSuffix = "" VersionSuffix = ""

View File

@ -15,16 +15,17 @@ import (
"git.kirsle.net/SketchyMaze/doodle/pkg/level" "git.kirsle.net/SketchyMaze/doodle/pkg/level"
"git.kirsle.net/SketchyMaze/doodle/pkg/level/giant_screenshot" "git.kirsle.net/SketchyMaze/doodle/pkg/level/giant_screenshot"
"git.kirsle.net/SketchyMaze/doodle/pkg/level/publishing" "git.kirsle.net/SketchyMaze/doodle/pkg/level/publishing"
"git.kirsle.net/SketchyMaze/doodle/pkg/license"
"git.kirsle.net/SketchyMaze/doodle/pkg/log" "git.kirsle.net/SketchyMaze/doodle/pkg/log"
"git.kirsle.net/SketchyMaze/doodle/pkg/modal" "git.kirsle.net/SketchyMaze/doodle/pkg/modal"
"git.kirsle.net/SketchyMaze/doodle/pkg/modal/loadscreen" "git.kirsle.net/SketchyMaze/doodle/pkg/modal/loadscreen"
"git.kirsle.net/SketchyMaze/doodle/pkg/native" "git.kirsle.net/SketchyMaze/doodle/pkg/native"
"git.kirsle.net/SketchyMaze/doodle/pkg/plus"
"git.kirsle.net/SketchyMaze/doodle/pkg/usercfg" "git.kirsle.net/SketchyMaze/doodle/pkg/usercfg"
"git.kirsle.net/SketchyMaze/doodle/pkg/userdir" "git.kirsle.net/SketchyMaze/doodle/pkg/userdir"
"git.kirsle.net/SketchyMaze/doodle/pkg/windows" "git.kirsle.net/SketchyMaze/doodle/pkg/windows"
"git.kirsle.net/go/render" "git.kirsle.net/go/render"
"git.kirsle.net/go/render/event" "git.kirsle.net/go/render/event"
"git.kirsle.net/go/ui"
) )
// EditorScene manages the "Edit Level" game mode. // EditorScene manages the "Edit Level" game mode.
@ -55,6 +56,8 @@ type EditorScene struct {
filename string filename string
lastAutosaveAt time.Time lastAutosaveAt time.Time
winOpenLevel *ui.Window
} }
// Name of the scene. // Name of the scene.
@ -252,7 +255,7 @@ func (s *EditorScene) setupAsync(d *Doodle) error {
func (s *EditorScene) installActors() error { func (s *EditorScene) installActors() error {
if err := s.UI.Canvas.InstallActors(s.Level.Actors); err != nil { if err := s.UI.Canvas.InstallActors(s.Level.Actors); err != nil {
summary := "This level references some doodads that were not found:" summary := "This level references some doodads that were not found:"
if strings.Contains(err.Error(), license.ErrRegisteredFeature.Error()) { if strings.Contains(err.Error(), plus.ErrRegisteredFeature.Error()) {
summary = "This level contains embedded doodads, but this is not\n" + summary = "This level contains embedded doodads, but this is not\n" +
"available in the free version of the game. The following\n" + "available in the free version of the game. The following\n" +
"doodads could not be loaded:" "doodads could not be loaded:"
@ -507,7 +510,7 @@ func (s *EditorScene) LoadLevel(filename string) error {
log.Info("Installing %d actors into the drawing", len(level.Actors)) log.Info("Installing %d actors into the drawing", len(level.Actors))
if err := s.UI.Canvas.InstallActors(level.Actors); err != nil { if err := s.UI.Canvas.InstallActors(level.Actors); err != nil {
summary := "This level references some doodads that were not found:" summary := "This level references some doodads that were not found:"
if strings.Contains(err.Error(), license.ErrRegisteredFeature.Error()) { if strings.Contains(err.Error(), plus.ErrRegisteredFeature.Error()) {
summary = "This level contains embedded doodads, but this is not\n" + summary = "This level contains embedded doodads, but this is not\n" +
"available in the free version of the game. The following\n" + "available in the free version of the game. The following\n" +
"doodads could not be loaded:" "doodads could not be loaded:"

View File

@ -9,7 +9,7 @@ import (
"git.kirsle.net/SketchyMaze/doodle/pkg/doodads" "git.kirsle.net/SketchyMaze/doodle/pkg/doodads"
"git.kirsle.net/SketchyMaze/doodle/pkg/level" "git.kirsle.net/SketchyMaze/doodle/pkg/level"
"git.kirsle.net/SketchyMaze/doodle/pkg/log" "git.kirsle.net/SketchyMaze/doodle/pkg/log"
"git.kirsle.net/SketchyMaze/doodle/pkg/plus" "git.kirsle.net/SketchyMaze/doodle/pkg/plus/dpp"
"git.kirsle.net/SketchyMaze/doodle/pkg/uix" "git.kirsle.net/SketchyMaze/doodle/pkg/uix"
"git.kirsle.net/go/render" "git.kirsle.net/go/render"
) )
@ -35,7 +35,7 @@ func (u *EditorUI) startDragActor(doodad *doodads.Doodad, actor *level.Actor) {
if doodad == nil { if doodad == nil {
if actor != nil { if actor != nil {
obj, err := plus.DoodadFromEmbeddable(actor.Filename, u.Scene.Level, false) obj, err := dpp.Driver.LoadFromEmbeddable(actor.Filename, u.Scene.Level, false)
if err != nil { if err != nil {
log.Error("startDragExistingActor: actor doodad name %s not found: %s", actor.Filename, err) log.Error("startDragExistingActor: actor doodad name %s not found: %s", actor.Filename, err)
return return

View File

@ -9,10 +9,11 @@ import (
"git.kirsle.net/SketchyMaze/doodle/pkg/drawtool" "git.kirsle.net/SketchyMaze/doodle/pkg/drawtool"
"git.kirsle.net/SketchyMaze/doodle/pkg/enum" "git.kirsle.net/SketchyMaze/doodle/pkg/enum"
"git.kirsle.net/SketchyMaze/doodle/pkg/level/giant_screenshot" "git.kirsle.net/SketchyMaze/doodle/pkg/level/giant_screenshot"
"git.kirsle.net/SketchyMaze/doodle/pkg/license"
"git.kirsle.net/SketchyMaze/doodle/pkg/log" "git.kirsle.net/SketchyMaze/doodle/pkg/log"
"git.kirsle.net/SketchyMaze/doodle/pkg/modal" "git.kirsle.net/SketchyMaze/doodle/pkg/modal"
"git.kirsle.net/SketchyMaze/doodle/pkg/native" "git.kirsle.net/SketchyMaze/doodle/pkg/native"
"git.kirsle.net/SketchyMaze/doodle/pkg/plus/dpp"
"git.kirsle.net/SketchyMaze/doodle/pkg/shmem"
"git.kirsle.net/SketchyMaze/doodle/pkg/userdir" "git.kirsle.net/SketchyMaze/doodle/pkg/userdir"
"git.kirsle.net/SketchyMaze/doodle/pkg/windows" "git.kirsle.net/SketchyMaze/doodle/pkg/windows"
"git.kirsle.net/go/render" "git.kirsle.net/go/render"
@ -282,7 +283,7 @@ func (u *EditorUI) SetupMenuBar(d *Doodle) *ui.MenuBar {
// Registration item for Doodle++ builds. // Registration item for Doodle++ builds.
if balance.DPP { if balance.DPP {
var registerText = "Register" var registerText = "Register"
if license.IsRegistered() { if dpp.Driver.IsRegistered() {
registerText = "Registration" registerText = "Registration"
} }
@ -318,7 +319,24 @@ func (s *EditorScene) MenuNewDoodad() {
// File->Open, or Ctrl-O // File->Open, or Ctrl-O
func (s *EditorScene) MenuOpen() { func (s *EditorScene) MenuOpen() {
s.ConfirmUnload(func() { s.ConfirmUnload(func() {
s.d.GotoLoadMenu() if s.winOpenLevel == nil {
s.winOpenLevel = windows.NewOpenDrawingWindow(windows.OpenDrawing{
Supervisor: s.UI.Supervisor,
Engine: shmem.CurrentRenderEngine,
OnOpenDrawing: func(filename string) {
s.d.EditFile(filename)
},
OnCloseWindow: func() {
s.winOpenLevel.Destroy()
s.winOpenLevel = nil
},
})
}
s.winOpenLevel.MoveTo(render.Point{
X: (s.d.width / 2) - (s.winOpenLevel.Size().W / 2),
Y: (s.d.height / 2) - (s.winOpenLevel.Size().H / 2),
})
s.winOpenLevel.Show()
}) })
} }

View File

@ -9,9 +9,9 @@ import (
"git.kirsle.net/SketchyMaze/doodle/pkg/doodads" "git.kirsle.net/SketchyMaze/doodle/pkg/doodads"
"git.kirsle.net/SketchyMaze/doodle/pkg/drawtool" "git.kirsle.net/SketchyMaze/doodle/pkg/drawtool"
"git.kirsle.net/SketchyMaze/doodle/pkg/level" "git.kirsle.net/SketchyMaze/doodle/pkg/level"
"git.kirsle.net/SketchyMaze/doodle/pkg/license"
"git.kirsle.net/SketchyMaze/doodle/pkg/log" "git.kirsle.net/SketchyMaze/doodle/pkg/log"
"git.kirsle.net/SketchyMaze/doodle/pkg/modal" "git.kirsle.net/SketchyMaze/doodle/pkg/modal"
"git.kirsle.net/SketchyMaze/doodle/pkg/plus/dpp"
"git.kirsle.net/SketchyMaze/doodle/pkg/windows" "git.kirsle.net/SketchyMaze/doodle/pkg/windows"
"git.kirsle.net/go/render" "git.kirsle.net/go/render"
"git.kirsle.net/go/ui" "git.kirsle.net/go/ui"
@ -68,7 +68,7 @@ func (u *EditorUI) OpenPublishWindow() {
OnPublish: func(includeBuiltins bool) { OnPublish: func(includeBuiltins bool) {
u.d.FlashError("OnPublish Called") u.d.FlashError("OnPublish Called")
// XXX: Paid Version Only. // XXX: Paid Version Only.
if !license.IsRegistered() { if !dpp.Driver.IsRegistered() {
if u.licenseWindow != nil { if u.licenseWindow != nil {
u.licenseWindow.Show() u.licenseWindow.Show()
u.Supervisor.FocusWindow(u.licenseWindow) u.Supervisor.FocusWindow(u.licenseWindow)

View File

@ -11,7 +11,7 @@ import (
"git.kirsle.net/SketchyMaze/doodle/pkg/level" "git.kirsle.net/SketchyMaze/doodle/pkg/level"
"git.kirsle.net/SketchyMaze/doodle/pkg/log" "git.kirsle.net/SketchyMaze/doodle/pkg/log"
"git.kirsle.net/SketchyMaze/doodle/pkg/plus" "git.kirsle.net/SketchyMaze/doodle/pkg/plus/dpp"
"git.kirsle.net/SketchyMaze/doodle/pkg/shmem" "git.kirsle.net/SketchyMaze/doodle/pkg/shmem"
"git.kirsle.net/SketchyMaze/doodle/pkg/userdir" "git.kirsle.net/SketchyMaze/doodle/pkg/userdir"
"git.kirsle.net/SketchyMaze/doodle/pkg/wallpaper" "git.kirsle.net/SketchyMaze/doodle/pkg/wallpaper"
@ -95,7 +95,7 @@ func GiantScreenshot(lvl *level.Level) (image.Image, error) {
// Render the doodads. // Render the doodads.
log.Debug("GiantScreenshot: Render actors...") log.Debug("GiantScreenshot: Render actors...")
for _, actor := range lvl.Actors { for _, actor := range lvl.Actors {
doodad, err := plus.DoodadFromEmbeddable(actor.Filename, lvl, false) doodad, err := dpp.Driver.LoadFromEmbeddable(actor.Filename, lvl, false)
if err != nil { if err != nil {
log.Error("GiantScreenshot: Load doodad: %s", err) log.Error("GiantScreenshot: Load doodad: %s", err)
continue continue

View File

@ -14,7 +14,7 @@ import (
"git.kirsle.net/SketchyMaze/doodle/pkg/balance" "git.kirsle.net/SketchyMaze/doodle/pkg/balance"
"git.kirsle.net/SketchyMaze/doodle/pkg/level" "git.kirsle.net/SketchyMaze/doodle/pkg/level"
"git.kirsle.net/SketchyMaze/doodle/pkg/log" "git.kirsle.net/SketchyMaze/doodle/pkg/log"
"git.kirsle.net/SketchyMaze/doodle/pkg/plus" "git.kirsle.net/SketchyMaze/doodle/pkg/plus/dpp"
"git.kirsle.net/SketchyMaze/doodle/pkg/userdir" "git.kirsle.net/SketchyMaze/doodle/pkg/userdir"
"git.kirsle.net/go/render" "git.kirsle.net/go/render"
"golang.org/x/image/draw" "golang.org/x/image/draw"
@ -78,7 +78,7 @@ func CroppedScreenshot(lvl *level.Level, viewport render.Rect) (image.Image, err
// Render the doodads. // Render the doodads.
log.Debug("CroppedScreenshot: Render actors...") log.Debug("CroppedScreenshot: Render actors...")
for _, actor := range lvl.Actors { for _, actor := range lvl.Actors {
doodad, err := plus.DoodadFromEmbeddable(actor.Filename, lvl, false) doodad, err := dpp.Driver.LoadFromEmbeddable(actor.Filename, lvl, false)
if err != nil { if err != nil {
log.Error("CroppedScreenshot: Load doodad: %s", err) log.Error("CroppedScreenshot: Load doodad: %s", err)
continue continue

View File

@ -17,9 +17,8 @@ import (
"git.kirsle.net/SketchyMaze/doodle/pkg/balance" "git.kirsle.net/SketchyMaze/doodle/pkg/balance"
"git.kirsle.net/SketchyMaze/doodle/pkg/doodads" "git.kirsle.net/SketchyMaze/doodle/pkg/doodads"
"git.kirsle.net/SketchyMaze/doodle/pkg/level" "git.kirsle.net/SketchyMaze/doodle/pkg/level"
"git.kirsle.net/SketchyMaze/doodle/pkg/license"
"git.kirsle.net/SketchyMaze/doodle/pkg/log" "git.kirsle.net/SketchyMaze/doodle/pkg/log"
"git.kirsle.net/SketchyMaze/doodle/pkg/plus" "git.kirsle.net/SketchyMaze/doodle/pkg/plus/dpp"
) )
/* /*
@ -38,7 +37,7 @@ func Publish(lvl *level.Level) error {
} }
// Registered games only. // Registered games only.
if !balance.DPP || !license.IsRegistered() { if !balance.DPP || !dpp.Driver.IsRegistered() {
return errors.New("only registered versions of the game can attach doodads to levels") return errors.New("only registered versions of the game can attach doodads to levels")
} }
@ -53,7 +52,7 @@ func Publish(lvl *level.Level) error {
log.Debug("Embed filename: %s", filename) log.Debug("Embed filename: %s", filename)
names[filename] = nil names[filename] = nil
doodad, err := plus.DoodadFromEmbeddable(filename, lvl, false) doodad, err := dpp.Driver.LoadFromEmbeddable(filename, lvl, false)
if err != nil { if err != nil {
return fmt.Errorf("couldn't load doodad %s: %s", filename, err) return fmt.Errorf("couldn't load doodad %s: %s", filename, err)
} }

View File

@ -9,10 +9,10 @@ import (
"git.kirsle.net/SketchyMaze/doodle/pkg/branding/builds" "git.kirsle.net/SketchyMaze/doodle/pkg/branding/builds"
"git.kirsle.net/SketchyMaze/doodle/pkg/level" "git.kirsle.net/SketchyMaze/doodle/pkg/level"
"git.kirsle.net/SketchyMaze/doodle/pkg/levelpack" "git.kirsle.net/SketchyMaze/doodle/pkg/levelpack"
"git.kirsle.net/SketchyMaze/doodle/pkg/license"
"git.kirsle.net/SketchyMaze/doodle/pkg/log" "git.kirsle.net/SketchyMaze/doodle/pkg/log"
"git.kirsle.net/SketchyMaze/doodle/pkg/modal/loadscreen" "git.kirsle.net/SketchyMaze/doodle/pkg/modal/loadscreen"
"git.kirsle.net/SketchyMaze/doodle/pkg/native" "git.kirsle.net/SketchyMaze/doodle/pkg/native"
"git.kirsle.net/SketchyMaze/doodle/pkg/plus/dpp"
"git.kirsle.net/SketchyMaze/doodle/pkg/savegame" "git.kirsle.net/SketchyMaze/doodle/pkg/savegame"
"git.kirsle.net/SketchyMaze/doodle/pkg/scripting" "git.kirsle.net/SketchyMaze/doodle/pkg/scripting"
"git.kirsle.net/SketchyMaze/doodle/pkg/shmem" "git.kirsle.net/SketchyMaze/doodle/pkg/shmem"
@ -225,7 +225,7 @@ func (s *MainScene) Setup(d *Doodle) error {
{ {
Name: "Register", Name: "Register",
If: func() bool { If: func() bool {
return balance.DPP && !license.IsRegistered() return balance.DPP && !dpp.Driver.IsRegistered()
}, },
Func: func() { Func: func() {
if s.winRegister == nil { if s.winRegister == nil {

View File

@ -73,6 +73,8 @@ func (d *Doodle) GotoNewDoodadMenu() {
} }
// GotoLoadMenu loads the MenuScene and shows the "Load" window. // GotoLoadMenu loads the MenuScene and shows the "Load" window.
//
// DEPRECATED: loads the old menu, in dev console run `$ d.GotoLoadMenu()` to see.
func (d *Doodle) GotoLoadMenu() { func (d *Doodle) GotoLoadMenu() {
log.Info("Loading the MenuScene to the Load window for Edit Mode") log.Info("Loading the MenuScene to the Load window for Edit Mode")
scene := &MenuScene{ scene := &MenuScene{
@ -83,6 +85,8 @@ func (d *Doodle) GotoLoadMenu() {
// GotoPlayMenu loads the MenuScene and shows the "Load" window for playing a // GotoPlayMenu loads the MenuScene and shows the "Load" window for playing a
// level, not editing it. // level, not editing it.
//
// DEPRECATED: loads the old menu, in dev console run `$ d.GotoPlayMenu()` to see.
func (d *Doodle) GotoPlayMenu() { func (d *Doodle) GotoPlayMenu() {
log.Info("Loading the MenuScene to the Load window for Play Mode") log.Info("Loading the MenuScene to the Load window for Play Mode")
scene := &MenuScene{ scene := &MenuScene{

View File

@ -3,7 +3,7 @@ package native
import ( import (
"os" "os"
"git.kirsle.net/SketchyMaze/doodle/pkg/plus" "git.kirsle.net/SketchyMaze/doodle/pkg/plus/dpp"
) )
var USER string = os.Getenv("USER") var USER string = os.Getenv("USER")
@ -17,9 +17,9 @@ If they have registered the game, use the name from their license JWT token.
Otherwise fall back to their native operating system user. Otherwise fall back to their native operating system user.
*/ */
func DefaultAuthor() string { func DefaultAuthor() string {
// Are we registered? // Are we registered? TODO: get from registration
if plus.IsRegistered() { if dpp.Driver.IsRegistered() {
if reg, err := plus.GetRegistration(); err == nil { if reg, err := dpp.Driver.GetRegistration(); err == nil {
return reg.Name return reg.Name
} }
} }

View File

@ -13,13 +13,12 @@ import (
"git.kirsle.net/SketchyMaze/doodle/pkg/keybind" "git.kirsle.net/SketchyMaze/doodle/pkg/keybind"
"git.kirsle.net/SketchyMaze/doodle/pkg/level" "git.kirsle.net/SketchyMaze/doodle/pkg/level"
"git.kirsle.net/SketchyMaze/doodle/pkg/levelpack" "git.kirsle.net/SketchyMaze/doodle/pkg/levelpack"
"git.kirsle.net/SketchyMaze/doodle/pkg/license"
"git.kirsle.net/SketchyMaze/doodle/pkg/license/levelsigning"
"git.kirsle.net/SketchyMaze/doodle/pkg/log" "git.kirsle.net/SketchyMaze/doodle/pkg/log"
"git.kirsle.net/SketchyMaze/doodle/pkg/modal" "git.kirsle.net/SketchyMaze/doodle/pkg/modal"
"git.kirsle.net/SketchyMaze/doodle/pkg/modal/loadscreen" "git.kirsle.net/SketchyMaze/doodle/pkg/modal/loadscreen"
"git.kirsle.net/SketchyMaze/doodle/pkg/physics" "git.kirsle.net/SketchyMaze/doodle/pkg/physics"
"git.kirsle.net/SketchyMaze/doodle/pkg/plus" "git.kirsle.net/SketchyMaze/doodle/pkg/plus"
"git.kirsle.net/SketchyMaze/doodle/pkg/plus/dpp"
"git.kirsle.net/SketchyMaze/doodle/pkg/savegame" "git.kirsle.net/SketchyMaze/doodle/pkg/savegame"
"git.kirsle.net/SketchyMaze/doodle/pkg/scripting" "git.kirsle.net/SketchyMaze/doodle/pkg/scripting"
"git.kirsle.net/SketchyMaze/doodle/pkg/shmem" "git.kirsle.net/SketchyMaze/doodle/pkg/shmem"
@ -63,6 +62,7 @@ type PlayScene struct {
menubar *ui.MenuBar menubar *ui.MenuBar
editButton *ui.Button editButton *ui.Button
winLevelPacks *ui.Window winLevelPacks *ui.Window
winOpenLevel *ui.Window
// Custom debug labels. // Custom debug labels.
debPosition *string debPosition *string
@ -247,7 +247,7 @@ func (s *PlayScene) setupAsync(d *Doodle) error {
s.drawing.OnResetTimer = s.ResetTimer s.drawing.OnResetTimer = s.ResetTimer
// If this level game from a signed LevelPack, inform the canvas. // If this level game from a signed LevelPack, inform the canvas.
if s.LevelPack != nil && levelsigning.IsLevelPackSigned(s.LevelPack) { if s.LevelPack != nil && dpp.Driver.IsLevelPackSigned(s.LevelPack) {
s.drawing.IsSignedLevelPack = s.LevelPack s.drawing.IsSignedLevelPack = s.LevelPack
} }
@ -337,7 +337,7 @@ func (s *PlayScene) setupAsync(d *Doodle) error {
func (s *PlayScene) installActors() error { func (s *PlayScene) installActors() error {
if err := s.drawing.InstallActors(s.Level.Actors); err != nil { if err := s.drawing.InstallActors(s.Level.Actors); err != nil {
summary := "This level references some doodads that were not found:" summary := "This level references some doodads that were not found:"
if strings.Contains(err.Error(), license.ErrRegisteredFeature.Error()) { if strings.Contains(err.Error(), plus.ErrRegisteredFeature.Error()) {
summary = "This level contains embedded doodads, but this is not\n" + summary = "This level contains embedded doodads, but this is not\n" +
"available in the free version of the game. The following\n" + "available in the free version of the game. The following\n" +
"doodads could not be loaded:" "doodads could not be loaded:"
@ -504,7 +504,7 @@ func (s *PlayScene) setupPlayer(playerCharacterFilename string) {
// centerIn is optional, ignored if zero. // centerIn is optional, ignored if zero.
func (s *PlayScene) installPlayerDoodad(filename string, spawn render.Point, centerIn render.Rect) { func (s *PlayScene) installPlayerDoodad(filename string, spawn render.Point, centerIn render.Rect) {
// Load in the player character. // Load in the player character.
player, err := plus.DoodadFromEmbeddable(filename, s.Level, false) player, err := dpp.Driver.LoadFromEmbeddable(filename, s.Level, false)
if err != nil { if err != nil {
log.Error("PlayScene.Setup: failed to load player doodad: %s", err) log.Error("PlayScene.Setup: failed to load player doodad: %s", err)
player = doodads.NewDummy(32) player = doodads.NewDummy(32)

View File

@ -40,7 +40,26 @@ func (u *PlayScene) setupMenuBar(d *Doodle) *ui.MenuBar {
u.winLevelPacks.Show() u.winLevelPacks.Show()
}) })
gameMenu.AddItemAccel("New drawing", "Ctrl-N", d.GotoNewMenu) gameMenu.AddItemAccel("New drawing", "Ctrl-N", d.GotoNewMenu)
gameMenu.AddItemAccel("Open drawing", "Ctrl-O", d.GotoLoadMenu) gameMenu.AddItemAccel("Open drawing", "Ctrl-O", func() {
if u.winOpenLevel == nil {
u.winOpenLevel = windows.NewOpenDrawingWindow(windows.OpenDrawing{
Supervisor: u.Supervisor,
Engine: shmem.CurrentRenderEngine,
OnOpenDrawing: func(filename string) {
d.EditFile(filename)
},
OnCloseWindow: func() {
u.winOpenLevel.Destroy()
u.winOpenLevel = nil
},
})
}
u.winOpenLevel.MoveTo(render.Point{
X: (d.width / 2) - (u.winOpenLevel.Size().W / 2),
Y: (d.height / 2) - (u.winOpenLevel.Size().H / 2),
})
u.winOpenLevel.Show()
})
gameMenu.AddSeparator() gameMenu.AddSeparator()
gameMenu.AddItem("Quit to menu", func() { gameMenu.AddItem("Quit to menu", func() {

View File

@ -0,0 +1,21 @@
//go:build dpp
// +build dpp
/*
Package bootstrap is a common import between the Doodle and Doodad programs.
Its chief job is to work around circular dependency issues when dealing with
pluggable parts of the codebase, such as Doodle++ which adds features for the
official release which are missing from the FOSS version.
*/
package bootstrap
import (
"git.kirsle.net/SketchyMaze/doodle/pkg/plus/dpp"
)
var Driver dpp.Pluggable
func InitPlugins() {
Driver = dpp.Plugin{}
}

View File

@ -0,0 +1,14 @@
//go:build !dpp
// +build !dpp
package bootstrap
import (
"git.kirsle.net/SketchyMaze/doodle/pkg/plus/dpp"
)
var Driver dpp.Pluggable
func InitPlugins() {
Driver = dpp.Plugin{}
}

21
pkg/plus/dpp/plugin.go Normal file
View File

@ -0,0 +1,21 @@
package dpp
import (
"git.kirsle.net/SketchyMaze/doodle/pkg/doodads"
"git.kirsle.net/SketchyMaze/doodle/pkg/filesystem"
"git.kirsle.net/SketchyMaze/doodle/pkg/level"
"git.kirsle.net/SketchyMaze/doodle/pkg/levelpack"
"git.kirsle.net/SketchyMaze/doodle/pkg/plus"
)
var Driver Pluggable
// Plugin
type Pluggable interface {
LoadFromEmbeddable(string, filesystem.Embeddable, bool) (*doodads.Doodad, error)
IsRegistered() bool
GetRegistration() (plus.Registration, error)
UploadLicenseFile(string) (plus.Registration, error)
IsLevelSigned(*level.Level) bool
IsLevelPackSigned(*levelpack.LevelPack) bool
}

View File

@ -1,24 +1,68 @@
//go:build dpp //go:build dpp
// +build dpp // +build dpp
package plus package dpp
import ( import (
"encoding/json"
"git.kirsle.net/SketchyMaze/doodle/pkg/doodads" "git.kirsle.net/SketchyMaze/doodle/pkg/doodads"
"git.kirsle.net/SketchyMaze/doodle/pkg/filesystem" "git.kirsle.net/SketchyMaze/doodle/pkg/filesystem"
"git.kirsle.net/SketchyMaze/doodle/pkg/level"
"git.kirsle.net/SketchyMaze/doodle/pkg/levelpack"
"git.kirsle.net/SketchyMaze/doodle/pkg/plus"
"git.kirsle.net/SketchyMaze/dpp/embedding" "git.kirsle.net/SketchyMaze/dpp/embedding"
"git.kirsle.net/SketchyMaze/dpp/license" "git.kirsle.net/SketchyMaze/dpp/license"
"git.kirsle.net/SketchyMaze/dpp/license/levelsigning"
) )
func DoodadFromEmbeddable(filename string, fs filesystem.Embeddable, force bool) (*doodads.Doodad, error) { type Plugin struct{}
func (Plugin) LoadFromEmbeddable(filename string, fs filesystem.Embeddable, force bool) (*doodads.Doodad, error) {
return embedding.LoadFromEmbeddable(filename, fs, force) return embedding.LoadFromEmbeddable(filename, fs, force)
} }
func IsRegistered() bool { func (Plugin) IsRegistered() bool {
return license.IsRegistered() return license.IsRegistered()
} }
func GetRegistration() (*Registration, error) { func (Plugin) GetRegistration() (plus.Registration, error) {
reg, err := license.GetRegistration() reg, err := license.GetRegistration()
return reg.(*Registration), err if err != nil {
return plus.Registration{}, err
}
return translateLicenseStruct(reg)
}
func (Plugin) UploadLicenseFile(filename string) (plus.Registration, error) {
reg, err := license.UploadLicenseFile(filename)
if err != nil {
return plus.Registration{}, err
}
return translateLicenseStruct(reg)
}
// Hack: to translate JWT token types, easiest is to just encode/decode them (inner jwt.StandardClaims complexity).
func translateLicenseStruct(reg license.Registration) (plus.Registration, error) {
jsonStr, err := json.Marshal(reg)
if err != nil {
return plus.Registration{}, err
}
var result plus.Registration
err = json.Unmarshal(jsonStr, &result)
return result, err
}
func (Plugin) IsLevelPackSigned(lp *levelpack.LevelPack) bool {
return levelsigning.IsLevelPackSigned(lp)
}
func (Plugin) IsLevelSigned(lvl *level.Level) bool {
return levelsigning.IsLevelSigned(lvl)
}
func init() {
Driver = Plugin{}
} }

46
pkg/plus/dpp/plus_foss.go Normal file
View File

@ -0,0 +1,46 @@
//go:build !dpp
// +build !dpp
package dpp
import (
"errors"
"git.kirsle.net/SketchyMaze/doodle/pkg/doodads"
"git.kirsle.net/SketchyMaze/doodle/pkg/filesystem"
"git.kirsle.net/SketchyMaze/doodle/pkg/level"
"git.kirsle.net/SketchyMaze/doodle/pkg/levelpack"
"git.kirsle.net/SketchyMaze/doodle/pkg/plus"
)
var ErrNotImplemented = errors.New("not implemented")
type Plugin struct{}
func (Plugin) LoadFromEmbeddable(filename string, fs filesystem.Embeddable, force bool) (*doodads.Doodad, error) {
return doodads.LoadFile(filename)
}
func (Plugin) IsRegistered() bool {
return false
}
func (Plugin) GetRegistration() (plus.Registration, error) {
return plus.Registration{}, ErrNotImplemented
}
func (Plugin) UploadLicenseFile(string) (plus.Registration, error) {
return plus.Registration{}, ErrNotImplemented
}
func (Plugin) IsLevelPackSigned(*levelpack.LevelPack) bool {
return false
}
func (Plugin) IsLevelSigned(*level.Level) bool {
return false
}
func init() {
Driver = Plugin{}
}

View File

@ -1,22 +0,0 @@
//go:build !dpp
// +build !dpp
package plus
import (
"git.kirsle.net/SketchyMaze/doodle/pkg/doodads"
"git.kirsle.net/SketchyMaze/doodle/pkg/filesystem"
)
// DoodadFromEmbeddable may load a doodad from an embedding filesystem, such as a Level or LevelPack.
func DoodadFromEmbeddable(filename string, fs filesystem.Embeddable, force bool) (*doodads.Doodad, error) {
return doodads.LoadFile(filename)
}
func IsRegistered() bool {
return false
}
func GetRegistration() (*Registration, error) {
return nil, ErrNotImplemented
}

View File

@ -1,24 +0,0 @@
//go:build dpp
// +build dpp
package plus
import (
"git.kirsle.net/SketchyMaze/doodle/pkg/doodads"
"git.kirsle.net/SketchyMaze/doodle/pkg/filesystem"
"git.kirsle.net/SketchyMaze/dpp/embedding"
"git.kirsle.net/SketchyMaze/dpp/license"
)
func DoodadFromEmbeddable(filename string, fs filesystem.Embeddable, force bool) (*doodads.Doodad, error) {
return embedding.LoadFromEmbeddable(filename, fs, force)
}
func IsRegistered() bool {
return license.IsRegistered()
}
func GetRegistration() (*Registration, error) {
reg, err := license.GetRegistration()
return reg.(*Registration), err
}

View File

@ -1,22 +0,0 @@
//go:build !dpp
// +build !dpp
package plus
import (
"git.kirsle.net/SketchyMaze/doodle/pkg/doodads"
"git.kirsle.net/SketchyMaze/doodle/pkg/filesystem"
)
// DoodadFromEmbeddable may load a doodad from an embedding filesystem, such as a Level or LevelPack.
func DoodadFromEmbeddable(filename string, fs filesystem.Embeddable, force bool) (*doodads.Doodad, error) {
return doodads.LoadFile(filename)
}
func IsRegistered() bool {
return false
}
func GetRegistration() (*Registration, error) {
return nil, ErrNotImplemented
}

View File

@ -1 +0,0 @@
package initdpp

View File

@ -4,16 +4,14 @@ package plus
import ( import (
"errors" "errors"
"git.kirsle.net/SketchyMaze/doodle/pkg/doodads"
"git.kirsle.net/SketchyMaze/doodle/pkg/filesystem"
"github.com/dgrijalva/jwt-go" "github.com/dgrijalva/jwt-go"
) )
var ErrNotImplemented = errors.New("not implemented") // Errors
var (
type Bridge interface { ErrNotImplemented = errors.New("not implemented")
DoodadFromEmbeddable(filename string, fs filesystem.Embeddable, force bool) (*doodads.Doodad, error) ErrRegisteredFeature = errors.New("feature not available")
} )
// Registration object encoded into a license key file. // Registration object encoded into a license key file.
type Registration struct { type Registration struct {

View File

@ -7,9 +7,8 @@ import (
"strings" "strings"
"git.kirsle.net/SketchyMaze/doodle/pkg/level" "git.kirsle.net/SketchyMaze/doodle/pkg/level"
"git.kirsle.net/SketchyMaze/doodle/pkg/license/levelsigning"
"git.kirsle.net/SketchyMaze/doodle/pkg/log" "git.kirsle.net/SketchyMaze/doodle/pkg/log"
"git.kirsle.net/SketchyMaze/doodle/pkg/plus" "git.kirsle.net/SketchyMaze/doodle/pkg/plus/dpp"
"git.kirsle.net/SketchyMaze/doodle/pkg/scripting" "git.kirsle.net/SketchyMaze/doodle/pkg/scripting"
"git.kirsle.net/SketchyMaze/doodle/pkg/scripting/exceptions" "git.kirsle.net/SketchyMaze/doodle/pkg/scripting/exceptions"
"git.kirsle.net/go/render" "git.kirsle.net/go/render"
@ -37,18 +36,18 @@ func (w *Canvas) InstallActors(actors level.ActorMap) error {
// Signed Levels: the free version normally won't load embedded assets from // Signed Levels: the free version normally won't load embedded assets from
// a level and the call to LoadFromEmbeddable below returns the error. If the // a level and the call to LoadFromEmbeddable below returns the error. If the
// level is signed it is allowed to use its embedded assets. // level is signed it is allowed to use its embedded assets.
isSigned := w.IsSignedLevelPack != nil || levelsigning.IsLevelSigned(w.level) isSigned := w.IsSignedLevelPack != nil || dpp.Driver.IsLevelSigned(w.level)
w.actors = make([]*Actor, 0) w.actors = make([]*Actor, 0)
for _, id := range actorIDs { for _, id := range actorIDs {
var actor = actors[id] var actor = actors[id]
// Try loading the doodad from the level's own attached files. // Try loading the doodad from the level's own attached files.
doodad, err := plus.DoodadFromEmbeddable(actor.Filename, w.level, isSigned) doodad, err := dpp.Driver.LoadFromEmbeddable(actor.Filename, w.level, isSigned)
if err != nil { if err != nil {
// If we have a signed levelpack, try loading from the levelpack. // If we have a signed levelpack, try loading from the levelpack.
if w.IsSignedLevelPack != nil { if w.IsSignedLevelPack != nil {
if found, err := plus.DoodadFromEmbeddable(actor.Filename, w.IsSignedLevelPack, true); err == nil { if found, err := dpp.Driver.LoadFromEmbeddable(actor.Filename, w.IsSignedLevelPack, true); err == nil {
doodad = found doodad = found
} }
} }

View File

@ -7,10 +7,11 @@ import (
"git.kirsle.net/SketchyMaze/doodle/pkg/balance" "git.kirsle.net/SketchyMaze/doodle/pkg/balance"
"git.kirsle.net/SketchyMaze/doodle/pkg/branding" "git.kirsle.net/SketchyMaze/doodle/pkg/branding"
"git.kirsle.net/SketchyMaze/doodle/pkg/branding/builds" "git.kirsle.net/SketchyMaze/doodle/pkg/branding/builds"
"git.kirsle.net/SketchyMaze/doodle/pkg/license"
"git.kirsle.net/SketchyMaze/doodle/pkg/log" "git.kirsle.net/SketchyMaze/doodle/pkg/log"
"git.kirsle.net/SketchyMaze/doodle/pkg/modal" "git.kirsle.net/SketchyMaze/doodle/pkg/modal"
"git.kirsle.net/SketchyMaze/doodle/pkg/native" "git.kirsle.net/SketchyMaze/doodle/pkg/native"
"git.kirsle.net/SketchyMaze/doodle/pkg/plus"
"git.kirsle.net/SketchyMaze/doodle/pkg/plus/dpp"
"git.kirsle.net/go/render" "git.kirsle.net/go/render"
"git.kirsle.net/go/ui" "git.kirsle.net/go/ui"
"git.kirsle.net/go/ui/style" "git.kirsle.net/go/ui/style"
@ -51,12 +52,12 @@ func NewLicenseWindow(cfg License) *ui.Window {
labelSize = render.NewRect(100, 16) labelSize = render.NewRect(100, 16)
valueSize = render.NewRect(windowWidth-labelSize.W-4, labelSize.H) valueSize = render.NewRect(windowWidth-labelSize.W-4, labelSize.H)
isRegistered bool isRegistered bool
registration license.Registration registration plus.Registration
summary = "Unregistered" + builds.VersionSuffix summary = "Unregistered" + builds.VersionSuffix
) )
// Get our current registration status. // Get our current registration status.
if reg, err := license.GetRegistration(); err == nil { if reg, err := dpp.Driver.GetRegistration(); err == nil {
isRegistered = true isRegistered = true
registration = reg registration = reg
windowHeight = 200 windowHeight = 200
@ -141,7 +142,7 @@ func NewLicenseWindow(cfg License) *ui.Window {
} }
// Upload and validate the license key. // Upload and validate the license key.
reg, err := license.UploadLicenseFile(filename) reg, err := dpp.Driver.UploadLicenseFile(filename)
if err != nil { if err != nil {
modal.Alert("That license key didn't seem quite right.").WithTitle("License Error") modal.Alert("That license key didn't seem quite right.").WithTitle("License Error")
return return