initial commit

This commit is contained in:
2024-03-25 12:12:08 +01:00
parent cfd94b9fcb
commit c8d7e8fe87
11 changed files with 803 additions and 0 deletions

88
Makefile Normal file
View File

@@ -0,0 +1,88 @@
# Copyright © 2024 Thomas von Dein
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# no need to modify anything below
tool = kage-viewer
VERSION = $(shell grep VERSION config.go | head -1 | cut -d '"' -f2)
archs = darwin freebsd linux windows
PREFIX = /usr/local
UID = root
GID = 0
HAVE_POD := $(shell pod2text -h 2>/dev/null)
all: buildlocal
# doesn't build
#CGO_LDFLAGS='-static' go build -tags osusergo,netgo -ldflags "-extldflags=-static" -o $(tool)
buildlocal:
go build
install: buildlocal
install -d -o $(UID) -g $(GID) $(PREFIX)/bin
install -d -o $(UID) -g $(GID) $(PREFIX)/man/man1
install -o $(UID) -g $(GID) -m 555 $(tool) $(PREFIX)/sbin/
install -o $(UID) -g $(GID) -m 444 $(tool).1 $(PREFIX)/man/man1/
clean:
rm -rf $(tool) coverage.out testdata t/out
test: clean
mkdir -p t/out
go test ./... $(ARGS)
testlint: test lint
lint:
golangci-lint run
lint-full:
golangci-lint run --enable-all --exclude-use-default --disable exhaustivestruct,exhaustruct,depguard,interfacer,deadcode,golint,structcheck,scopelint,varcheck,ifshort,maligned,nosnakecase,godot,funlen,gofumpt,cyclop,noctx,gochecknoglobals,paralleltest
testfuzzy: clean
go test -fuzz ./... $(ARGS)
singletest:
@echo "Call like this: make singletest TEST=TestPrepareColumns ARGS=-v"
go test -run $(TEST) $(ARGS)
cover-report:
go test ./... -cover -coverprofile=coverage.out
go tool cover -html=coverage.out
goupdate:
go get -t -u=patch ./...
buildall:
./mkrel.sh $(tool) $(VERSION)
release: buildall
gh release create v$(VERSION) --generate-notes releases/*
show-versions: buildlocal
@echo "### kage-viewer version:"
@./kage-viewer -V
@echo
@echo "### go module versions:"
@go list -m all
@echo
@echo "### go version used for building:"
@grep -m 1 go go.mod
# lint:
# golangci-lint run -p bugs -p unused

132
README.md Normal file
View File

@@ -0,0 +1,132 @@
# kage-viewer - Viewer for shaders written in Kage, similar to glslviewer
[![License](https://img.shields.io/badge/license-GPL-blue.svg)](https://github.com/tlinden/kage-viewer/blob/master/LICENSE)
[![Go Report Card](https://goreportcard.com/badge/github.com/tlinden/kage-viewer)](https://goreportcard.com/report/github.com/tlinden/kage-viewer)
This little tool can be used to test shaders written in [Kage](https://ebitengine.org/en/documents/shader.html), a shader meta language for [Ebitengine](https://github.com/hajimehoshi/ebiten).
## Installation
The tool does not have any dependencies. Just download the binary for
your platform from the releases page and you're good to go.
### Installation using a pre-compiled binary
Go to the [latest release page](https://github.com/TLINDEN/kage-viewer/releases/latest)
and look for your OS and platform. There are two options to install the binary:
Directly download the binary for your platform,
e.g. `kage-viewer-linux-amd64-0.0.2`, rename it to `kage-viewer` (or whatever
you like more!) and put it into your bin dir (e.g. `$HOME/bin` or as
root to `/usr/local/bin`).
Be sure to verify the signature of the binary file. For this also
download the matching `kage-viewer-linux-amd64-0.0.2.sha256` file and:
```shell
cat kage-viewer-linux-amd64-0.0.2.sha25 && sha256sum kage-viewer-linux-amd64-0.0.2
```
You should see the same SHA256 hash.
You may also download a binary tarball for your platform, e.g.
`kage-viewer-linux-amd64-0.0.2.tar.gz`, unpack and install it. GNU Make is
required for this:
```shell
tar xvfz kage-viewer-linux-amd64-0.0.2.tar.gz
cd kage-viewer-linux-amd64-0.0.2
sudo make install
```
### Installation from source
You will need the Golang toolchain in order to build from source. GNU
Make will also help but is not strictly neccessary.
If you want to compile the tool yourself, use `git clone` to clone the
repository. Then execute `go mod tidy` to install all
dependencies. Then just enter `go build` or - if you have GNU Make
installed - `make`.
To install after building either copy the binary or execute `sudo make
install`.
# Usage
```shell
kage-viewer -h
This is kage-viewer, a shader viewer.
Usage: kage-viewer [-vd] [-c <config file>] [-g geom] [-p geom] \
-i <image0.png> -i <image1.png> -s <shader.kage>
Options:
-c --config <toml file> Config file to use (optional)
-i --image <png file> Image to load (multiple times allowed, up to 4)
-s --shader <kage file> Shader to run
-g --geometry <WIDTHxHEIGHT> Window size
-p --position <XxY> Position of image0
-d --debug Show debugging output
-v --version Show program version
```
Example usage using the provided example:
```shell
kage-viewer -g 32x32 -i example/wall.png -i example/damage.png -s example/destruct.kg
```
Hit `SPACE` or press the left mouse button to toggle the damage
mask. Press the `UP` or `DOWN` key to adjust the damage scale.
# Uniforms
Since this is a generic viewer, you cannot (yet) use custom
uniforms. If you need this, just edit the source accordingly.
Uniforms supported so far:
- `var Flag int`: a flag which toggles between 0 and 1 by pressing
`SPACE` or pusing the left mouse button
- `var Slider float`: a normalized float value, you can increment it
with `UP` or `DOWN`
- `var Ticks int`: the time the game runs (ticks, not seconds!)
- `var Mouse vec2`: the current mouse position
# Config File
You can use a config file to store your own codes, once you found one
you like. A configfile is searched in these locations in this order:
* `/etc/kage-viewer.conf`
* `/usr/local/etc/kage-viewer.conf`
* `$HOME/.config/kage-viewer/config`
* `$HOME/.kage-viewer`
You may also specify a config file on the commandline using the `-c`
flag.
Config files are expected to be in the [TOML format](https://toml.io/en/).
Possible parameters equal the long command line options.
# TODO
- [X] Implement loading of images and shader files
- [X] Implement basic shader rendering and user input
- [ ] Add custom uniforms (maybe using lua code?)
- [ ] Provide a way to respond live to shader code changes (use lua as
well?)
# Report bugs
[Please open an issue](https://github.com/TLINDEN/kage-viewer/issues). Thanks!
# License
This work is licensed under the terms of the General Public Licens
version 3.
# Author
Copyleft (c) 2024 Thomas von Dein

192
config.go Normal file
View File

@@ -0,0 +1,192 @@
/*
Copyright © 2024 Thomas von Dein
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package main
import (
"fmt"
"os"
"path/filepath"
"strconv"
"strings"
"github.com/knadh/koanf/parsers/toml"
"github.com/knadh/koanf/providers/file"
"github.com/knadh/koanf/providers/posflag"
"github.com/knadh/koanf/v2"
flag "github.com/spf13/pflag"
)
const (
VERSION string = "0.0.1"
Usage string = `This is kage-viewer, a shader viewer.
Usage: kage-viewer [-vd] [-c <config file>] [-g geom] [-p geom] \
-i <image0.png> -i <image1.png> -s <shader.kage>
Options:
-c --config <toml file> Config file to use (optional)
-i --image <png file> Image to load (multiple times allowed, up to 4)
-s --shader <kage file> Shader to run
-g --geometry <WIDTHxHEIGHT> Window size
-p --position <XxY> Position of image0
-d --debug Show debugging output
-v --version Show program version
`
)
type Config struct {
Showversion bool `koanf:"version"` // -v
Debug bool `koanf:"debug"` // -d
Config string `koanf:"config"` // -c
Image []string `koanf:"image"` // -i
Shader string `koanf:"shader"` // -s
Geo string `koanf:"geometry"` // -g
Posision string `koanf:"position"` // -p
X, Y, Width, Height int // feed from -g + -p
}
func InitConfig() (*Config, error) {
var kloader = koanf.New(".")
// Load default values using the confmap provider.
/* not needed yet
if err := kloader.Load(confmap.Provider(map[string]interface{}{
}, "."), nil); err != nil {
return nil, fmt.Errorf("failed to load default values into koanf: %w", err)
}
*/
// setup custom usage
flagset := flag.NewFlagSet("config", flag.ContinueOnError)
flagset.Usage = func() {
fmt.Println(Usage)
os.Exit(0)
}
// parse commandline flags
flagset.BoolP("version", "v", false, "show program version")
flagset.BoolP("debug", "d", false, "enable debug output")
flagset.StringP("config", "c", "", "config file")
flagset.StringP("geometry", "g", "256x256", "window geometry")
flagset.StringP("position", "p", "0x0", "position of shader")
flagset.StringArrayP("image", "i", nil, "image file")
flagset.StringP("shader", "s", "", "shader file")
if err := flagset.Parse(os.Args[1:]); err != nil {
return nil, fmt.Errorf("failed to parse program arguments: %w", err)
}
// generate a list of config files to try to load, including the
// one provided via -c, if any
var configfiles []string
configfile, _ := flagset.GetString("config")
home, _ := os.UserHomeDir()
if configfile != "" {
configfiles = []string{configfile}
} else {
configfiles = []string{
"/etc/kage-viewer.conf", "/usr/local/etc/kage-viewer.conf", // unix variants
filepath.Join(home, ".config", "kage-viewer", "config"),
filepath.Join(home, ".kage-viewer"),
"kage-viewer.conf",
}
}
// Load the config file[s]
for _, cfgfile := range configfiles {
if path, err := os.Stat(cfgfile); !os.IsNotExist(err) {
if !path.IsDir() {
if err := kloader.Load(file.Provider(cfgfile), toml.Parser()); err != nil {
return nil, fmt.Errorf("error loading config file: %w", err)
}
}
} // else: we ignore the file if it doesn't exists
}
// command line setup
if err := kloader.Load(posflag.Provider(flagset, ".", kloader), nil); err != nil {
return nil, fmt.Errorf("error loading flags: %w", err)
}
// fetch values
conf := &Config{}
if err := kloader.Unmarshal("", &conf); err != nil {
return nil, fmt.Errorf("error unmarshalling: %w", err)
}
if err := SanitiyCheck(conf); err != nil {
return nil, err
}
return conf, nil
}
func SanitiyCheck(conf *Config) error {
if len(conf.Image) < 1 {
return fmt.Errorf("at least 1 image must be specified")
}
if conf.Shader == "" {
return fmt.Errorf("shader file must be specified")
}
geoerr := "window geometry must be specified as NUMBERxNUMBER, e.g. 32x32"
geo := strings.Split(conf.Geo, "x")
if len(geo) != 2 {
return fmt.Errorf(geoerr)
}
w, errw := strconv.Atoi(geo[0])
h, errh := strconv.Atoi(geo[1])
if errw != nil || errh != nil {
return fmt.Errorf(geoerr)
}
conf.Width = w
conf.Height = h
poserr := "shader position must be specified as NUMBERxNUMBER, e.g. 32x32"
pos := strings.Split(conf.Posision, "x")
if len(geo) != 2 {
return fmt.Errorf(poserr)
}
x, errx := strconv.Atoi(pos[0])
y, erry := strconv.Atoi(pos[1])
if errx != nil || erry != nil {
return fmt.Errorf(poserr)
}
conf.X = x
conf.Y = y
return nil
}
func fileExists(filename string) bool {
info, err := os.Stat(filename)
if os.IsNotExist(err) {
return false
}
return !info.IsDir()
}

BIN
example/damage.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

37
example/destruct.kg Normal file
View File

@@ -0,0 +1,37 @@
// Copyright 2020 The Ebiten Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//go:build ignore
//kage:unit pixels
package main
var Flag int
var Slider float
var Time int
var Mouse vec2
func Fragment(_ vec4, texCoord vec2, _ vec4) vec4 {
wallpx := imageSrc0At(texCoord) // A pixel from the wall tile
mask := imageSrc1At(texCoord) // A pixel from the damage mask image
if Flag == 1 && (wallpx.a != 0.0 && mask.a != 0.0) {
alpha := clamp(Slider+(1.0-mask.a), 0.0, 1.0)
// Create a darker pixel if it's inside a damage mask.
return vec4(wallpx.r*alpha, wallpx.g*alpha, wallpx.b*alpha, wallpx.a)
}
return wallpx // Otherwise, leave a pixel color as is
}

BIN
example/wall.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

155
game.go Normal file
View File

@@ -0,0 +1,155 @@
/*
Copyright © 2024 Thomas von Dein
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package main
import (
"fmt"
"image"
_ "image/png"
"log/slog"
"os"
"github.com/hajimehoshi/ebiten/v2"
"github.com/hajimehoshi/ebiten/v2/inpututil"
)
type Game struct {
Conf *Config
Images []*ebiten.Image
Shader *ebiten.Shader
Ticks int
Slider float64
Flag int
}
func LoadImage(name string) (*ebiten.Image, error) {
fd, err := os.Open(name)
if err != nil {
return nil, err
}
defer fd.Close()
img, _, err := image.Decode(fd)
if err != nil {
return nil, fmt.Errorf("failed to load image %s: %s", name, err)
}
return ebiten.NewImageFromImage(img), nil
}
func (game *Game) Init() error {
for _, image := range game.Conf.Image {
slog.Debug("Loading images", "image", image)
img, err := LoadImage(image)
if err != nil {
return err
}
game.Images = append(game.Images, img)
}
data, err := os.ReadFile(game.Conf.Shader)
if err != nil {
return fmt.Errorf("failed to load shader %s: %s", game.Conf.Shader, err)
}
shader, err := ebiten.NewShader(data)
if err != nil {
return fmt.Errorf("failed to create new shader %s: %s", game.Conf.Shader, err)
}
game.Shader = shader
return nil
}
func (g *Game) CheckInput() bool {
pressed := false
switch {
case inpututil.IsMouseButtonJustPressed(ebiten.MouseButton0):
fallthrough
case inpututil.IsKeyJustPressed(ebiten.KeySpace):
g.Toggle()
pressed = true
case inpututil.IsKeyJustPressed(ebiten.KeyUp):
g.Up()
pressed = true
case inpututil.IsKeyJustPressed(ebiten.KeyDown):
g.Down()
pressed = true
case inpututil.IsKeyJustPressed(ebiten.KeyQ):
os.Exit(0)
}
return pressed
}
func (g *Game) Toggle() {
g.Flag = 1 - g.Flag
}
func (g *Game) Up() {
g.Slider += 0.1
if g.Slider > 1.0 {
g.Slider = 1.0
}
}
func (g *Game) Down() {
g.Slider -= 0.1
if g.Slider < 0 {
g.Slider = 0.0
}
}
func (game *Game) Update() error {
if game.CheckInput() {
slog.Debug("Key pressed", "Slider", game.Slider, "Flag", game.Flag)
}
game.Ticks++
return nil
}
func (game *Game) Draw(screen *ebiten.Image) {
op := &ebiten.DrawRectShaderOptions{}
mousex, mousey := ebiten.CursorPosition()
op.Uniforms = map[string]any{
"Flag": game.Flag,
"Slider": game.Slider,
"Ticks": game.Ticks,
"Mouse": []float64{float64(mousex), float64(mousey)},
}
for idx, image := range game.Images {
op.Images[idx] = image
}
op.GeoM.Translate(float64(game.Conf.X), float64(game.Conf.Y))
screen.DrawRectShader(game.Conf.Width, game.Conf.Height, game.Shader, op)
}
func (game *Game) Layout(outsideWidth, outsideHeight int) (int, int) {
return game.Conf.Width, game.Conf.Height
}

31
go.mod Normal file
View File

@@ -0,0 +1,31 @@
module github.com/TLINDEN/kage-viewer
go 1.22
require (
github.com/ebitengine/purego v0.6.0 // indirect
github.com/fatih/color v1.16.0 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 // indirect
github.com/hajimehoshi/ebiten/v2 v2.6.7 // indirect
github.com/jezek/xgb v1.1.0 // indirect
github.com/knadh/koanf/maps v0.1.1 // indirect
github.com/knadh/koanf/parsers/toml v0.1.0 // indirect
github.com/knadh/koanf/providers/confmap v0.1.0 // indirect
github.com/knadh/koanf/providers/file v0.1.0 // indirect
github.com/knadh/koanf/providers/posflag v0.1.0 // indirect
github.com/knadh/koanf/v2 v2.1.0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/pelletier/go-toml v1.9.5 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/tlinden/yadu v0.1.3 // indirect
golang.org/x/exp/shiny v0.0.0-20230817173708-d852ddb80c63 // indirect
golang.org/x/image v0.12.0 // indirect
golang.org/x/mobile v0.0.0-20230922142353-e2f452493d57 // indirect
golang.org/x/sync v0.3.0 // indirect
golang.org/x/sys v0.14.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

88
go.sum Normal file
View File

@@ -0,0 +1,88 @@
github.com/ebitengine/purego v0.6.0 h1:Yo9uBc1x+ETQbfEaf6wcBsjrQfCEnh/gaGUg7lguEJY=
github.com/ebitengine/purego v0.6.0/go.mod h1:ah1In8AOtksoNK6yk5z1HTJeUkC1Ez4Wk2idgGslMwQ=
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsMBaUOKXq6HSv655U1c=
github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/hajimehoshi/ebiten/v2 v2.6.7 h1:rxlMxu487wZN/JteykmuGdO1qotOolL8vJDU85lPh7A=
github.com/hajimehoshi/ebiten/v2 v2.6.7/go.mod h1:gKgQI26zfoSb6j5QbrEz2L6nuHMbAYwrsXa5qsGrQKo=
github.com/jezek/xgb v1.1.0 h1:wnpxJzP1+rkbGclEkmwpVFQWpuE2PUGNUzP8SbfFobk=
github.com/jezek/xgb v1.1.0/go.mod h1:nrhwO0FX/enq75I7Y7G8iN1ubpSGZEiA3v9e9GyRFlk=
github.com/knadh/koanf/maps v0.1.1 h1:G5TjmUh2D7G2YWf5SQQqSiHRJEjaicvU0KpypqB3NIs=
github.com/knadh/koanf/maps v0.1.1/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI=
github.com/knadh/koanf/parsers/toml v0.1.0 h1:S2hLqS4TgWZYj4/7mI5m1CQQcWurxUz6ODgOub/6LCI=
github.com/knadh/koanf/parsers/toml v0.1.0/go.mod h1:yUprhq6eo3GbyVXFFMdbfZSo928ksS+uo0FFqNMnO18=
github.com/knadh/koanf/providers/confmap v0.1.0 h1:gOkxhHkemwG4LezxxN8DMOFopOPghxRVp7JbIvdvqzU=
github.com/knadh/koanf/providers/confmap v0.1.0/go.mod h1:2uLhxQzJnyHKfxG927awZC7+fyHFdQkd697K4MdLnIU=
github.com/knadh/koanf/providers/file v0.1.0 h1:fs6U7nrV58d3CFAFh8VTde8TM262ObYf3ODrc//Lp+c=
github.com/knadh/koanf/providers/file v0.1.0/go.mod h1:rjJ/nHQl64iYCtAW2QQnF0eSmDEX/YZ/eNFj5yR6BvA=
github.com/knadh/koanf/providers/posflag v0.1.0 h1:mKJlLrKPcAP7Ootf4pBZWJ6J+4wHYujwipe7Ie3qW6U=
github.com/knadh/koanf/providers/posflag v0.1.0/go.mod h1:SYg03v/t8ISBNrMBRMlojH8OsKowbkXV7giIbBVgbz0=
github.com/knadh/koanf/v2 v2.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8=
github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/tlinden/yadu v0.1.3 h1:5cRCUmj+l5yvlM2irtpFBIJwVV2DPEgYSaWvF19FtcY=
github.com/tlinden/yadu v0.1.3/go.mod h1:l3bRmHKL9zGAR6pnBHY2HRPxBecf7L74BoBgOOpTcUA=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/exp/shiny v0.0.0-20230817173708-d852ddb80c63 h1:3AGKexOYqL+ztdWdkB1bDwXgPBuTS/S8A4WzuTvJ8Cg=
golang.org/x/exp/shiny v0.0.0-20230817173708-d852ddb80c63/go.mod h1:UH99kUObWAZkDnWqppdQe5ZhPYESUw8I0zVV1uWBR+0=
golang.org/x/image v0.12.0 h1:w13vZbU4o5rKOFFR8y7M+c4A5jXDC0uXTdHYRP8X2DQ=
golang.org/x/image v0.12.0/go.mod h1:Lu90jvHG7GfemOIcldsh9A2hS01ocl6oNO7ype5mEnk=
golang.org/x/mobile v0.0.0-20230922142353-e2f452493d57 h1:Q6NT8ckDYNcwmi/bmxe+XbiDMXqMRW1xFBtJ+bIpie4=
golang.org/x/mobile v0.0.0-20230922142353-e2f452493d57/go.mod h1:wEyOn6VvNW7tcf+bW/wBz1sehi2s2BZ4TimyR7qZen4=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

BIN
kage-viewer Executable file

Binary file not shown.

80
main.go Normal file
View File

@@ -0,0 +1,80 @@
/*
Copyright © 2024 Thomas von Dein
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package main
import (
"fmt"
"log"
"os"
"runtime/debug"
"log/slog"
"github.com/hajimehoshi/ebiten/v2"
"github.com/tlinden/yadu"
)
func main() {
// parse config file and command line parameters, if any
conf, err := InitConfig()
if err != nil {
log.Fatal(err)
}
if conf.Showversion {
fmt.Printf("This is kage-viewer version %s\n", VERSION)
return
}
// enable debugging, if needed. We only use log/slog for
// debugging, so there's no need to configure it outside debugging
if conf.Debug {
logLevel := &slog.LevelVar{}
// we're using a more verbose logger in debug mode
buildInfo, _ := debug.ReadBuildInfo()
opts := &yadu.Options{
Level: logLevel,
AddSource: true,
}
logLevel.Set(slog.LevelDebug)
handler := yadu.NewHandler(os.Stdout, opts)
debuglogger := slog.New(handler).With(
slog.Group("program_info",
slog.Int("pid", os.Getpid()),
slog.String("go_version", buildInfo.GoVersion),
),
)
slog.SetDefault(debuglogger)
}
game := &Game{Conf: conf}
if err := game.Init(); err != nil {
log.Fatal(err)
}
ebiten.SetWindowSize(game.Conf.Width, game.Conf.Height)
ebiten.SetWindowTitle("Kage shader viewer")
ebiten.SetWindowResizable(true)
if err := ebiten.RunGame(game); err != nil {
log.Fatal(err)
}
}