10 Commits
404 changed files with 927 additions and 29762 deletions
-4
View File
@@ -37,10 +37,6 @@ jobs:
- run: go vet ./platform/sdl - run: go vet ./platform/sdl
- run: make lint - run: make lint
- run: make depcheck - run: make depcheck
- name: packaging tools
run: sudo apt-get install -y nsis squashfs-tools
- name: installer dry run
run: make nsis-check
build: build:
strategy: strategy:
+12 -77
View File
File diff suppressed because it is too large Load Diff
+3 -17
View File
@@ -14,7 +14,7 @@ BENCH_COUNT ?= 10
BENCH_CPU ?= 2 BENCH_CPU ?= 2
BENCH_PIN = $(shell command -v taskset >/dev/null && echo taskset -c $(BENCH_CPU)) BENCH_PIN = $(shell command -v taskset >/dev/null && echo taskset -c $(BENCH_CPU))
EDITOR_VERSION ?= 0.1.0 EDITOR_VERSION ?= 0.1.0
EDITOR_ICON ?= app/brand/png EDITOR_ICON ?= third_party/brand/aego-1024.png
EXPORT_SMOKE = $(CURDIR)/.cache/export-smoke EXPORT_SMOKE = $(CURDIR)/.cache/export-smoke
EXPORT_HOME = $(CURDIR)/.cache/export-home EXPORT_HOME = $(CURDIR)/.cache/export-home
CHROMIUM ?= $(shell command -v chromium || command -v chromium-browser || command -v google-chrome) CHROMIUM ?= $(shell command -v chromium || command -v chromium-browser || command -v google-chrome)
@@ -26,7 +26,6 @@ WEB_DEMO_BUDGET = @size=$$(stat -c %s site/demo/game.wasm.gz); echo "demo game.w
if [ $$size -gt $(WASM_BUDGET) ]; then echo "the web demo is over the 8 MB gzip budget"; exit 1; fi if [ $$size -gt $(WASM_BUDGET) ]; then echo "the web demo is over the 8 MB gzip budget"; exit 1; fi
TRY_BUDGET = 10485760 TRY_BUDGET = 10485760
WEB_TRY = cd tools/websmoke && CHROMIUM=$(CHROMIUM) node try.mjs --site=$(CURDIR)/site WEB_TRY = cd tools/websmoke && CHROMIUM=$(CHROMIUM) node try.mjs --site=$(CURDIR)/site
WEB_AUDIO = cd tools/websmoke && CHROMIUM=$(CHROMIUM) node audio.mjs --site=$(CURDIR)/site
TRY_SIZE_CHECK = gzip -9 -k -f site/try/aego-docs.wasm; size=$$(stat -c %s site/try/aego-docs.wasm.gz); echo "aego-docs.wasm.gz: $$size bytes"; \ TRY_SIZE_CHECK = gzip -9 -k -f site/try/aego-docs.wasm; size=$$(stat -c %s site/try/aego-docs.wasm.gz); echo "aego-docs.wasm.gz: $$size bytes"; \
if [ $$size -gt $(TRY_BUDGET) ]; then echo "the docs runtime is over the 10 MB gzip budget, see make try-size"; exit 1; fi if [ $$size -gt $(TRY_BUDGET) ]; then echo "the docs runtime is over the 10 MB gzip budget, see make try-size"; exit 1; fi
# Module targets, appended by modules/*/module.mk. # Module targets, appended by modules/*/module.mk.
@@ -39,7 +38,7 @@ BENCH_PHYSICS_PKGS :=
.DEFAULT_GOAL := bootstrap .DEFAULT_GOAL := bootstrap
-include modules/*/module.mk -include modules/*/module.mk
.PHONY: dmg nsis-check appimage bootstrap build test test-nonative test-editor test-runtime test-gl vet lint depcheck smoke run genfont genicons icons icons-doc res genpreviews golden golden-update site-headless bench bench-baseline bench-scripts bench-build bench-compare bench-profile bench-scripts-run bench-allocs playground playground-size site site-check cli example example-platformer check-all ci clean fuzz runtime export-smoke editor-app shaders test-wasm web-smoke web-smoke-update try-size shots shots-check .PHONY: bootstrap build test test-nonative test-editor test-runtime test-gl vet lint depcheck smoke run genfont genicons icons icons-doc res genpreviews golden golden-update site-headless bench bench-baseline bench-scripts bench-build bench-compare bench-profile bench-scripts-run bench-allocs playground playground-size site site-check cli example example-platformer check-all ci clean fuzz runtime export-smoke editor-app shaders test-wasm web-smoke web-smoke-update try-size shots shots-check
XVFB := $(shell command -v xvfb-run 2>/dev/null) XVFB := $(shell command -v xvfb-run 2>/dev/null)
GL_OVERRIDE = MESA_GL_VERSION_OVERRIDE=3.3 MESA_GLSL_VERSION_OVERRIDE=330 GL_OVERRIDE = MESA_GL_VERSION_OVERRIDE=3.3 MESA_GLSL_VERSION_OVERRIDE=330
@@ -50,7 +49,7 @@ GL_ENV = env SDL_VIDEODRIVER=offscreen LIBGL_ALWAYS_SOFTWARE=1 GALLIUM_DRIVER=ll
endif endif
NONATIVE_PKGS = $$(go list ./... | grep -v -e '/platform/sdl$$' -e '/gpu/gl33$$' -e '/gpu/gl33/gl$$') NONATIVE_PKGS = $$(go list ./... | grep -v -e '/platform/sdl$$' -e '/gpu/gl33$$' -e '/gpu/gl33/gl$$')
LINT_PKGS = $$(go list ./... | grep -v -e '/gpu/gl33/gl$$' -e '/audio/codec/vorbis/internal/') LINT_PKGS = $$(go list ./... | grep -v '/gpu/gl33/gl$$')
bootstrap: $(STAMP) bootstrap: $(STAMP)
@@ -247,7 +246,6 @@ web-smoke: site
$(WEB_SMOKE) --report=$(CURDIR)/.cache/web-bench.json $(WEB_SMOKE) --report=$(CURDIR)/.cache/web-bench.json
$(WEB_DEMO) $(WEB_DEMO)
$(WEB_TRY) $(WEB_TRY)
$(WEB_AUDIO)
web-smoke-update: site web-smoke-update: site
$(WEB_SMOKE) --update $(WEB_SMOKE) --update
@@ -283,8 +281,6 @@ fuzz:
go test -run '^$$' -fuzz '^FuzzParse$$' -fuzztime $(FUZZTIME) ./script/parser go test -run '^$$' -fuzz '^FuzzParse$$' -fuzztime $(FUZZTIME) ./script/parser
go test -run '^$$' -fuzz '^FuzzDecodeVerify$$' -fuzztime $(FUZZTIME) ./script/verify go test -run '^$$' -fuzz '^FuzzDecodeVerify$$' -fuzztime $(FUZZTIME) ./script/verify
go test -run '^$$' -fuzz '^FuzzDecodeVerifyV3$$' -fuzztime $(FUZZTIME) ./script/verify go test -run '^$$' -fuzz '^FuzzDecodeVerifyV3$$' -fuzztime $(FUZZTIME) ./script/verify
go test -run '^$$' -fuzz '^FuzzWAV$$' -fuzztime $(FUZZTIME) ./audio/codec
go test -run '^$$' -fuzz '^FuzzVorbis$$' -fuzztime $(FUZZTIME) ./audio/codec
ci: build vet lint depcheck test test-nonative test-editor test-runtime test-wasm runtime smoke fuzz golden shots-check test-gl cli playground web-smoke site-check example example-platformer check-all export-smoke $(MODULE_CI) bench-allocs ci: build vet lint depcheck test test-nonative test-editor test-runtime test-wasm runtime smoke fuzz golden shots-check test-gl cli playground web-smoke site-check example example-platformer check-all export-smoke $(MODULE_CI) bench-allocs
@@ -325,15 +321,5 @@ editor-app: bootstrap
go build -o .cache/bin/aego-editor ./cmd/aego-editor go build -o .cache/bin/aego-editor ./cmd/aego-editor
go run ./tools/appbundle -bin .cache/bin/aego-editor -out .cache -version $(EDITOR_VERSION) $(if $(wildcard $(EDITOR_ICON)),-icon $(EDITOR_ICON)) go run ./tools/appbundle -bin .cache/bin/aego-editor -out .cache -version $(EDITOR_VERSION) $(if $(wildcard $(EDITOR_ICON)),-icon $(EDITOR_ICON))
dmg: editor-app
tools/release/dmg.sh ".cache/Aego Editor.app" .cache/dist/Aego-$$(sed -n 's/^const Version = "\(.*\)"$$/\1/p' engine/config.go).dmg
nsis-check:
sh tools/release/nsis-check.sh
appimage: cli
mkdir -p .cache/stage/bin .cache/dist && cp .cache/bin/aego .cache/stage/bin/aego && printf 'dev\n' > .cache/stage/VERSION && cp tools/release/README.txt .cache/stage/
sh tools/release/appimage.sh .cache/stage .cache/dist/Aego-dev-x86_64.AppImage
clean: clean:
rm -rf .cache/build rm -rf .cache/build
-1
View File
@@ -90,7 +90,6 @@ func (s *Session) lookupType(name string) (*schema.TypeDescriptor, error) {
found = append(found, td) found = append(found, td)
} }
} }
found = schema.PreferProject(found)
switch len(found) { switch len(found) {
case 1: case 1:
return found[0], nil return found[0], nil
+1 -6
View File
@@ -10,7 +10,6 @@ import (
"aego/modules/dataasset" "aego/modules/dataasset"
"aego/modules/debug" "aego/modules/debug"
"aego/modules/display" "aego/modules/display"
"aego/modules/gameplay"
inputmod "aego/modules/input" inputmod "aego/modules/input"
"aego/modules/physics" "aego/modules/physics"
"aego/modules/render2d" "aego/modules/render2d"
@@ -77,10 +76,6 @@ func cameraEntry() assembly.Entry {
return assembly.Entry{ID: camera.ID, Requires: []string{scripting.ID}, New: func(assembly.Options) module.Module { return camera.New() }} return assembly.Entry{ID: camera.ID, Requires: []string{scripting.ID}, New: func(assembly.Options) module.Module { return camera.New() }}
} }
func gameplayEntry() assembly.Entry {
return assembly.Entry{ID: gameplay.ID, Requires: []string{physics.ID, scripting.ID}, New: func(assembly.Options) module.Module { return gameplay.New() }}
}
func dataEntry() assembly.Entry { func dataEntry() assembly.Entry {
return assembly.Entry{ID: dataasset.ID, New: func(assembly.Options) module.Module { return dataasset.New() }} return assembly.Entry{ID: dataasset.ID, New: func(assembly.Options) module.Module { return dataasset.New() }}
} }
@@ -95,5 +90,5 @@ func savegameEntry() assembly.Entry {
func Default() assembly.Catalog { func Default() assembly.Catalog {
return assembly.Catalog{core(), dataEntry(), inputEntry(), render2dEntry(), render3dEntry(), scriptEntry(), physicsEntry(), debugEntry(), return assembly.Catalog{core(), dataEntry(), inputEntry(), render2dEntry(), render3dEntry(), scriptEntry(), physicsEntry(), debugEntry(),
displayEntry(), audioEntry(), accessibilityEntry(), settingsEntry(), tweenEntry(), cameraEntry(), gameplayEntry(), spawnEntry(), savegameEntry()} displayEntry(), audioEntry(), accessibilityEntry(), settingsEntry(), tweenEntry(), cameraEntry(), spawnEntry(), savegameEntry()}
} }
-6
View File
@@ -2,14 +2,10 @@ package editors
import ( import (
"aego/app/assembly" "aego/app/assembly"
"aego/modules/audio"
audioeditor "aego/modules/audio/editor"
"aego/modules/camera" "aego/modules/camera"
cameraeditor "aego/modules/camera/editor" cameraeditor "aego/modules/camera/editor"
"aego/modules/debug" "aego/modules/debug"
debugeditor "aego/modules/debug/editor" debugeditor "aego/modules/debug/editor"
"aego/modules/gameplay"
gameplayeditor "aego/modules/gameplay/editor"
inputmod "aego/modules/input" inputmod "aego/modules/input"
inputeditor "aego/modules/input/editor" inputeditor "aego/modules/input/editor"
"aego/modules/physics" "aego/modules/physics"
@@ -27,7 +23,5 @@ func With(c assembly.Catalog) assembly.Catalog {
With(render3d.ID, render3deditor.Hook). With(render3d.ID, render3deditor.Hook).
With(physics.ID, physicseditor.Hook). With(physics.ID, physicseditor.Hook).
With(camera.ID, cameraeditor.Hook). With(camera.ID, cameraeditor.Hook).
With(gameplay.ID, gameplayeditor.Hook).
With(audio.ID, audioeditor.Hook).
With(debug.ID, debugeditor.Hook) With(debug.ID, debugeditor.Hook)
} }
-8
View File
@@ -4,17 +4,13 @@ import (
"aego/app/assembly" "aego/app/assembly"
"aego/engine/base" "aego/engine/base"
"aego/engine/module" "aego/engine/module"
"aego/modules/audio"
"aego/modules/camera" "aego/modules/camera"
"aego/modules/debug" "aego/modules/debug"
"aego/modules/gameplay"
inputmod "aego/modules/input" inputmod "aego/modules/input"
"aego/modules/physics" "aego/modules/physics"
"aego/modules/render2d" "aego/modules/render2d"
"aego/modules/render3d" "aego/modules/render3d"
"aego/modules/savegame"
"aego/modules/scripting" "aego/modules/scripting"
"aego/modules/spawn"
"aego/modules/tween" "aego/modules/tween"
"aego/script/stdlib" "aego/script/stdlib"
"aego/script/vm" "aego/script/vm"
@@ -32,11 +28,7 @@ func Catalog() assembly.Catalog {
{ID: debug.ID, New: func(assembly.Options) module.Module { return debug.New() }}, {ID: debug.ID, New: func(assembly.Options) module.Module { return debug.New() }},
{ID: tween.ID, Requires: []string{scripting.ID}, New: func(assembly.Options) module.Module { return tween.New() }}, {ID: tween.ID, Requires: []string{scripting.ID}, New: func(assembly.Options) module.Module { return tween.New() }},
{ID: camera.ID, Requires: []string{scripting.ID}, New: func(assembly.Options) module.Module { return camera.New() }}, {ID: camera.ID, Requires: []string{scripting.ID}, New: func(assembly.Options) module.Module { return camera.New() }},
{ID: gameplay.ID, Requires: []string{physics.ID, scripting.ID}, New: func(assembly.Options) module.Module { return gameplay.New() }},
{ID: render3d.ID, New: func(assembly.Options) module.Module { return render3d.New() }}, {ID: render3d.ID, New: func(assembly.Options) module.Module { return render3d.New() }},
{ID: spawn.ID, New: func(assembly.Options) module.Module { return spawn.New() }},
{ID: savegame.ID, Requires: []string{scripting.ID, spawn.ID}, New: func(assembly.Options) module.Module { return savegame.New() }},
{ID: audio.ID, New: func(assembly.Options) module.Module { return audio.New() }},
} }
} }
-61
View File
@@ -1,61 +0,0 @@
package playground
import (
"io/fs"
"path"
"sort"
"strings"
"time"
"aego/contracts/persistence"
"aego/engine"
"aego/platform"
"aego/save"
)
// UseMemorySaves gives e a save store kept in memory, for runs in a browser page that must not touch the visitor's storage.
func UseMemorySaves(e *engine.Engine) {
e.SetService(persistence.StoreID, save.NewStoreFS("saves", &memUser{files: map[string][]byte{}}))
}
type memUser struct {
files map[string][]byte
}
func (m *memUser) ReadFile(p string) ([]byte, error) {
data, ok := m.files[path.Clean(p)]
if !ok {
return nil, fs.ErrNotExist
}
return append([]byte(nil), data...), nil
}
func (m *memUser) WriteFile(p string, data []byte) error {
m.files[path.Clean(p)] = append([]byte(nil), data...)
return nil
}
func (m *memUser) Remove(p string) error {
delete(m.files, path.Clean(p))
return nil
}
func (m *memUser) Stat(p string) (platform.UserEntry, error) {
data, ok := m.files[path.Clean(p)]
if !ok {
return platform.UserEntry{}, fs.ErrNotExist
}
return platform.UserEntry{Name: path.Base(p), Size: int64(len(data)), Mod: time.Time{}}, nil
}
func (m *memUser) List(dir string) ([]platform.UserEntry, error) {
prefix := path.Clean(dir) + "/"
var out []platform.UserEntry
for p, data := range m.files {
if rest, ok := strings.CutPrefix(p, prefix); ok && !strings.Contains(rest, "/") {
out = append(out, platform.UserEntry{Name: rest, Size: int64(len(data))})
}
}
sort.Slice(out, func(i, j int) bool { return out[i].Name < out[j].Name })
return out, nil
}
-62
View File
@@ -1,62 +0,0 @@
package playground
import (
"encoding/base64"
"strings"
"aego/asset"
"aego/asset/loader"
"aego/core/ids"
"aego/script/bytecode"
"aego/vfs"
"aego/vfs/memfs"
)
// EncodeTry packs the compiled script of a try scene for a docs page: base64 modules joined by commas.
func EncodeTry(mods []*bytecode.Module) string {
parts := make([]string, len(mods))
for i, m := range mods {
parts[i] = base64.StdEncoding.EncodeToString(bytecode.Encode(m))
}
return strings.Join(parts, ",")
}
func DecodeTry(code string) ([]*bytecode.Module, error) {
if code == "" {
return nil, nil
}
var mods []*bytecode.Module
for _, part := range strings.Split(code, ",") {
b, err := base64.StdEncoding.DecodeString(part)
if err != nil {
return nil, err
}
m, err := bytecode.Decode(b)
if err != nil {
return nil, err
}
mods = append(mods, m)
}
return mods, nil
}
// MountTry gives the loader the prefabs of a try scene, keyed by asset id; none unmounts them.
func MountTry(l *loader.Loader, prefabs map[string]string) error {
idx := asset.NewIndex()
files := map[string][]byte{}
for key, text := range prefabs {
id, err := ids.ParseAssetID(key)
if err != nil {
return err
}
p := id.String() + ".aeprefab"
files[p] = []byte(text)
idx.Put(asset.Entry{ID: id, Kind: asset.ArtPrefab, Name: p, Source: p,
Artifacts: []asset.Artifact{{Kind: asset.ArtPrefab, Path: "try://" + p}}})
}
fs, err := vfs.New(vfs.Mount{Scheme: "try", ReadOnly: true, Source: memfs.New(files)})
if err != nil {
return err
}
return l.Mount(idx, fs)
}
-2
View File
@@ -9,7 +9,6 @@ import (
"sort" "sort"
"strings" "strings"
"aego/app/proc"
"aego/core/errs" "aego/core/errs"
"aego/core/log" "aego/core/log"
"aego/project" "aego/project"
@@ -170,7 +169,6 @@ func Build(p *project.Project, t Target, mode Mode, engineVersion string, lg *lo
cmd := exec.Command("go", args...) cmd := exec.Command("go", args...)
cmd.Dir = p.Root cmd.Dir = p.Root
cmd.Env = append(os.Environ(), "GOOS="+t.OS, "GOARCH="+t.Arch) cmd.Env = append(os.Environ(), "GOOS="+t.OS, "GOARCH="+t.Arch)
proc.Hide(cmd)
output, err := cmd.CombinedOutput() output, err := cmd.CombinedOutput()
if err != nil { if err != nil {
os.RemoveAll(outDir) os.RemoveAll(outDir)
-3
View File
@@ -8,7 +8,6 @@ import (
"path/filepath" "path/filepath"
"strings" "strings"
"aego/app/proc"
"aego/core/errs" "aego/core/errs"
"aego/core/log" "aego/core/log"
"aego/project" "aego/project"
@@ -33,14 +32,12 @@ func RunIcons(p *project.Project, engineVersion string, out io.Writer) (int, err
defer os.Remove(bin) defer os.Remove(bin)
build := exec.Command("go", "build", "-tags", strings.Join(t.Tags, ","), "-o", bin, "./.aego/generated/icons") build := exec.Command("go", "build", "-tags", strings.Join(t.Tags, ","), "-o", bin, "./.aego/generated/icons")
build.Dir = p.Root build.Dir = p.Root
proc.Hide(build)
if output, err := build.CombinedOutput(); err != nil { if output, err := build.CombinedOutput(); err != nil {
return 2, errs.New(errs.BuildFailed, "native icons helper does not compile", return 2, errs.New(errs.BuildFailed, "native icons helper does not compile",
log.F("output", strings.TrimSpace(string(output)))) log.F("output", strings.TrimSpace(string(output))))
} }
run := exec.Command(bin) run := exec.Command(bin)
run.Dir, run.Stdout, run.Stderr = p.Root, out, out run.Dir, run.Stdout, run.Stderr = p.Root, out, out
proc.Hide(run)
err = run.Run() err = run.Run()
var ee *exec.ExitError var ee *exec.ExitError
if errors.As(err, &ee) { if errors.As(err, &ee) {
-3
View File
@@ -6,7 +6,6 @@ import (
"path/filepath" "path/filepath"
"strings" "strings"
"aego/app/proc"
"aego/core/errs" "aego/core/errs"
"aego/core/log" "aego/core/log"
"aego/project" "aego/project"
@@ -53,7 +52,6 @@ func BuildManifest(p *project.Project, engineVersion string, lg *log.Logger) (st
defer os.Remove(bin) defer os.Remove(bin)
build := exec.Command("go", "build", "-tags", strings.Join(t.Tags, ","), "-o", bin, "./.aego/generated/manifest") build := exec.Command("go", "build", "-tags", strings.Join(t.Tags, ","), "-o", bin, "./.aego/generated/manifest")
build.Dir = p.Root build.Dir = p.Root
proc.Hide(build)
if output, err := build.CombinedOutput(); err != nil { if output, err := build.CombinedOutput(); err != nil {
return "", errs.New(errs.BuildFailed, "native bindings helper does not compile", return "", errs.New(errs.BuildFailed, "native bindings helper does not compile",
log.F("output", strings.TrimSpace(string(output)))) log.F("output", strings.TrimSpace(string(output))))
@@ -61,7 +59,6 @@ func BuildManifest(p *project.Project, engineVersion string, lg *log.Logger) (st
tmp := out + ".tmp" tmp := out + ".tmp"
run := exec.Command(bin, tmp) run := exec.Command(bin, tmp)
run.Dir = p.Root run.Dir = p.Root
proc.Hide(run)
if output, err := run.CombinedOutput(); err != nil { if output, err := run.CombinedOutput(); err != nil {
os.Remove(tmp) os.Remove(tmp)
return "", errs.New(errs.BuildFailed, "native module Register failed", return "", errs.New(errs.BuildFailed, "native module Register failed",
-33
View File
@@ -1,33 +0,0 @@
package brand
import (
"bytes"
"embed"
"image"
"image/png"
"strconv"
)
//go:embed png/aego-*.png
var files embed.FS
var windowSizes = []int{16, 24, 32, 48, 64, 128, 256}
func PNG(n int) ([]byte, bool) {
data, err := files.ReadFile("png/aego-" + strconv.Itoa(n) + ".png")
return data, err == nil
}
func Window() []image.Image {
out := make([]image.Image, 0, len(windowSizes))
for _, n := range windowSizes {
data, ok := PNG(n)
if !ok {
continue
}
if img, err := png.Decode(bytes.NewReader(data)); err == nil {
out = append(out, img)
}
}
return out
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 563 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 878 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

+4 -8
View File
@@ -21,8 +21,7 @@ import (
"aego/script/workspace" "aego/script/workspace"
) )
// build assembles the registry; with pg it also compiles the diagnostics examples and the try scripts. func build(p *project.Project, mods []module.Module, diagnose func(string, *docs.DiagInfo)) (*docs.Registry, *workspace.Workspace, error) {
func build(p *project.Project, mods []module.Module, pg *playground.Playground) (*docs.Registry, *workspace.Workspace, error) {
types, err := assembly.NewTypes() types, err := assembly.NewTypes()
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
@@ -43,10 +42,7 @@ func build(p *project.Project, mods []module.Module, pg *playground.Playground)
return nil, nil, err return nil, nil, err
} }
src := docs.SourcesOf(bm, types.Schema(), man) src := docs.SourcesOf(bm, types.Schema(), man)
if pg != nil { src.Diagnose = diagnose
src.Diagnose = diagnoser(pg)
src.CompileTry = pg.TryCode
}
var ws *workspace.Workspace var ws *workspace.Workspace
if p != nil { if p != nil {
ws, err = workspace.Open(workspace.Config{Root: p.Root, Module: p.Module, Scripts: p.ScriptsDir(), Bindings: reg.Table(), Docs: bm}) ws, err = workspace.Open(workspace.Config{Root: p.Root, Module: p.Module, Scripts: p.ScriptsDir(), Bindings: reg.Table(), Docs: bm})
@@ -71,13 +67,13 @@ func Registry(p *project.Project, mods []module.Module) (*docs.Registry, error)
return r, err return r, err
} }
// ExportRegistry is Registry with the diagnostics examples compiled for their messages and positions, and the try scripts compiled. // ExportRegistry is Registry with the diagnostics examples compiled for their messages and positions.
func ExportRegistry(p *project.Project, mods []module.Module) (*docs.Registry, error) { func ExportRegistry(p *project.Project, mods []module.Module) (*docs.Registry, error) {
pg, err := playground.New() pg, err := playground.New()
if err != nil { if err != nil {
return nil, err return nil, err
} }
r, _, err := build(p, mods, pg) r, _, err := build(p, mods, diagnoser(pg))
return r, err return r, err
} }
+1 -8
View File
@@ -41,16 +41,9 @@ func CheckTry(reg *docs.Registry, w io.Writer) int {
} }
msgs = append(msgs, msg) msgs = append(msgs, msg)
} }
var code string switch res := pg.PlayScene(e.ID, []byte(e.Try)); {
var err error
if e.TryScript != "" {
code, err = pg.TryCode(e.TryScript)
}
switch res := pg.PlayScene(e.ID, []byte(e.Try), code, e.TryPrefabs); {
case !sandbox[e.ID]: case !sandbox[e.ID]:
add("belongs to a module the docs runtime does not include") add("belongs to a module the docs runtime does not include")
case err != nil:
add("script does not compile: " + err.Error())
case !res.Started: case !res.Started:
add("does not load: " + res.Error) add("does not load: " + res.Error)
default: default:
+1 -4
View File
@@ -75,7 +75,6 @@ type App struct {
ui *core.Context ui *core.Context
clip *docsession.Clipboard clip *docsession.Clipboard
session *docsession.Session session *docsession.Session
scripts *scriptHost
insp *inspector.Panel insp *inspector.Panel
game *gameview.Panel game *gameview.Panel
list *draw.List list *draw.List
@@ -144,17 +143,15 @@ func New(opt Options) (*App, error) {
return nil, err return nil, err
} }
a.e.SetService(loader.ServiceID, a.loader) a.e.SetService(loader.ServiceID, a.loader)
playmods.UseMemorySaves(a.e)
a.e.SetService(renderhost.ServiceID, a.renderer) a.e.SetService(renderhost.ServiceID, a.renderer)
if err := a.man.Init(&module.InitContext{Engine: a.e, Assets: a.loader, Log: a.log, Editor: true, Sections: sections}); err != nil { if err := a.man.Init(&module.InitContext{Engine: a.e, Assets: a.loader, Log: a.log, Editor: true, Sections: sections}); err != nil {
a.Close() a.Close()
return nil, err return nil, err
} }
a.initUI() a.initUI()
a.scripts = &scriptHost{reg: reg, types: a.types, man: a.man, log: a.log}
a.session = docsession.New(docsession.Options{ a.session = docsession.New(docsession.Options{
Engine: a.e, Renderer: a.renderer, Loader: a.loader, Types: a.types, Sections: sections, Engine: a.e, Renderer: a.renderer, Loader: a.loader, Types: a.types, Sections: sections,
Scripts: a.scripts, Scripts: &scriptHost{reg: reg, types: a.types, man: a.man, log: a.log},
UI: a.ui, UI: a.ui,
Clipboard: a.clip, Clipboard: a.clip,
Log: a.log, Log: a.log,
+2 -14
View File
@@ -3,7 +3,6 @@
package docsview package docsview
import ( import (
"encoding/json"
"strings" "strings"
"testing" "testing"
@@ -47,22 +46,11 @@ func errorsOf(a *App) []string {
func TestTryScenesRun(t *testing.T) { func TestTryScenesRun(t *testing.T) {
a := newHeadless(t) a := newHeadless(t)
p, err := playground.New()
if err != nil {
t.Fatal(err)
}
for _, e := range tries(t) { for _, e := range tries(t) {
var code string if err := a.session.Load([]byte(e.Try), e.TrySelect); err != nil {
if e.TryScript != "" {
if code, err = p.TryCode(e.TryScript); err != nil {
t.Fatalf("%s: %v", e.ID, err) t.Fatalf("%s: %v", e.ID, err)
} }
} if err := a.Step(60); err != nil {
req, _ := json.Marshal(map[string]any{"scene": e.Try, "select": e.TrySelect, "code": code, "prefabs": e.TryPrefabs})
if r := a.Call("load", req); r.Error != "" {
t.Fatalf("%s: %s", e.ID, r.Error)
}
if err := a.Step(400); err != nil {
t.Fatalf("%s: %v", e.ID, err) t.Fatalf("%s: %v", e.ID, err)
} }
st := a.session.State() st := a.session.State()
-12
View File
@@ -6,7 +6,6 @@ import (
"encoding/json" "encoding/json"
"strconv" "strconv"
playmods "aego/app/assembly/playground"
"aego/editor/core/docsession" "aego/editor/core/docsession"
"aego/scene/sceneio" "aego/scene/sceneio"
) )
@@ -14,8 +13,6 @@ import (
type request struct { type request struct {
Scene string `json:"scene"` Scene string `json:"scene"`
Select string `json:"select"` Select string `json:"select"`
Code string `json:"code"`
Prefabs map[string]string `json:"prefabs"`
Component string `json:"component"` Component string `json:"component"`
Field string `json:"field"` Field string `json:"field"`
Value float64 `json:"value"` Value float64 `json:"value"`
@@ -40,16 +37,7 @@ func (a *App) Call(method string, payload []byte) Reply {
var err error var err error
switch method { switch method {
case "load": case "load":
mods, derr := playmods.DecodeTry(req.Code)
if err = derr; err == nil {
err = a.scripts.use(mods)
}
if err == nil {
err = playmods.MountTry(a.loader, req.Prefabs)
}
if err == nil {
err = s.Load([]byte(req.Scene), req.Select) err = s.Load([]byte(req.Scene), req.Select)
}
case "reset": case "reset":
err = s.Reset() err = s.Reset()
case "text": case "text":
-9
View File
@@ -22,15 +22,6 @@ type scriptHost struct {
mods []*bytecode.Module mods []*bytecode.Module
} }
// use makes mods the scripts of the next scene and publishes their types, so the scene keeps their fields.
func (h *scriptHost) use(mods []*bytecode.Module) error {
if err := scriptruntime.Publish(h.types.Schema(), mods, h.reg.Surface()); err != nil {
return err
}
h.mods = mods
return nil
}
func (h *scriptHost) Errors() int { func (h *scriptHost) Errors() int {
return 0 return 0
} }
-27
View File
@@ -1,27 +0,0 @@
package edit
import (
"os"
"os/exec"
"runtime"
"strings"
"aego/engine"
"aego/platform"
)
func startBoot(verb string) {
wd, _ := os.Getwd()
exe, _ := os.Executable()
gobin, err := exec.LookPath("go")
if err != nil {
gobin = "not on PATH"
}
_ = platform.StartBoot(platform.DefaultBootPath(),
"aego "+engine.Version+" "+runtime.GOOS+"/"+runtime.GOARCH+" "+verb,
"exe "+exe,
"args "+strings.Join(os.Args[1:], " "),
"cwd "+wd,
"go "+gobin,
)
}
+48 -12
View File
File diff suppressed because it is too large Load Diff
-163
View File
File diff suppressed because it is too large Load Diff
-49
View File
@@ -1,19 +1,14 @@
package edit package edit
import ( import (
"net"
"net/http"
"os/exec" "os/exec"
"path/filepath"
"runtime" "runtime"
"sync"
"aego/app/bootstrap" "aego/app/bootstrap"
"aego/app/export" "aego/app/export"
"aego/app/projects" "aego/app/projects"
"aego/asset/pipeline" "aego/asset/pipeline"
"aego/editor/core/services" "aego/editor/core/services"
"aego/editor/core/sysopen"
"aego/engine/problems" "aego/engine/problems"
"aego/project" "aego/project"
) )
@@ -92,47 +87,3 @@ func (x *exporter) Reveal(path string) error {
} }
return cmd.Start() return cmd.Start()
} }
var webServers sync.Map
func serveWeb(dir string) (string, error) {
if u, ok := webServers.Load(dir); ok {
return u.(string), nil
}
ln, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
return "", err
}
files := http.FileServer(http.Dir(dir))
h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Cross-Origin-Opener-Policy", "same-origin")
w.Header().Set("Cross-Origin-Embedder-Policy", "require-corp")
w.Header().Set("Cache-Control", "no-store")
files.ServeHTTP(w, r)
})
go http.Serve(ln, h)
u := "http://" + ln.Addr().String() + "/"
webServers.Store(dir, u)
return u, nil
}
func (x *exporter) Run(out, target string) error {
path, err := export.Launchable(x.p, target, out)
if err != nil {
return err
}
t, _ := export.ParseTarget(target)
switch {
case t.Web():
u, err := serveWeb(path)
if err != nil {
return err
}
return sysopen.Open(u)
case t.OS == "darwin":
return exec.Command("open", path).Start()
}
cmd := exec.Command(path)
cmd.Dir = filepath.Dir(path)
return cmd.Start()
}
+5 -82
View File
File diff suppressed because it is too large Load Diff
-50
View File
@@ -1,50 +0,0 @@
package edit
import (
"path/filepath"
"testing"
"aego/app/projects"
"aego/editor/shell/launcher"
"aego/project"
)
func TestLauncherCreatesAndOpens(t *testing.T) {
recent := filepath.Join(t.TempDir(), "recent")
ls, err := OpenLauncher(Config{Headless: true, Recent: recent})
if err != nil {
t.Fatal(err)
}
ls.UI.SetTab(launcher.TabNew)
dir := filepath.Join(t.TempDir(), "Aego Projects", "game")
if _, err := ls.UI.Create(dir, projects.Template2D, "", ""); err != nil {
ls.Close()
t.Fatal(err)
}
for i := 0; i < 3 && ls.Step(); i++ {
}
ls.Close()
root, ok := ls.UI.Result()
if !ok {
t.Fatal("the launcher has no result")
}
p, err := project.Load(root)
if err != nil {
t.Fatal(err)
}
s, err := Open(p, Config{Headless: true, NoWatch: true, Recent: recent})
if err != nil {
t.Fatal(err)
}
defer s.Close()
for i := 0; i < 3; i++ {
s.Step()
}
if s.App.Context().Docs.Active() == nil {
t.Fatal("no scene is open after creating the project")
}
list, _ := launcher.LoadRecent(recent)
if len(list) == 0 || list[0].Path != root {
t.Fatalf("recent list %+v", list)
}
}
-78
View File
@@ -1,78 +0,0 @@
package edit
import (
"io"
"os"
"path/filepath"
"sort"
"strconv"
"strings"
"time"
"aego/core/log"
)
const keepLogs = 10
type logFile struct {
f *os.File
}
func LogsDir() string {
dir, err := os.UserCacheDir()
if err != nil {
return ""
}
return filepath.Join(dir, "aego", "logs")
}
func attachLogs(cfg *Config) *logFile {
if cfg.Logger == nil {
cfg.Logger = log.New(log.NewTextSink(os.Stderr))
if cfg.Debug {
cfg.Logger.SetLevel(log.Debug)
}
}
dir := LogsDir()
if dir == "" || os.MkdirAll(dir, 0o755) != nil {
return &logFile{}
}
name := "editor-" + time.Now().Format("20060102-150405") + "-" + strconv.Itoa(os.Getpid()) + ".log"
f, err := os.Create(filepath.Join(dir, name))
if err != nil {
return &logFile{}
}
cfg.Logger.AddSink(log.NewTextSink(f))
pruneLogs(dir)
return &logFile{f: f}
}
func (l *logFile) writer(w io.Writer) io.Writer {
if l.f == nil {
return w
}
return io.MultiWriter(w, l.f)
}
func (l *logFile) close() {
if l.f != nil {
l.f.Close()
}
}
func pruneLogs(dir string) {
entries, err := os.ReadDir(dir)
if err != nil {
return
}
var names []string
for _, e := range entries {
if !e.IsDir() && strings.HasSuffix(e.Name(), ".log") {
names = append(names, e.Name())
}
}
sort.Strings(names)
for i := 0; i+keepLogs < len(names); i++ {
os.Remove(filepath.Join(dir, names[i]))
}
}
+1 -1
View File
@@ -179,7 +179,7 @@ func TestProfilerSectionsFollowPlay(t *testing.T) {
s.Step() s.Step()
} }
drawPanel(s, prof) drawPanel(s, prof)
expectSections(t, prof.Sections(), "Frame", "Memory", "Game", "Scripts", "Physics", "Audio") expectSections(t, prof.Sections(), "Frame", "Memory", "Game", "Scripts", "Physics")
if _, err := ctx.Docs.Open("scenes/other.aescene"); err != nil { if _, err := ctx.Docs.Open("scenes/other.aescene"); err != nil {
t.Fatal(err) t.Fatal(err)
} }
-77
View File
@@ -1,77 +0,0 @@
package edit
import (
"os"
"os/exec"
"strings"
"aego/app/proc"
"aego/editor/core/session"
)
const (
EnvEditorExe = "AEGO_EDITOR_EXE"
EnvEditorVerb = "AEGO_EDITOR_VERB"
)
func markEntry(verb string) {
if os.Getenv(EnvEditorExe) != "" {
return
}
if img := os.Getenv("APPIMAGE"); img != "" {
os.Setenv(EnvEditorExe, img)
os.Setenv(EnvEditorVerb, "")
return
}
exe, err := os.Executable()
if err != nil {
return
}
os.Setenv(EnvEditorExe, exe)
os.Setenv(EnvEditorVerb, verb)
}
func relaunchArgs(verb, target, tab string) []string {
if verb != "" {
args := []string{verb}
if target != "" {
args = append(args, target)
}
if tab != "" {
args = append(args, "--launcher", tab)
}
return args
}
var args []string
if tab != "" {
args = append(args, "-launcher", tab)
}
if target != "" {
args = append(args, target)
}
return args
}
func withoutEnv(env []string, key string) []string {
out := env[:0:0]
for _, kv := range env {
if !strings.HasPrefix(kv, key+"=") {
out = append(out, kv)
}
}
return out
}
func Relaunch(target, tab string) error {
exe := os.Getenv(EnvEditorExe)
if exe == "" {
var err error
if exe, err = os.Executable(); err != nil {
return err
}
}
cmd := exec.Command(exe, relaunchArgs(os.Getenv(EnvEditorVerb), target, tab)...)
cmd.Env = withoutEnv(os.Environ(), session.EnvSupervised)
proc.Hide(cmd)
return cmd.Start()
}
-77
View File
@@ -1,77 +0,0 @@
package edit
import (
"os"
"path/filepath"
"slices"
"testing"
"aego/project"
)
func TestRelaunchArgs(t *testing.T) {
cases := []struct {
verb, target, tab string
want []string
}{
{"", "/p", "", []string{"/p"}},
{"", "", "recent", []string{"-launcher", "recent"}},
{"edit", "/p", "", []string{"edit", "/p"}},
{"edit", "", "new", []string{"edit", "--launcher", "new"}},
}
for _, c := range cases {
if got := relaunchArgs(c.verb, c.target, c.tab); !slices.Equal(got, c.want) {
t.Errorf("%q %q %q: %v, want %v", c.verb, c.target, c.tab, got, c.want)
}
}
env := withoutEnv([]string{"A=1", "AEGO_SUPERVISED=1", "B=2"}, "AEGO_SUPERVISED")
if !slices.Equal(env, []string{"A=1", "B=2"}) {
t.Fatal(env)
}
}
func TestResolveArg(t *testing.T) {
root := t.TempDir()
os.WriteFile(filepath.Join(root, project.FileName), []byte("project version=1 {\n}\n"), 0o644)
os.MkdirAll(filepath.Join(root, "scenes"), 0o755)
scene := filepath.Join(root, "scenes", "main.aescene")
os.WriteFile(scene, []byte("scene version=1 {\n}\n"), 0o644)
if dir, file := resolveArg(filepath.Join(root, project.FileName)); dir != root || file != "" {
t.Fatalf("project.aego: %q %q", dir, file)
}
dir, file := resolveArg(scene)
if dir != filepath.Join(root, "scenes") || file != scene {
t.Fatalf("scene: %q %q", dir, file)
}
if rel, ok := relInside(root, file); !ok || rel != "scenes/main.aescene" {
t.Fatalf("rel %q %v", rel, ok)
}
}
func TestNewer(t *testing.T) {
cases := []struct {
latest, current string
want bool
}{
{"v0.9.0", "0.9.0-beta.1", true},
{"v0.9.0-beta.1", "0.9.0-beta.1", false},
{"v0.9.0-beta.2", "0.9.0-beta.1", true},
{"v0.8.5", "0.9.0-beta.1", false},
{"v1.0.0", "0.9.0", true},
{"nightly", "0.9.0", false},
{"", "0.9.0", false},
}
for _, c := range cases {
if got := newer(c.latest, c.current); got != c.want {
t.Errorf("newer(%q, %q) = %v", c.latest, c.current, got)
}
}
file := filepath.Join(t.TempDir(), "update")
st := updateState{Enabled: false, Latest: "v1.2.3"}
if err := saveUpdate(file, st); err != nil {
t.Fatal(err)
}
if back := loadUpdate(file); back.Enabled || back.Latest != "v1.2.3" {
t.Fatalf("round trip %+v", back)
}
}
-17
View File
@@ -1,17 +0,0 @@
package edit
import (
"bytes"
"aego/app/run"
)
func (s *Session) runTests(done func(out string, failed bool)) error {
p, mods := s.Project, s.mods
go func() {
var buf bytes.Buffer
code := run.Tool(p, []string{"test", "-v"}, &buf, &buf, mods...)
s.Engine.Jobs().OnMain(func() { done(buf.String(), code != 0) })
}()
return nil
}
-194
View File
File diff suppressed because it is too large Load Diff
+1 -3
View File
@@ -12,7 +12,6 @@ import (
"aego/app/export/icon" "aego/app/export/icon"
"aego/app/export/winres" "aego/app/export/winres"
"aego/app/proc"
"aego/core/errs" "aego/core/errs"
"aego/core/log" "aego/core/log"
"aego/runtime/bundle" "aego/runtime/bundle"
@@ -122,7 +121,7 @@ func (j *job) resources(dir string) error {
var icons []winres.Icon var icons []winres.Icon
if j.icon != nil { if j.icon != nil {
for _, n := range winres.IconSizes { for _, n := range winres.IconSizes {
data, err := icon.PNG(icon.Sized(j.icon, n)) data, err := icon.PNG(icon.Resize(j.icon, n, n))
if err != nil { if err != nil {
return err return err
} }
@@ -176,7 +175,6 @@ func (j *job) build() error {
args = append(args, pkg) args = append(args, pkg)
cmd := exec.Command("go", args...) cmd := exec.Command("go", args...)
cmd.Dir = root cmd.Dir = root
proc.Hide(cmd)
cgo := "CGO_ENABLED=1" cgo := "CGO_ENABLED=1"
if j.t.Web() { if j.t.Web() {
cgo = "CGO_ENABLED=0" cgo = "CGO_ENABLED=0"
+2 -3
View File
@@ -189,9 +189,8 @@ func (j *job) license(lib bundle.Lib, src, name string) bundle.Lib {
} }
func (j *job) libs() []bundle.Lib { func (j *job) libs() []bundle.Lib {
vorbis := j.license(bundle.Lib{Name: "oggvorbis", Link: "static"}, filepath.Join(j.opt.Engine, "audio", "codec", "vorbis", "internal", "oggvorbis", "LICENSE"), "oggvorbis.txt")
if j.t.Web() { if j.t.Web() {
return []bundle.Lib{j.license(bundle.Lib{Name: "Go wasm_exec.js", Link: "script", File: webExec}, filepath.Join(j.goroot, "LICENSE"), "Go.txt"), vorbis} return []bundle.Lib{j.license(bundle.Lib{Name: "Go wasm_exec.js", Link: "script", File: webExec}, filepath.Join(j.goroot, "LICENSE"), "Go.txt")}
} }
return []bundle.Lib{j.license(bundle.Lib{Name: "SDL3", Link: "static"}, j.sdlLicense(), "SDL3.txt"), vorbis} return []bundle.Lib{j.license(bundle.Lib{Name: "SDL3", Link: "static"}, j.sdlLicense(), "SDL3.txt")}
} }
-18
View File
@@ -307,21 +307,3 @@ func (j *job) prepareOut() error {
} }
return nil return nil
} }
func Launchable(p *project.Project, target, out string) (string, error) {
t, err := ParseTarget(target)
if err != nil {
return "", err
}
if !t.Web() && !t.Host() {
return "", errs.New(errs.EngineConfig, "the build is for "+t.String()+"; copy it to that system to run it")
}
l := layoutFor(t, out, p)
switch {
case t.Web():
return l.root, nil
case t.OS == "darwin":
return l.app, nil
}
return l.binary(), nil
}
File diff suppressed because it is too large Load Diff
+1 -25
View File
@@ -13,12 +13,6 @@ import (
"aego/core/errs" "aego/core/errs"
) )
type DocType struct {
Name string
Extensions []string
Role string
}
type Info struct { type Info struct {
Name string Name string
Executable string Executable string
@@ -28,7 +22,6 @@ type Info struct {
MinOS string MinOS string
Category string Category string
Copyright string Copyright string
Documents []DocType
} }
var icnsTypes = []struct { var icnsTypes = []struct {
@@ -87,23 +80,6 @@ func Plist(i Info, iconFile string) []byte {
str("LSMinimumSystemVersion", i.MinOS) str("LSMinimumSystemVersion", i.MinOS)
str("LSApplicationCategoryType", i.Category) str("LSApplicationCategoryType", i.Category)
str("NSHumanReadableCopyright", i.Copyright) str("NSHumanReadableCopyright", i.Copyright)
if len(i.Documents) > 0 {
b.WriteString("\t<key>CFBundleDocumentTypes</key>\n\t<array>\n")
for _, d := range i.Documents {
role := d.Role
if role == "" {
role = "Editor"
}
b.WriteString("\t\t<dict>\n\t\t\t<key>CFBundleTypeName</key>\n\t\t\t<string>" + esc(d.Name) + "</string>\n")
b.WriteString("\t\t\t<key>CFBundleTypeRole</key>\n\t\t\t<string>" + esc(role) + "</string>\n")
b.WriteString("\t\t\t<key>CFBundleTypeExtensions</key>\n\t\t\t<array>\n")
for _, e := range d.Extensions {
b.WriteString("\t\t\t\t<string>" + esc(e) + "</string>\n")
}
b.WriteString("\t\t\t</array>\n\t\t</dict>\n")
}
b.WriteString("\t</array>\n")
}
b.WriteString("\t<key>NSHighResolutionCapable</key>\n\t<true/>\n") b.WriteString("\t<key>NSHighResolutionCapable</key>\n\t<true/>\n")
b.WriteString("</dict>\n</plist>\n") b.WriteString("</dict>\n</plist>\n")
return []byte(b.String()) return []byte(b.String())
@@ -116,7 +92,7 @@ func ICNS(src image.Image) ([]byte, error) {
data, ok := cache[t.size] data, ok := cache[t.size]
if !ok { if !ok {
var err error var err error
if data, err = icon.PNG(icon.Sized(src, t.size)); err != nil { if data, err = icon.PNG(icon.Resize(src, t.size, t.size)); err != nil {
return nil, err return nil, err
} }
cache[t.size] = data cache[t.size] = data
-9
View File
@@ -23,12 +23,3 @@ func TestPlistEscapesAndBundleID(t *testing.T) {
t.Fatal(p) t.Fatal(p)
} }
} }
func TestPlistDocumentTypes(t *testing.T) {
out := string(Plist(Info{Name: "Aego", Executable: "aego", ID: "ru.akarpov.aego", Documents: []DocType{{Name: "Aego Scene", Extensions: []string{"aescene"}}}}, ""))
for _, want := range []string{"<key>CFBundleDocumentTypes</key>", "<string>Aego Scene</string>", "<string>Editor</string>", "<string>aescene</string>"} {
if !strings.Contains(out, want) {
t.Fatalf("plist has no %s:\n%s", want, out)
}
}
}
+1 -1
View File
@@ -29,7 +29,7 @@ func (j *job) pack() error {
func (j *job) packLinux() error { func (j *job) packLinux() error {
if j.icon != nil { if j.icon != nil {
data, err := icon.PNG(icon.Sized(j.icon, 256)) data, err := icon.PNG(icon.Resize(j.icon, 256, 256))
if err != nil { if err != nil {
return err return err
} }
+1 -6
View File
@@ -26,7 +26,6 @@ var webFS embed.FS
const ( const (
CodeWebAsset = "EXP010" CodeWebAsset = "EXP010"
CodeWebNative = "EXP011" CodeWebNative = "EXP011"
CodeWebMP3 = "EXP012"
WebWasm = "game.wasm" WebWasm = "game.wasm"
WebFiles = "files.json" WebFiles = "files.json"
WebBudget = 8 << 20 WebBudget = 8 << 20
@@ -69,11 +68,7 @@ func CheckWeb(s *Snapshot, native bool) []problems.Diagnostic {
out = append(out, diag(CodeWebNative, problems.Warning, out = append(out, diag(CodeWebNative, problems.Warning,
"the native Go module is compiled to WebAssembly: it must build without cgo and must not use files, processes or the network", "native/")) "the native Go module is compiled to WebAssembly: it must build without cgo and must not use files, processes or the network", "native/"))
} }
_, ffmpegErr := exec.LookPath("ffmpeg")
s.idx.Each(func(e *asset.Entry) { s.idx.Each(func(e *asset.Entry) {
if ffmpegErr != nil && strings.EqualFold(filepath.Ext(e.Source), ".mp3") {
out = append(out, diag(CodeWebMP3, problems.Warning, e.Source+" is an mp3; it is converted to ogg on import, which needs ffmpeg in PATH", e.Source))
}
if e.Missing || exportSkip(e.Kind) || !webUnsupported(e.Kind) { if e.Missing || exportSkip(e.Kind) || !webUnsupported(e.Kind) {
return return
} }
@@ -161,7 +156,7 @@ func (j *job) packWeb() error {
return err return err
} }
if j.icon != nil { if j.icon != nil {
data, err := icon.PNG(icon.Sized(j.icon, webIconSize)) data, err := icon.PNG(icon.Resize(j.icon, webIconSize, webIconSize))
if err != nil { if err != nil {
return err return err
} }
+2 -8
View File
@@ -18,13 +18,8 @@ canvas { display: block; width: 100%; height: 100%; outline: none; touch-action:
#status { color: #9a9890; font-size: 13px; } #status { color: #9a9890; font-size: 13px; }
.loader.failed #bar { background: #f0776c; } .loader.failed #bar { background: #f0776c; }
#error { max-width: min(640px, 90vw); max-height: 40vh; overflow: auto; margin: 0; padding: 10px 12px; white-space: pre-wrap; color: #f0776c; background: #1d1f23; border-radius: 6px; font: 12px/1.5 ui-monospace, Menlo, Consolas, monospace; } #error { max-width: min(640px, 90vw); max-height: 40vh; overflow: auto; margin: 0; padding: 10px 12px; white-space: pre-wrap; color: #f0776c; background: #1d1f23; border-radius: 6px; font: 12px/1.5 ui-monospace, Menlo, Consolas, monospace; }
#fullscreen { position: fixed; top: 10px; right: 10px; width: 36px; height: 36px; border: 0; border-radius: 6px; background: rgba(0, 0, 0, 0.45); color: #fff; padding: 0; cursor: pointer; opacity: 0.5; } #fullscreen { position: fixed; top: 10px; right: 10px; width: 36px; height: 36px; border: 0; border-radius: 6px; background: rgba(0, 0, 0, 0.45); color: #fff; font-size: 18px; cursor: pointer; opacity: 0.5; }
#fullscreen:hover { opacity: 1; } #fullscreen:hover { opacity: 1; }
#mute { position: fixed; top: 10px; right: 52px; width: 36px; height: 36px; border: 0; border-radius: 6px; background: rgba(0, 0, 0, 0.45); color: #fff; padding: 0; cursor: pointer; opacity: 0.5; }
#mute:hover { opacity: 1; }
#fullscreen svg, #mute svg { display: block; width: 18px; height: 18px; margin: auto; }
#mute .off, #mute.muted .on { display: none; }
#mute.muted .off { display: inline; }
</style> </style>
<link rel="preload" href="game.wasm?v={{.Build}}" as="fetch" type="application/wasm" crossorigin> <link rel="preload" href="game.wasm?v={{.Build}}" as="fetch" type="application/wasm" crossorigin>
</head> </head>
@@ -36,8 +31,7 @@ canvas { display: block; width: 100%; height: 100%; outline: none; touch-action:
<div id="status">Loading…</div> <div id="status">Loading…</div>
<pre id="error" hidden></pre> <pre id="error" hidden></pre>
</div> </div>
<button id="fullscreen" type="button" title="Fullscreen" aria-label="Fullscreen" hidden><svg viewBox="0 0 16 16" aria-hidden="true"><path fill="currentColor" d="M9.92 13.44L10.25 13.38L13.38 13.38L13.38 10.25L13.44 9.92L13.76 9.52L14.08 9.39L14.58 9.44L14.98 9.76L15.12 10.25L15.12 14.25L15.06 14.58L14.74 14.98L14.25 15.12L10.25 15.12L9.92 15.06L9.52 14.74L9.38 14.25L9.52 13.76ZM13.44 6.08L13.38 5.75L13.38 2.62L10.25 2.62L9.92 2.56L9.52 2.24L9.39 1.92L9.44 1.42L9.76 1.02L10.25 0.88L14.25 0.88L14.58 0.94L14.98 1.26L15.12 1.75L15.12 5.75L15.06 6.08L14.74 6.48L14.25 6.62L13.76 6.48ZM2.56 9.92L2.62 10.25L2.62 13.38L5.75 13.38L6.08 13.44L6.48 13.76L6.62 14.25L6.56 14.58L6.24 14.98L5.75 15.12L1.75 15.12L1.42 15.06L1.02 14.74L0.88 14.25L0.88 10.25L0.94 9.92L1.26 9.52L1.75 9.38L2.24 9.52ZM6.08 2.56L5.75 2.62L2.62 2.62L2.62 5.75L2.56 6.08L2.24 6.48L1.75 6.62L1.42 6.56L1.02 6.24L0.88 5.75L0.88 1.75L0.94 1.42L1.26 1.02L1.75 0.88L5.75 0.88L6.08 0.94L6.48 1.26L6.62 1.75L6.48 2.24Z"/></svg></button> <button id="fullscreen" type="button" title="Fullscreen" aria-label="Fullscreen" hidden>⛶</button>
<button id="mute" type="button" title="Mute" aria-label="Mute" hidden><svg viewBox="0 0 16 16" aria-hidden="true"><path fill="currentColor" d="M1.81 6.04L4 6L6.74 3.47L7.11 3.41L7.36 3.55L7.5 3.9L7.5 12.1L7.36 12.45L7.11 12.59L6.74 12.53L4 10L2 10L1.65 9.85L1.5 9.5L1.5 6.5L1.58 6.22Z"/><path class="on" fill="currentColor" d="M12.53 5.89L11.97 4.96L11.01 3.9L10.95 3.62L10.99 3.33L11.15 3.08L11.39 2.91L11.82 2.86L12.21 3.05L12.72 3.54L13.53 4.59L13.91 5.29L14.17 5.95L14.35 6.63L14.5 7.96L14.46 8.75L14.34 9.45L14.14 10.13L13.58 11.34L13.18 11.92L12.67 12.52L12.09 13.04L11.67 13.15L11.39 13.09L11.15 12.92L10.99 12.67L10.95 12.38L11.09 11.97L11.61 11.46L12.27 10.59L12.73 9.61L12.88 9.08L12.97 8.54L12.97 7.46L12.73 6.39ZM10.05 7.09L9.82 6.68L9.38 6.19L9.26 5.77L9.31 5.48L9.48 5.24L9.72 5.08L10.01 5.02L10.29 5.08L10.54 5.24L11.01 5.76L11.27 6.16L11.66 7.18L11.75 8.04L11.58 9.12L11.23 9.91L10.54 10.76L10.29 10.92L10.01 10.98L9.72 10.92L9.48 10.76L9.31 10.52L9.26 10.23L9.38 9.81L9.95 9.12L10.2 8.47L10.24 7.76Z"/><path class="off" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" d="M10.25 5.75l4.5 4.5M14.75 5.75l-4.5 4.5"/></svg></button>
<script src="wasm_exec.js?v={{.Build}}"></script> <script src="wasm_exec.js?v={{.Build}}"></script>
<script src="loader.js?v={{.Build}}"></script> <script src="loader.js?v={{.Build}}"></script>
</body> </body>

Some files were not shown because too many files have changed in this diff Show More