├── .gitignore ├── Makefile ├── README.md ├── assets ├── demo_ttme.gif ├── example.json ├── tilesetpkm.png └── ttme_layout.rgl ├── go.mod ├── go.sum ├── main.go └── src ├── app.go ├── show_widget.go ├── tile.go ├── tile_properties_widget.go ├── tile_property.go ├── tilemap.go ├── tilemap_configuration_widget.go ├── tilemap_widget.go ├── tileset.go ├── tileset_configuration_widget.go └── tileset_widget.go /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | packaged_build/ -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all: run 2 | 3 | run: 4 | go run ./main.go 5 | 6 | build-windows: 7 | CGO_ENABLED=1 GOARCH=amd64 CC=x86_64-w64-mingw32-gcc GOOS=windows go build -o ./build/ttme-windows ./main.go 8 | 9 | build-darwin: 10 | CGO_ENABLED=1 GOARCH=amd64 CC=gcc GOOS=darwin go build -o ./build/ttme-darwin ./main.go 11 | 12 | build-linux: 13 | CGO_ENABLED=1 GOARCH=amd64 CC=gcc GOOS=linux go build -o ./build/ttme-linux ./main.go 14 | 15 | fbuild: build-windows build-darwin build-linux 16 | mkdir -p ./build/assets 17 | mkdir -p ./packaged_build 18 | cp ./assets/tilesetpkm.png ./build/assets/tilesetpkm.png 19 | zip -r ttme ./build 20 | mv ./ttme.zip ./packaged_build/ttme.zip 21 | 22 | fclean: 23 | rm -rf ./build/* 24 | rm -rf ./packaged_build/* 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Ttme is Tiny Tile Map Editor (think [Tiled](https://www.mapeditor.org/) but with way less features). It is written in [Golang](https://golang.org/) 2 | using [those bindings](https://github.com/lachee/raylib-goplus) to the awesome [raygui/raylib](https://www.raylib.com/). 3 | 4 | I started this project because I wanted to learn Go and try to build a cross-platform GUI application without using big frameworks. 5 | 6 | ## Builds 7 | 8 | ### Run 9 | 10 | Run the project 11 | 12 | `make` 13 | 14 | ### Build 15 | 16 | Build for Windows, Darwin and Linux. 17 | Bin file are under ./build. 18 | Zipfile with all builds is under ./packed_build. 19 | 20 | `make fbuild` 21 | 22 | ### Clean 23 | 24 | Clean build folders 25 | 26 | `make fclean` 27 | 28 | ## Current Feature 29 | 30 | - Define map size 31 | - Use your own tileset (with the tile size you want) 32 | - Ability to add (custom) properties to your tiles (blocking property exists by default) 33 | - Export to json 34 | - Show/Hide grid 35 | - Show/Hide properties 36 | - Reload existing map through arguments (`ttme mymap.json`) 37 | 38 | ## Known bugs or limitations 39 | 40 | - Open a File dialog at startup (It's a workaround [this bug](https://github.com/sqweek/dialog/issues/51)) 41 | - Does not support layers (may be added in the future) 42 | - Does not show well on high DPI screens (at least on my Macbook) 43 | 44 | ## Demo 45 | 46 | ![Ttme Demo](assets/demo_ttme.gif) 47 | 48 | The exported json file can be found under `assets/example.json`, but here is a template: 49 | 50 | ```json 51 | { 52 | "width": Int, 53 | "height": Int, 54 | "tileset": { 55 | "tileWidth": Int, 56 | "tileHeight": Int, 57 | "imagePath": String 58 | }, 59 | "tiles": [ 60 | { 61 | "index": Int (-1 for empty tiles), 62 | "properties": [{"name": String, "value": String, "color": {"R": Int,"G": Int,"B": Int,"A": Int}}] (can be null) 63 | } 64 | ] 65 | } 66 | ``` 67 | 68 | ## Future 69 | 70 | Since I don't use this project at the moment, it will evolve but slowly while I have fun coding it. 71 | -------------------------------------------------------------------------------- /assets/demo_ttme.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hfabre/ttme/dab25f381ed7a0da498c4d5cb1efae0b97648ea8/assets/demo_ttme.gif -------------------------------------------------------------------------------- /assets/example.json: -------------------------------------------------------------------------------- 1 | {"width":34,"height":27,"tileset":{"tileWidth":32,"tileHeight":32,"imagePath":"/home/hfabre/local/go/ttme/assets/tilesetpkm.png"},"tiles":[[{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null}],[{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null}],[{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null}],[{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null}],[{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null}],[{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null}],[{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null}],[{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null}],[{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null}],[{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null}],[{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null}],[{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":15,"properties":[{"name":"blocking","value":"true","color":{"R":0,"G":228,"B":48,"A":255}}]},{"index":15,"properties":[{"name":"blocking","value":"true","color":{"R":0,"G":228,"B":48,"A":255}}]},{"index":15,"properties":[{"name":"blocking","value":"true","color":{"R":0,"G":228,"B":48,"A":255}}]},{"index":15,"properties":[{"name":"blocking","value":"true","color":{"R":0,"G":228,"B":48,"A":255}}]},{"index":15,"properties":[{"name":"blocking","value":"true","color":{"R":0,"G":228,"B":48,"A":255}}]},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null}],[{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":15,"properties":null},{"index":15,"properties":[{"name":"other","value":"value","color":{"R":0,"G":9,"B":228,"A":255}}]},{"index":15,"properties":null},{"index":15,"properties":null},{"index":15,"properties":null},{"index":15,"properties":[{"name":"blocking","value":"true","color":{"R":0,"G":228,"B":48,"A":255}}]},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null}],[{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":15,"properties":null},{"index":15,"properties":[{"name":"other","value":"value","color":{"R":0,"G":9,"B":228,"A":255}}]},{"index":15,"properties":null},{"index":15,"properties":null},{"index":15,"properties":null},{"index":15,"properties":[{"name":"blocking","value":"true","color":{"R":0,"G":228,"B":48,"A":255}}]},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null}],[{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":15,"properties":null},{"index":15,"properties":[{"name":"other","value":"value","color":{"R":0,"G":9,"B":228,"A":255}}]},{"index":15,"properties":null},{"index":15,"properties":null},{"index":15,"properties":null},{"index":15,"properties":[{"name":"blocking","value":"true","color":{"R":0,"G":228,"B":48,"A":255}}]},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null}],[{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":15,"properties":null},{"index":15,"properties":[{"name":"other","value":"value","color":{"R":0,"G":9,"B":228,"A":255}}]},{"index":15,"properties":null},{"index":15,"properties":null},{"index":15,"properties":null},{"index":15,"properties":[{"name":"blocking","value":"true","color":{"R":0,"G":228,"B":48,"A":255}},{"name":"other","value":"value","color":{"R":0,"G":9,"B":228,"A":255}}]},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null}],[{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":15,"properties":null},{"index":15,"properties":[{"name":"other","value":"value","color":{"R":0,"G":9,"B":228,"A":255}}]},{"index":15,"properties":null},{"index":15,"properties":null},{"index":15,"properties":null},{"index":15,"properties":[{"name":"blocking","value":"true","color":{"R":0,"G":228,"B":48,"A":255}},{"name":"other","value":"value","color":{"R":0,"G":9,"B":228,"A":255}}]},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null}],[{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":15,"properties":null},{"index":15,"properties":null},{"index":15,"properties":[{"name":"other","value":"value","color":{"R":0,"G":9,"B":228,"A":255}}]},{"index":15,"properties":null},{"index":15,"properties":null},{"index":15,"properties":null},{"index":15,"properties":[{"name":"blocking","value":"true","color":{"R":0,"G":228,"B":48,"A":255}},{"name":"other","value":"value","color":{"R":0,"G":9,"B":228,"A":255}}]},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null}],[{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":15,"properties":null},{"index":15,"properties":[{"name":"other","value":"value","color":{"R":0,"G":9,"B":228,"A":255}}]},{"index":15,"properties":null},{"index":15,"properties":null},{"index":15,"properties":null},{"index":15,"properties":[{"name":"blocking","value":"true","color":{"R":0,"G":228,"B":48,"A":255}},{"name":"other","value":"value","color":{"R":0,"G":9,"B":228,"A":255}}]},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null}],[{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":15,"properties":[{"name":"other","value":"value","color":{"R":0,"G":9,"B":228,"A":255}}]},{"index":15,"properties":[{"name":"other","value":"value","color":{"R":0,"G":9,"B":228,"A":255}}]},{"index":15,"properties":[{"name":"other","value":"value","color":{"R":0,"G":9,"B":228,"A":255}}]},{"index":15,"properties":[{"name":"other","value":"value","color":{"R":0,"G":9,"B":228,"A":255}}]},{"index":15,"properties":[{"name":"blocking","value":"true","color":{"R":0,"G":228,"B":48,"A":255}},{"name":"other","value":"value","color":{"R":0,"G":9,"B":228,"A":255}}]},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null}],[{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null}],[{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null}],[{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null}],[{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null}],[{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null}],[{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null}],[{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null},{"index":-1,"properties":null}]]} -------------------------------------------------------------------------------- /assets/tilesetpkm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hfabre/ttme/dab25f381ed7a0da498c4d5cb1efae0b97648ea8/assets/tilesetpkm.png -------------------------------------------------------------------------------- /assets/ttme_layout.rgl: -------------------------------------------------------------------------------- 1 | # 2 | # rgl layout text file (v2.1) - raygui layout file generated using rGuiLayout 3 | # 4 | # Number of controls: 20 5 | # 6 | # Ref. window: r 7 | # Anchor info: a 8 | # Control info: c 9 | # 10 | r 0 0 -1 -1 11 | a 000 anchorMain 0 0 0 12 | a 001 anchor01 25 299 1 13 | a 002 anchor02 25 45 1 14 | a 003 anchor03 9 150 1 15 | a 004 anchor04 911 789 1 16 | a 005 anchor05 0 0 0 17 | a 006 anchor06 0 0 0 18 | a 007 anchor07 0 0 0 19 | c 000 21 ScrollPanel000 419 72 790 699 0 20 | c 001 5 Button001 926 810 125 30 0 SAMPLE TEXT 21 | c 002 5 Button002 1075 810 125 30 0 SAMPLE TEXT 22 | c 003 21 ScrollPanel003 30 174 369 96 0 23 | c 004 5 Button004 26 811 125 30 0 SAMPLE TEXT 24 | c 005 5 Button009 278 100 125 30 0 SAMPLE TEXT 25 | c 006 16 Spinner006 147 74 125 25 0 26 | c 007 16 Spinner007 147 106 125 25 0 27 | c 008 4 Label008 42 73 126 25 0 SAMPLE TEXT 28 | c 009 4 Label009 40 112 126 25 0 SAMPLE TEXT 29 | c 010 16 Spinner010 243 786 125 25 0 30 | c 011 16 Spinner011 243 816 125 25 0 31 | c 012 4 Label012 162 786 126 25 0 SAMPLE TEXT 32 | c 013 4 Label013 163 820 126 25 0 SAMPLE TEXT 33 | c 014 5 Button014 382 811 31 31 0 SAMPLE TEXT 34 | c 015 1 GroupBox015 -5 0 397 548 1 SAMPLE TEXT 35 | c 016 21 ScrollPanel016 0 8 387 470 1 36 | c 017 1 GroupBox017 0 0 387 101 2 SAMPLE TEXT 37 | c 018 1 GroupBox018 13 6 390 125 3 SAMPLE TEXT 38 | c 019 1 GroupBox019 0 0 302 58 4 SAMPLE TEXT 39 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module ttme 2 | 3 | go 1.13 4 | 5 | require ( 6 | github.com/TheTitanrain/w32 v0.0.0-20200114052255-2654d97dbd3d // indirect 7 | github.com/lachee/raylib-goplus v0.0.0-20200605081007-7ca39b8afc71 8 | github.com/sqweek/dialog v0.0.0-20200911184034-8a3d98e8211d 9 | ) 10 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/TheTitanrain/w32 v0.0.0-20180517000239-4f5cfb03fabf h1:FPsprx82rdrX2jiKyS17BH6IrTmUBYqZa/CXT4uvb+I= 2 | github.com/TheTitanrain/w32 v0.0.0-20180517000239-4f5cfb03fabf/go.mod h1:peYoMncQljjNS6tZwI9WVyQB3qZS6u79/N3mBOcnd3I= 3 | github.com/TheTitanrain/w32 v0.0.0-20200114052255-2654d97dbd3d h1:2xp1BQbqcDDaikHnASWpVZRjibOxu7y9LhAv04whugI= 4 | github.com/TheTitanrain/w32 v0.0.0-20200114052255-2654d97dbd3d/go.mod h1:peYoMncQljjNS6tZwI9WVyQB3qZS6u79/N3mBOcnd3I= 5 | github.com/lachee/raylib-goplus v0.0.0-20200605081007-7ca39b8afc71 h1:H4fcwldyU7pQvzyR3fuNLe0Gs3f7yLg/lH7NorUTc7I= 6 | github.com/lachee/raylib-goplus v0.0.0-20200605081007-7ca39b8afc71/go.mod h1:dBwvFApqhdnnQuWzvHZnvWph/zlTAHC3nd/Hy6yBE8U= 7 | github.com/sqweek/dialog v0.0.0-20200911184034-8a3d98e8211d h1:Chay1rwJnXxI27H+pzu7P81BKf647un9GOoRPTdXN18= 8 | github.com/sqweek/dialog v0.0.0-20200911184034-8a3d98e8211d/go.mod h1:/qNPSY91qTz/8TgHEMioAUc6q7+3SOybeKczHMXFcXw= 9 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/sqweek/dialog" 5 | "os" 6 | ttme "ttme/src" 7 | ) 8 | 9 | func main() { 10 | // TODO: bug with gtk3 11 | dialog.File().Load() 12 | 13 | fileToLoad := "" 14 | if len(os.Args) > 1 { 15 | fileToLoad = os.Args[1] 16 | } 17 | 18 | app := ttme.NewApp(1400, 900, "ttme") 19 | app.Start(fileToLoad) 20 | } 21 | -------------------------------------------------------------------------------- /src/app.go: -------------------------------------------------------------------------------- 1 | package ttme 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | r "github.com/lachee/raylib-goplus/raylib" 7 | "io/ioutil" 8 | "os" 9 | ) 10 | 11 | type app struct { 12 | width, height int 13 | name string 14 | mousePressed bool 15 | mousePosition r.Vector2 16 | rightMousePressed bool 17 | } 18 | 19 | func NewApp(width, height int, name string) *app { 20 | r.InitWindow(width, height, name) 21 | 22 | return &app{ 23 | width: width, 24 | height: height, 25 | name: name, 26 | mousePressed: false, 27 | mousePosition: r.NewVector2Zero(), 28 | rightMousePressed: false, 29 | } 30 | } 31 | 32 | func (a app) ShowInfo() { 33 | mousePosInfo := fmt.Sprintf("Mouse position: %f - %f", a.mousePosition.X, a.mousePosition.Y) 34 | mouseStateInfo := fmt.Sprintf("Mouse pressed: %v", a.mousePressed) 35 | 36 | r.DrawText(mousePosInfo, 10, 10, 10, r.Black) 37 | r.DrawText(mouseStateInfo, 10, 30, 10, r.Black) 38 | } 39 | 40 | func (a app) Init(ts *tileset, tsw *tilesetWidget, tm *tilemap, tmw *tilemapWidget, tscw *tilesetConfigurationWidget, tpw *tilePropertiesWidget, tmcw *tilemapConfigurationWidget, sw *showWidget) { 41 | *ts = *NewTileset(16, 16, "") 42 | *tsw = *NewTilesetWidget(30, 425, 370, 370, ts) 43 | *tm = *NewTilemap(50, 50, ts) 44 | *tmw = *NewTilemapWidget(420, 95, 800, 700, tm) 45 | *tscw = *NewTilesetConfigurationWidget(30, 750, ts) 46 | *tpw = *NewTilePropertiesWidget(25, 200) 47 | *tmcw = *NewTilemapConfigurationWidget(80, 100, tm) 48 | *sw = showWidget{x: 550, y: 800, showGrid: false, showProperties: true} 49 | } 50 | 51 | func (a app) InitFromFile(path string, ts *tileset, tsw *tilesetWidget, tm *tilemap, tmw *tilemapWidget, tscw *tilesetConfigurationWidget, tpw *tilePropertiesWidget, tmcw *tilemapConfigurationWidget, sw *showWidget) { 52 | file, err := os.Open(path) 53 | if err != nil { 54 | fmt.Println(err) 55 | os.Exit(-1) 56 | } 57 | defer file.Close() 58 | 59 | var loadedTm tilemap 60 | byteValue, _ := ioutil.ReadAll(file) 61 | json.Unmarshal(byteValue, &loadedTm) 62 | 63 | *tm = loadedTm 64 | tm.Tileset.LoadTexture() 65 | *ts = *tm.Tileset 66 | *tsw = *NewTilesetWidget(30, 425, 370, 370, ts) 67 | *tmw = *NewTilemapWidget(420, 95, 800, 700, tm) 68 | *tscw = *NewTilesetConfigurationWidget(30, 750, ts) 69 | *tpw = *NewTilePropertiesWidget(25, 200) 70 | *tmcw = *NewTilemapConfigurationWidget(80, 100, tm) 71 | *sw = showWidget{x: 550, y: 800, showGrid: false, showProperties: true} 72 | } 73 | 74 | func (a *app) Start(fileToLoad string) { 75 | tileset := tileset{} 76 | tilesetWidget := tilesetWidget{} 77 | tilemap := tilemap{} 78 | tilemapWidget := tilemapWidget{} 79 | tilsetConfigurationWidget := tilesetConfigurationWidget{} 80 | tilePropertiesWidget := tilePropertiesWidget{} 81 | tilemapConfigurationWidget := tilemapConfigurationWidget{} 82 | showWidget := showWidget{} 83 | mouseInTileMap := false 84 | 85 | // TODO: Not really proud of this way to init app state 86 | if len(fileToLoad) == 0 { 87 | a.Init(&tileset, &tilesetWidget, &tilemap, &tilemapWidget, &tilsetConfigurationWidget, &tilePropertiesWidget, &tilemapConfigurationWidget, &showWidget) 88 | } else { 89 | a.InitFromFile(fileToLoad, &tileset, &tilesetWidget, &tilemap, &tilemapWidget, &tilsetConfigurationWidget, &tilePropertiesWidget, &tilemapConfigurationWidget, &showWidget) 90 | } 91 | 92 | for !r.WindowShouldClose() { 93 | 94 | // Handle Mouse inputs 95 | 96 | a.mousePosition = r.GetMousePosition() 97 | 98 | if r.IsMouseButtonPressed(r.MouseLeftButton) { 99 | a.mousePressed = true 100 | 101 | if !tilePropertiesWidget.editMode && tilesetWidget.Contains(a.mousePosition.X, a.mousePosition.Y) { 102 | tilePropertiesWidget.Unset() 103 | tilesetWidget.SelectTile(a.mousePosition.X, a.mousePosition.Y) 104 | } 105 | } 106 | 107 | if r.IsMouseButtonReleased(r.MouseLeftButton) { 108 | a.mousePressed = false 109 | } 110 | 111 | if r.IsMouseButtonPressed(r.MouseRightButton) { 112 | a.rightMousePressed = true 113 | } 114 | 115 | if r.IsMouseButtonReleased(r.MouseRightButton) { 116 | a.rightMousePressed = false 117 | } 118 | 119 | // Handle tile pasting 120 | 121 | mouseInTileMap = tilemapWidget.Contains(a.mousePosition.X, a.mousePosition.Y) 122 | 123 | if a.mousePressed && mouseInTileMap { 124 | if tilePropertiesWidget.Selected() { 125 | tilemapWidget.SetTileFromPos(a.mousePosition.X, a.mousePosition.Y, tilesetWidget.selectedTile) 126 | } else { 127 | tilemapWidget.SetPropertyFromPos(a.mousePosition.X, a.mousePosition.Y, tilePropertiesWidget.SelectedProperty()) 128 | } 129 | } 130 | 131 | // Handle tile removing 132 | 133 | if a.rightMousePressed && tilemapWidget.Contains(a.mousePosition.X, a.mousePosition.Y) { 134 | tilemapWidget.SetTileFromPos(a.mousePosition.X, a.mousePosition.Y, tile{Index: -1}) 135 | } 136 | 137 | r.BeginDrawing() 138 | r.ClearBackground(r.RayWhite) 139 | tilemapWidget.Draw(showWidget.showProperties, showWidget.showGrid) 140 | showWidget.Draw() 141 | tilesetWidget.Draw() 142 | tilsetConfigurationWidget.Draw(&tilemapWidget) 143 | tilemapConfigurationWidget.Draw(&tilemapWidget) 144 | tilePropertiesWidget.Draw() 145 | 146 | //a.ShowInfo() 147 | 148 | // Debug 149 | //tilesetinfo := fmt.Sprintf("Tileset: %v - %v / %v", tileset.TileWidth, tileset.TileHeight, tileset.ImagePath) 150 | //tilemapinfo := fmt.Sprintf("Tilemap: %v - %v", tilemap.Width, tilemap.Height) 151 | 152 | if mouseInTileMap { 153 | mouseTilePosInfo := fmt.Sprintf("Tile position: %v - %v", tilemapWidget.GetTileXFromPos(a.mousePosition.X), tilemapWidget.GetTileYFromPos(a.mousePosition.Y)) 154 | r.DrawText(mouseTilePosInfo, 420, 803, 11, r.Black) 155 | } 156 | 157 | // Debug 158 | //r.DrawText(tilesetinfo, 10, 70, 10, r.Black) 159 | //r.DrawText(tilemapinfo, 10, 90, 10, r.Black) 160 | r.EndDrawing() 161 | } 162 | r.CloseWindow() 163 | } -------------------------------------------------------------------------------- /src/show_widget.go: -------------------------------------------------------------------------------- 1 | package ttme 2 | 3 | import r "github.com/lachee/raylib-goplus/raylib" 4 | 5 | type showWidget struct { 6 | showGrid, showProperties bool 7 | x, y int 8 | } 9 | 10 | func (sw *showWidget) Draw() { 11 | sw.showGrid = r.GuiCheckBox(r.Rectangle{X: float32(sw.x), Y: float32(sw.y), Width: 16, Height: 16}, "Show grid", sw.showGrid) 12 | sw.showProperties = r.GuiCheckBox(r.Rectangle{X: float32(sw.x) + 100, Y: float32(sw.y), Width: 16, Height: 16}, "Show properties", sw.showProperties) 13 | } 14 | -------------------------------------------------------------------------------- /src/tile.go: -------------------------------------------------------------------------------- 1 | package ttme 2 | 3 | import r "github.com/lachee/raylib-goplus/raylib" 4 | 5 | type tile struct { 6 | Index int `json:"index"` 7 | Properties []tileProperty `json:"properties"` 8 | } 9 | 10 | func (t tile) Index32() int32 { 11 | return int32(t.Index) 12 | } 13 | 14 | func (t tile) GetTilsetPosition(tileset tileset) (float32, float32) { 15 | tilesetWidth := tileset.TilesByLine() 16 | 17 | tileX := float32((t.Index32() % tilesetWidth) * int32(tileset.TileHeight)) 18 | tileY := float32((t.Index32() / tilesetWidth) * int32(tileset.TileHeight)) 19 | 20 | return tileX, tileY 21 | } 22 | 23 | func (t *tile) AddProperty(property tileProperty) { 24 | alreadyContains := false 25 | 26 | for i := 0; i < len(t.Properties); i++ { 27 | if t.Properties[i].Name == property.Name { 28 | alreadyContains = true 29 | } 30 | } 31 | 32 | if !alreadyContains { 33 | t.Properties = append(t.Properties, property) 34 | } 35 | } 36 | 37 | func (t tile) Draw(x, y int, tileset tileset, showProperties, showGrid bool) { 38 | if t.Index == -1 { 39 | r.DrawRectangle(x, y, tileset.TileWidth, tileset.TileHeight, r.Black) 40 | } else { 41 | x32 := float32(x) 42 | y32 := float32(y) 43 | 44 | tileX, tileY := t.GetTilsetPosition(tileset) 45 | 46 | pos := r.Vector2{X: x32, Y: y32} 47 | subRec := r.Rectangle{X: tileX, Y: tileY, Width: float32(tileset.TileWidth), Height: float32(tileset.TileHeight)} 48 | r.DrawTextureRec(tileset.texture, subRec, pos, r.White) 49 | 50 | if showProperties { 51 | switch len(t.Properties) { 52 | case 0: 53 | // Nothing to do 54 | case 1: 55 | r.DrawRectangle(x, y, tileset.TileWidth, tileset.TileHeight, t.PropertyColor(0)) 56 | case 2: 57 | w := tileset.TileWidth / 2 58 | r.DrawRectangle(x, y, w, tileset.TileHeight, t.PropertyColor(0)) 59 | r.DrawRectangle(x + w, y, w, tileset.TileHeight, t.PropertyColor(1)) 60 | case 3: 61 | w := tileset.TileWidth / 2 62 | h := tileset.TileHeight / 2 63 | r.DrawRectangle(x, y, w, h, t.PropertyColor(0)) 64 | r.DrawRectangle(x + w, y, w, h, t.PropertyColor(1)) 65 | r.DrawRectangle(x, y + h, tileset.TileWidth, h, t.PropertyColor(2)) 66 | case 4: 67 | w := tileset.TileWidth / 2 68 | h := tileset.TileHeight / 2 69 | r.DrawRectangle(x, y, w, h, t.PropertyColor(0)) 70 | r.DrawRectangle(x + w, y, w, h, t.PropertyColor(1)) 71 | r.DrawRectangle(x, y + h, w, h, t.PropertyColor(2)) 72 | r.DrawRectangle(x + w, y + h, w, h, t.PropertyColor(3)) 73 | default: 74 | // Find a way to handle (or block) more than 4 properties 75 | } 76 | } 77 | } 78 | 79 | if showGrid { 80 | r.DrawRectangleLines(x, y, tileset.TileWidth, tileset.TileHeight, r.Red) 81 | } 82 | } 83 | 84 | func (t tile) PropertyColor(propertyIndex int) r.Color { 85 | color := t.Properties[propertyIndex].Color 86 | return r.NewColor(color.R, color.G, color.B, 100) 87 | } 88 | -------------------------------------------------------------------------------- /src/tile_properties_widget.go: -------------------------------------------------------------------------------- 1 | package ttme 2 | 3 | import ( 4 | r "github.com/lachee/raylib-goplus/raylib" 5 | ) 6 | 7 | type tilePropertiesWidget struct { 8 | x, y int 9 | properties []tileProperty 10 | selectedProperty int 11 | editMode, propertyNameEditMode, propertyValueEditMode bool 12 | propertyName, propertyValue string 13 | propertyColor r.Color 14 | } 15 | 16 | func NewTilePropertiesWidget(x, y int) *tilePropertiesWidget { 17 | newWidget := tilePropertiesWidget{x: x, y: y} 18 | newWidget.properties = append(newWidget.properties, tileProperty{Name: "none"}) 19 | newWidget.properties = append(newWidget.properties, tileProperty{Name: "blocking", Value: "true", Color: r.Green}) 20 | newWidget.Reset() 21 | 22 | return &newWidget 23 | } 24 | 25 | func (tpw *tilePropertiesWidget) Draw() { 26 | editMode := tpw.editMode 27 | propertyNameEditMode := tpw.propertyNameEditMode 28 | propertyValueEditMode := tpw.propertyValueEditMode 29 | 30 | r.GuiLabel(r.Rectangle{X: float32(tpw.x), Y: float32(tpw.y + 40), Width: 40, Height: 20}, "Property name:") 31 | propertyNameEditMode, tpw.propertyName = r.GuiTextBox(r.Rectangle{X: float32(tpw.x + 90), Y: float32(tpw.y + 40), Width: 80, Height: 20}, tpw.propertyName, 50, tpw.propertyNameEditMode) 32 | 33 | r.GuiLabel(r.Rectangle{X: float32(tpw.x), Y: float32(tpw.y + 70), Width: 40, Height: 20}, "Property value:") 34 | propertyValueEditMode, tpw.propertyValue = r.GuiTextBox(r.Rectangle{X: float32(tpw.x + 90), Y: float32(tpw.y + 70), Width: 80, Height: 20}, tpw.propertyValue, 50, tpw.propertyValueEditMode) 35 | 36 | tpw.propertyColor = r.GuiColorPicker(r.Rectangle{X: float32(tpw.x), Y: float32(tpw.y + 100), Width: 100, Height: 100}, tpw.propertyColor) 37 | 38 | if (r.GuiButton(r.Rectangle{X: float32(tpw.x + 150), Y: float32(tpw.y) + 175, Width: 95, Height: 25}, "Create property")) { 39 | tpw.properties = append(tpw.properties, tileProperty{Name: tpw.propertyName, Value: tpw.propertyValue, Color: tpw.propertyColor}) 40 | tpw.Reset() 41 | } 42 | 43 | selectBounds := r.Rectangle{X: float32(tpw.x), Y: float32(tpw.y), Width: 200, Height: 20} 44 | editMode, tpw.selectedProperty = r.GuiDropdownBox(selectBounds, tpw.AsText(), tpw.selectedProperty, tpw.editMode) 45 | 46 | if editMode { 47 | tpw.editMode = !tpw.editMode 48 | } 49 | 50 | if propertyNameEditMode { 51 | tpw.propertyNameEditMode = !tpw.propertyNameEditMode 52 | } 53 | 54 | if propertyValueEditMode { 55 | tpw.propertyValueEditMode = !tpw.propertyValueEditMode 56 | } 57 | } 58 | 59 | func (tpw *tilePropertiesWidget) Reset() { 60 | tpw.selectedProperty = 0 61 | tpw.editMode = false 62 | tpw.propertyNameEditMode = false 63 | tpw.propertyValueEditMode = false 64 | tpw.propertyName = "" 65 | tpw.propertyValue = "" 66 | tpw.propertyColor = r.Green 67 | } 68 | 69 | func (tpw *tilePropertiesWidget) Unset() { 70 | tpw.selectedProperty = 0 71 | } 72 | 73 | func (tpw tilePropertiesWidget) SelectedProperty() tileProperty { 74 | return tpw.properties[tpw.selectedProperty] 75 | } 76 | 77 | func (tpw tilePropertiesWidget) Selected() bool { 78 | return tpw.selectedProperty == 0 79 | } 80 | 81 | func (tpw tilePropertiesWidget) AsText() string { 82 | text := "" 83 | 84 | for i := 0; i < len(tpw.properties); i++ { 85 | baseText := "" 86 | 87 | if i > 0 { 88 | baseText += ";" 89 | } 90 | 91 | text += baseText + tpw.properties[i].Name 92 | } 93 | 94 | return text 95 | } 96 | -------------------------------------------------------------------------------- /src/tile_property.go: -------------------------------------------------------------------------------- 1 | package ttme 2 | 3 | import r "github.com/lachee/raylib-goplus/raylib" 4 | 5 | type tileProperty struct { 6 | Name string `json:"name"` 7 | Value string `json:"value"` 8 | Color r.Color `json:"color"` 9 | } -------------------------------------------------------------------------------- /src/tilemap.go: -------------------------------------------------------------------------------- 1 | package ttme 2 | 3 | type tilemap struct { 4 | Width int `json:"width"` // in tile 5 | Height int `json:"height"` //in tile 6 | Tileset *tileset `json:"tileset"` 7 | Tiles [][]tile `json:"tiles"` 8 | // actions (Array (custom tiles action) [name, color, attributes(json)]) 9 | } 10 | 11 | func NewTilemap(width, height int, tileset *tileset) *tilemap { 12 | newTilemap := tilemap{Width: width, Height: height, Tileset: tileset} 13 | newTilemap.FillEmptyBoard() 14 | 15 | return &newTilemap 16 | } 17 | 18 | func (tm *tilemap) ChangeSize(width, height int) { 19 | tm.Width = width 20 | tm.Height = height 21 | newBoard := make([][]tile, tm.Height) 22 | 23 | for y := 0; y < tm.Height; y++ { 24 | newBoard[y] = make([]tile, tm.Width) 25 | 26 | for x := 0; x < tm.Width; x++ { 27 | if y < len(tm.Tiles) && x < len(tm.Tiles[y]) { 28 | newBoard[y][x] = tm.Tiles[y][x] 29 | } else { 30 | newBoard[y][x] = tile{Index: -1} 31 | } 32 | } 33 | } 34 | 35 | tm.Tiles = newBoard 36 | } 37 | 38 | func (tm *tilemap) FillEmptyBoard() { 39 | tm.Tiles = make([][]tile, tm.Height) 40 | for y := 0; y < tm.Height; y++ { 41 | tm.Tiles[y] = make([]tile, tm.Width) 42 | for x := 0; x < tm.Width; x++ { 43 | tm.Tiles[y][x] = tile{Index: -1} 44 | } 45 | } 46 | } 47 | 48 | func (tm tilemap) Draw(showProperties, showGrid bool) { 49 | for y := 0; y < tm.Height; y++ { 50 | for x := 0; x < tm.Width; x++ { 51 | tm.Tiles[y][x].Draw(x * tm.Tileset.TileWidth, y * tm.Tileset.TileHeight, *tm.Tileset, showProperties, showGrid) 52 | } 53 | } 54 | } 55 | 56 | func (tm tilemap) PixelWidth() int { 57 | return tm.Width * tm.Tileset.TileWidth 58 | } 59 | 60 | func (tm tilemap) PixelHeight() int { 61 | return tm.Height * tm.Tileset.TileHeight 62 | } -------------------------------------------------------------------------------- /src/tilemap_configuration_widget.go: -------------------------------------------------------------------------------- 1 | package ttme 2 | 3 | import r "github.com/lachee/raylib-goplus/raylib" 4 | 5 | type tilemapConfigurationWidget struct { 6 | x, y int 7 | tilemap *tilemap 8 | mapWidth, mapHeight int 9 | mapWidthBoxEditMode, mapHeightBoxEditMode bool 10 | } 11 | 12 | func NewTilemapConfigurationWidget(x, y int, tilemap *tilemap) *tilemapConfigurationWidget { 13 | newWidget := tilemapConfigurationWidget{x: x, y: y, tilemap: tilemap, mapWidth: tilemap.Width, mapHeight: tilemap.Height} 14 | newWidget.mapWidthBoxEditMode = false 15 | newWidget.mapHeightBoxEditMode = false 16 | 17 | return &newWidget 18 | } 19 | 20 | // TODO: implement a messaging system to avoid passing other widget ? 21 | func (tmcw *tilemapConfigurationWidget) Draw(widget *tilemapWidget) { 22 | tmcw.mapWidthBoxEditMode, tmcw.mapWidth = r.GuiSpinner(r.Rectangle{X: float32(tmcw.x), Y: float32(tmcw.y), Width: 125, Height: 25}, "Map width: ", tmcw.mapWidth, 1, 124, tmcw.mapWidthBoxEditMode) 23 | tmcw.mapHeightBoxEditMode, tmcw.mapHeight = r.GuiSpinner(r.Rectangle{X: float32(tmcw.x), Y: float32(tmcw.y) + 30, Width: 125, Height: 25}, "Map height: ", tmcw.mapHeight, 1, 124, tmcw.mapHeightBoxEditMode) 24 | 25 | if (r.GuiButton(r.Rectangle{X: float32(tmcw.x) + 140, Y: float32(tmcw.y) + 30, Width: 50, Height: 25}, "Save")) { 26 | tmcw.tilemap.ChangeSize(tmcw.mapWidth, tmcw.mapHeight) 27 | widget.Update() 28 | } 29 | } -------------------------------------------------------------------------------- /src/tilemap_widget.go: -------------------------------------------------------------------------------- 1 | package ttme 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | r "github.com/lachee/raylib-goplus/raylib" 7 | "github.com/sqweek/dialog" 8 | "io/ioutil" 9 | ) 10 | 11 | type tilemapWidget struct { 12 | x, y, width, height int 13 | tilemap *tilemap 14 | panelScroll r.Vector2 15 | targetTexture r.RenderTexture2D 16 | view r.Rectangle 17 | } 18 | 19 | func NewTilemapWidget(x, y, width, height int, tilemap *tilemap) *tilemapWidget { 20 | newWidget := tilemapWidget{x: x, y: y, tilemap: tilemap} 21 | newWidget.width = width 22 | newWidget.height = height 23 | newWidget.panelScroll = r.Vector2{X: 0, Y: 0} 24 | newWidget.targetTexture = r.LoadRenderTexture(tilemap.PixelWidth(), tilemap.PixelHeight()) 25 | 26 | return &newWidget 27 | } 28 | 29 | func (tmw *tilemapWidget) Update() { 30 | r.UnloadRenderTexture(tmw.targetTexture) 31 | tmw.targetTexture = r.LoadRenderTexture(tmw.tilemap.PixelWidth(), tmw.tilemap.PixelHeight()) 32 | } 33 | 34 | func (tmw *tilemapWidget) Draw(showProperties, showGrid bool) { 35 | content := r.Rectangle{X: 0, Y: 0, Width: float32(tmw.tilemap.PixelWidth()), Height: float32(tmw.tilemap.PixelHeight())} 36 | tmw.view, tmw.panelScroll = r.GuiScrollPanel(tmw.Bounds(), content, tmw.panelScroll) 37 | 38 | r.BeginTextureMode(tmw.targetTexture) 39 | tmw.tilemap.Draw(showProperties, showGrid) 40 | r.EndTextureMode() 41 | 42 | // Note: We have to take back one because scroll offset starts at one 43 | verticalOffset := tmw.tilemap.PixelHeight() - int(tmw.view.Height) - 1 44 | 45 | // Note: Since we vertically invert texture we need to invert scroll (Y) as well, 46 | mapView := r.Rectangle{X: -(tmw.panelScroll.X - 1), Y: tmw.panelScroll.Y + float32(verticalOffset), Width: tmw.view.Width, Height: -tmw.view.Height} 47 | r.DrawTextureRec(tmw.targetTexture.Texture, mapView, r.Vector2{X: float32(tmw.x), Y: float32(tmw.y)}, r.White) 48 | 49 | if r.GuiButton(r.Rectangle{X: float32(tmw.x + tmw.width - 90), Y: float32(tmw.y + tmw.height + 10), Width: 90, Height: 25}, "Export to JSON") { 50 | path, _ := dialog.File().Filter("JSON files", "json").Title("Export to JSON").Save() 51 | file, _ := json.Marshal(*tmw.tilemap) 52 | _ = ioutil.WriteFile(path, file, 0644) 53 | } 54 | } 55 | 56 | func (tmw tilemapWidget) Contains(x, y float32) bool { 57 | point := r.Vector2{x, y} 58 | 59 | return r.CheckCollisionPointRec(point, tmw.view) 60 | } 61 | 62 | func (tmw *tilemapWidget) SetTile(x, y int, tile tile) { 63 | tmw.tilemap.Tiles[y][x] = tile 64 | } 65 | 66 | func (tmw tilemapWidget) GetTileXFromPos(x float32) int { 67 | return int((x - tmw.view.X - tmw.panelScroll.X) / float32(tmw.tilemap.Tileset.TileWidth)) 68 | } 69 | 70 | func (tmw tilemapWidget) GetTileYFromPos(y float32) int { 71 | return int((y - tmw.view.Y - tmw.panelScroll.Y) / float32(tmw.tilemap.Tileset.TileHeight)) 72 | } 73 | 74 | // Note: panelScroll Offset 75 | func (tmw *tilemapWidget) SetTileFromPos(x, y float32, tile tile) { 76 | tileX := tmw.GetTileXFromPos(x) 77 | tileY := tmw.GetTileYFromPos(y) 78 | 79 | tmw.SetTile(int(tileX), int(tileY), tile) 80 | } 81 | 82 | func (tmw *tilemapWidget) SetTileProperty(x, y int, property tileProperty) { 83 | tmw.tilemap.Tiles[y][x].AddProperty(property) 84 | } 85 | 86 | // Note: panelScroll Offset 87 | func (tmw *tilemapWidget) SetPropertyFromPos(x, y float32, property tileProperty) { 88 | tileX := (x - tmw.view.X - tmw.panelScroll.X) / float32(tmw.tilemap.Tileset.TileWidth) 89 | tileY := (y - tmw.view.Y - tmw.panelScroll.Y) / float32(tmw.tilemap.Tileset.TileHeight) 90 | 91 | tmw.SetTileProperty(int(tileX), int(tileY), property) 92 | } 93 | 94 | func (tmw tilemapWidget) ShowInfo() { 95 | scrollInfo := fmt.Sprintf("Scroll state: %f - %f", tmw.panelScroll.X, tmw.panelScroll.Y) 96 | viewInfo := fmt.Sprintf("View rect: %f - %f - %f - %f", tmw.view.X, tmw.view.Y, tmw.view.Width, tmw.view.Height) 97 | mapInfo := fmt.Sprintf("Map size: %d - %d", tmw.tilemap.PixelWidth(), tmw.tilemap.PixelHeight()) 98 | 99 | r.DrawText(scrollInfo, tmw.x + 10, tmw.y + 10, 10, r.Gray) 100 | r.DrawText(viewInfo, tmw.x + 10, tmw.y + 30, 10, r.Gray) 101 | r.DrawText(mapInfo, tmw.x + 10, tmw.y + 50, 10, r.Gray) 102 | } 103 | 104 | func (tmw tilemapWidget) Bounds() r.Rectangle { 105 | return r.Rectangle{X: float32(tmw.x), Y: float32(tmw.y), Width: float32(tmw.width), Height: float32(tmw.height)} 106 | } 107 | -------------------------------------------------------------------------------- /src/tileset.go: -------------------------------------------------------------------------------- 1 | package ttme 2 | 3 | import r "github.com/lachee/raylib-goplus/raylib" 4 | 5 | type tileset struct { 6 | TileWidth int `json:"tileWidth"` // in pixel 7 | TileHeight int `json:"tileHeight"` // in pixel 8 | ImagePath string `json:"imagePath"` 9 | texture r.Texture2D 10 | loaded, needsRedraw bool 11 | } 12 | 13 | func NewTileset(tileWidth, tileHeight int, imagePath string) *tileset { 14 | newTileset := tileset{TileWidth: tileWidth, TileHeight: tileHeight, ImagePath: imagePath} 15 | 16 | if len(newTileset.ImagePath) > 0 { 17 | newTileset.LoadTexture() 18 | } 19 | 20 | return &newTileset 21 | } 22 | 23 | func (t *tileset) LoadTexture() { 24 | t.texture = r.LoadTexture(t.ImagePath) 25 | t.loaded = true 26 | } 27 | 28 | func (t *tileset) ChangeImage(imagePath string) { 29 | r.UnloadTexture(t.texture) 30 | t.loaded = false 31 | t.ImagePath = imagePath 32 | t.LoadTexture() 33 | } 34 | 35 | func (t tileset) PixelWidth() int { 36 | return int(t.texture.Width) 37 | } 38 | 39 | func (t tileset) PixelHeight() int { 40 | return int(t.texture.Height) 41 | } 42 | 43 | func (t tileset) TilesByLine() int32 { 44 | return t.texture.Width / int32(t.TileWidth) 45 | } 46 | 47 | func (t tileset) Draw() { 48 | r.DrawTexture(t.texture, 0, 0, r.White) 49 | } 50 | -------------------------------------------------------------------------------- /src/tileset_configuration_widget.go: -------------------------------------------------------------------------------- 1 | package ttme 2 | 3 | import r "github.com/lachee/raylib-goplus/raylib" 4 | import "github.com/sqweek/dialog" 5 | 6 | type tilesetConfigurationWidget struct { 7 | x, y int 8 | tileset *tileset 9 | tileWidth, tileHeight int 10 | tileWidthBoxEditMode, tileHeightBoxEditMode bool 11 | newTilsesetPath string 12 | } 13 | 14 | func NewTilesetConfigurationWidget(x, y int, tileset *tileset) *tilesetConfigurationWidget { 15 | newWidget := tilesetConfigurationWidget{x: x, y: y, tileset: tileset} 16 | newWidget.tileWidth = tileset.TileWidth 17 | newWidget.tileHeight = tileset.TileHeight 18 | newWidget.tileWidthBoxEditMode = false 19 | newWidget.tileHeightBoxEditMode = false 20 | newWidget.newTilsesetPath = "" 21 | 22 | return &newWidget 23 | } 24 | 25 | // TODO: implement a messaging system to avoid passing other widget ? 26 | func (tscw *tilesetConfigurationWidget) Draw(widget *tilemapWidget) { 27 | if (r.GuiButton(r.Rectangle{X: float32(tscw.x), Y: float32(tscw.y) + 50, Width: 75, Height: 25}, "Select tileset")) { 28 | tscw.newTilsesetPath, _ = dialog.File().Load() 29 | tscw.tileset.ChangeImage(tscw.newTilsesetPath) 30 | tscw.newTilsesetPath = "" 31 | tscw.tileset.needsRedraw = true 32 | } 33 | 34 | tscw.tileWidthBoxEditMode, tscw.tileWidth = r.GuiSpinner(r.Rectangle{X: float32(tscw.x) + 180, Y: float32(tscw.y) + 50, Width: 125, Height: 25}, "Tile width: ", tscw.tileWidth, 1, 124, tscw.tileWidthBoxEditMode) 35 | tscw.tileHeightBoxEditMode, tscw.tileHeight = r.GuiSpinner(r.Rectangle{X: float32(tscw.x) + 180, Y: float32(tscw.y) + 80, Width: 125, Height: 25}, "Tile height: ", tscw.tileHeight, 1, 124, tscw.tileHeightBoxEditMode) 36 | 37 | if (r.GuiButton(r.Rectangle{X: float32(tscw.x) + 320, Y: float32(tscw.y) + 80, Width: 50, Height: 25}, "Save")) { 38 | tscw.tileset.TileWidth = tscw.tileWidth 39 | tscw.tileset.TileHeight = tscw.tileHeight 40 | 41 | widget.Update() 42 | } 43 | } -------------------------------------------------------------------------------- /src/tileset_widget.go: -------------------------------------------------------------------------------- 1 | package ttme 2 | 3 | import ( 4 | "fmt" 5 | r "github.com/lachee/raylib-goplus/raylib" 6 | ) 7 | 8 | type tilesetWidget struct { 9 | x, y, width, height int 10 | tileset *tileset 11 | panelScroll r.Vector2 12 | targetTexture r.RenderTexture2D 13 | view r.Rectangle 14 | selectedTile tile 15 | } 16 | 17 | func NewTilesetWidget(x, y, width, height int, tileset *tileset) *tilesetWidget { 18 | newWidget := tilesetWidget{x: x, y: y, tileset: tileset} 19 | newWidget.width = width 20 | newWidget.height = height 21 | newWidget.panelScroll = r.Vector2{X: 0, Y: 0} 22 | newWidget.selectedTile = tile{Index: -1} 23 | newWidget.ResetRenderTexture() 24 | 25 | return &newWidget 26 | } 27 | 28 | func (tsw *tilesetWidget) ResetRenderTexture() { 29 | tsw.targetTexture = r.LoadRenderTexture(tsw.tileset.PixelWidth(), tsw.tileset.PixelHeight()) 30 | } 31 | 32 | func (tsw *tilesetWidget) SelectTile(x, y float32) { 33 | tileX := (x - float32(tsw.x) - tsw.panelScroll.X) / float32(tsw.tileset.TileWidth) 34 | tileY := (y - float32(tsw.y) - tsw.panelScroll.Y) / float32(tsw.tileset.TileHeight) 35 | tilePos := int32(tileY) * tsw.tileset.TilesByLine() + int32(tileX) 36 | 37 | tsw.selectedTile = tile{Index: int(tilePos)} 38 | } 39 | 40 | func (tsw tilesetWidget) Contains(x, y float32) bool { 41 | point := r.Vector2{X: x, Y: y} 42 | 43 | return r.CheckCollisionPointRec(point, tsw.view) 44 | } 45 | 46 | func (tsw *tilesetWidget) Draw() { 47 | if !tsw.tileset.loaded { 48 | return 49 | } 50 | 51 | // TODO: I don't like the way i'm handling this 52 | if tsw.tileset.needsRedraw { 53 | tsw.ResetRenderTexture() 54 | tsw.tileset.needsRedraw = false 55 | } 56 | 57 | content := r.Rectangle{X: 0, Y: 0, Width: float32(tsw.tileset.PixelWidth()), Height: float32(tsw.tileset.PixelHeight())} 58 | tsw.view, tsw.panelScroll = r.GuiScrollPanel(tsw.Bounds(), content, tsw.panelScroll) 59 | tileX, tileY := tsw.selectedTile.GetTilsetPosition(*tsw.tileset) 60 | 61 | r.BeginTextureMode(tsw.targetTexture) 62 | tsw.tileset.Draw() 63 | r.DrawRectangleLines(int(tileX), int(tileY), tsw.tileset.TileWidth, tsw.tileset.TileHeight, r.Red) 64 | r.EndTextureMode() 65 | 66 | // Note: We have to take back one because scroll offset starts at one 67 | verticalOffset := tsw.tileset.PixelHeight() - int(tsw.view.Height) - 1 68 | 69 | // Note: Since we vertically invert texture we need to invert scroll (Y) as well, 70 | mapView := r.Rectangle{X: -(tsw.panelScroll.X - 1), Y: tsw.panelScroll.Y + float32(verticalOffset), Width: tsw.view.Width, Height: -tsw.view.Height} 71 | r.DrawTextureRec(tsw.targetTexture.Texture, mapView, r.Vector2{X: float32(tsw.x), Y: float32(tsw.y)}, r.White) 72 | } 73 | 74 | func (tsw tilesetWidget) ShowInfo() { 75 | scrollInfo := fmt.Sprintf("Scroll state: %f - %f", tsw.panelScroll.X, tsw.panelScroll.Y) 76 | viewInfo := fmt.Sprintf("View rect: %f - %f - %f - %f", tsw.view.X, tsw.view.Y, tsw.view.Width, tsw.view.Height) 77 | mapInfo := fmt.Sprintf("set size: %d - %d", tsw.tileset.PixelWidth(), tsw.tileset.PixelHeight()) 78 | selectedTileInfo := fmt.Sprintf("Selected tile: %v", tsw.selectedTile.Index) 79 | 80 | r.DrawText(scrollInfo, tsw.x + 10, tsw.y + 10, 14, r.Red) 81 | r.DrawText(viewInfo, tsw.x + 10, tsw.y + 30, 14, r.Red) 82 | r.DrawText(mapInfo, tsw.x + 10, tsw.y + 50, 14, r.Red) 83 | r.DrawText(selectedTileInfo, tsw.x + 10, tsw.y + 70, 14, r.Red) 84 | } 85 | 86 | func (tsw tilesetWidget) Bounds() r.Rectangle { 87 | return r.Rectangle{X: float32(tsw.x), Y: float32(tsw.y), Width: float32(tsw.width), Height: float32(tsw.height)} 88 | } 89 | --------------------------------------------------------------------------------