Compare commits

..

162 Commits

Author SHA1 Message Date
Dominik Madarász 2d593809d7 move queries 2024-05-29 17:50:42 +02:00
Dominik Madarász 23645ed32a move ASSET_MOB to survival game 2024-05-29 11:18:48 +02:00
Dominik Madarász 29d9b9306d drop lists dir 2024-05-29 11:10:44 +02:00
Dominik Madarász 6e09c09037 style 2024-05-29 10:58:16 +02:00
Dominik Madarász b348400c1a streamline assets= 2024-05-29 10:45:43 +02:00
Dominik Madarász a9ea1e9335 sqlite db 2024-05-29 10:11:37 +02:00
Dominik Madarász e2e6ef9185 Update README.md 2023-09-16 06:57:33 +00:00
Dominik Madarász 3fba1bc1d4 collision grid + perf improvements 2023-07-27 11:53:35 +02:00
Dominik Madarász e43b167435 rename prj 2023-07-26 19:08:34 +02:00
Dominik Madarász a9efa0f01c big chungus 2023-07-26 19:05:50 +02:00
Dominik Madarász 213710e922 mob spawner + friendly fire 2023-07-26 14:53:50 +02:00
Dominik Madarász d864661e65 render mobs via spritesheet + blood splatters 2023-07-25 22:18:19 +02:00
Dominik Madarász 9c669407fc fix long-standing web build time related bug 2023-07-25 21:23:41 +02:00
Dominik Madarász a1d576fe8a update flecs 2023-06-30 15:14:47 +02:00
Dominik Madarász 200d0a1e6d remove flecs-dash 2023-06-30 15:04:20 +02:00
Dominik Madarász 00f0a672f8 optimize IntegratePositions system to avoid comp fetch + update flecs v3.2.3 2023-06-07 09:52:08 +02:00
Dominik Madarász 4a07e4ff4c allow entities to override stream layer 2023-02-28 09:11:33 +01:00
Dominik Madarász c022b104d0 drop world_component_cache 2023-02-28 09:11:27 +01:00
Dominik Madarász a9898527ee dropped component caching
This was fixed in flecs already
2023-02-13 10:31:08 +01:00
Dominik Madarász e302d1c865 bunch of code quality fixes 2023-02-10 06:42:30 +01:00
Dominik Madarász eccaa14bda improve player init 2023-02-03 11:22:15 +01:00
Dominik Madarász 94c49e770b add pkt_send_code + system changes 2023-02-03 09:54:16 +01:00
Dominik Madarász 3e4814222e improve force feedback 2023-02-03 07:31:36 +01:00
Dominik Madarász 410d6e5f11 set up dmg system for mobs 2023-02-03 07:28:17 +01:00
DavoSK cf200e8bf5 weapon hit system 2023-02-02 22:01:03 +01:00
DavoSK ea9b201a08 proper pos offset 2023-02-02 19:22:12 +01:00
DavoSK c21cb39140 implemented angles in sprite rendering, knifes has proper rotation based from direction of player 2023-02-02 18:59:49 +01:00
DavoSK 3a9196d19a adjust starting pos of projectile based on direction 2023-02-02 18:52:11 +01:00
DavoSK 98b9f3431e random offseting of knifes 2023-02-02 17:49:29 +01:00
Dominik Madarász d15e7da7cc again 2023-02-02 17:29:39 +01:00
DavoSK 7356168b6f player is shooting knifes now 2023-02-02 17:28:15 +01:00
DavoSK 1631e9199b Merge branch 'master' of https://github.com/zpl-c/eco2d 2023-02-02 17:27:17 +01:00
Dominik Madarász 7ed35706fc fix heading dir 2023-02-02 17:26:33 +01:00
DavoSK e89cd75388 Merge branch 'master' of https://github.com/zpl-c/eco2d 2023-02-02 17:23:21 +01:00
DavoSK f89b35a856 Merge branch 'master' of https://github.com/zpl-c/eco2d 2023-02-02 17:22:07 +01:00
Dominik Madarász 8c288dc193 add heading dir to input 2023-02-02 17:22:05 +01:00
Dominik Madarász fc9997d4db Add rotation component 2023-02-02 16:58:20 +01:00
DavoSK 5473ca3c46 Merge branch 'master' of https://github.com/zpl-c/eco2d 2023-02-02 16:55:51 +01:00
DavoSK 698d3d2089 projectile work 2023-02-02 16:55:49 +01:00
Dominik Madarász 78c05fd9da Add collision masking tags 2023-02-02 16:54:32 +01:00
DavoSK f6d5c76d1b Merge branch 'master' of https://github.com/zpl-c/eco2d 2023-02-02 16:21:12 +01:00
Dominik Madarász e8934ac2f3 improve sprite data 2023-02-02 16:20:55 +01:00
DavoSK 755f7e7a86 Merge branch 'master' of https://github.com/zpl-c/eco2d 2023-02-02 15:43:56 +01:00
DavoSK 1f451f10be added weapon knife system 2023-02-02 15:41:16 +01:00
Dominik Madarász 91f005b4bb Add support for sprite rendering 2023-02-02 15:40:48 +01:00
Dominik Madarász 11549eb324 send notification from server 2023-02-02 14:17:53 +01:00
Dominik Madarász 65766d8748 small refactor of game layer 2023-02-02 13:24:16 +01:00
Dominik Madarász 0760d1809d sprite animation finished 2023-02-02 12:38:45 +01:00
Dominik Madarász 6e6243e9df spritesheet viewer + update flecs 2023-02-02 12:26:01 +01:00
Dominik Madarász 89fea143d3 remove dbg 2023-02-01 17:28:02 +01:00
Dominik Madarász 5aa90fc5af fix mem leak and improve spritesheet explorer 2023-02-01 17:26:52 +01:00
DavoSK bdd43143f8 implemented simple spritesheet 2023-02-01 17:10:16 +01:00
Dominik Madarász f35c9b8a1c unsigned fix 2023-02-01 15:49:13 +01:00
Dominik Madarász 6e0e747756 Merge remote-tracking branch 'origin/master' 2023-02-01 15:42:25 +01:00
DavoSK b578ceffef fix casts and make function non inlined (clang fix) 2023-02-01 15:39:51 +01:00
Dominik Madarász 3f5d999d44 survival game wip 2023-02-01 15:28:30 +01:00
Dominik Madarász 719b002989 physics impl part 2 2023-01-31 23:51:39 +01:00
Dominik Madarász 4d1a90d5cb physics impl part 1 2023-01-31 18:41:01 +01:00
Dominik Madarász 36a4a010c8 simplify prefabs 2023-01-23 15:56:02 +01:00
Dominik Madarász 1c68c73028 basic ai demo 2023-01-23 11:51:12 +01:00
Dominik Madarász 4fd2856a25 emscripten windows build scripts 2023-01-23 01:12:17 +01:00
Dominik Madarász 391106417b fix unused-but-set-variable 2023-01-23 01:02:03 +01:00
Dominik Madarász a31f4f6f25 fix web build 2023-01-23 00:58:07 +01:00
Dominik Madarász 3174b8a3c3 item router fix rolling counter 2023-01-17 10:47:16 +01:00
Dominik Madarász 267a60af32 custom UI style 2023-01-16 16:37:26 +01:00
Dominik Madarász 0e614b53a5 improve tooltip search 2023-01-16 15:46:51 +01:00
Dominik Madarász d0edc058eb tooltip search bar 2023-01-16 15:21:55 +01:00
Dominik Madarász 3165d21f2b fix padding 2023-01-16 14:45:14 +01:00
Dominik Madarász 701c15fde1 improve spacing 2023-01-16 14:23:12 +01:00
Dominik Madarász 82a8bbdaf8 wip notifications + manager 2023-01-16 14:05:15 +01:00
Dominik Madarász 847289c6de improve layouting 2023-01-16 13:23:41 +01:00
Dominik Madarász 341040abc2 embedded tooltips 2023-01-16 13:11:27 +01:00
Dominik Madarász b9e29dd7ab improve tooltips 2023-01-16 10:02:58 +01:00
Dominik Madarász c8b21e86b5 tooltip feature 2023-01-16 09:51:57 +01:00
Dominik Madarász 31cf65ad50 disable tooltip scrollbar 2023-01-15 20:42:15 +01:00
Dominik Madarász ba78e5360e add crafting tooltip 2023-01-15 20:21:56 +01:00
Dominik Madarász f24ab7dc04 prep game ui nuklear ctx 2023-01-15 19:12:28 +01:00
Dominik Madarász d51d88002d recipe filtering in crafting list 2023-01-15 18:43:03 +01:00
Dominik Madarász 553afd44d0 entity inspector addition 2023-01-15 17:44:48 +01:00
Dominik Madarász 72005402cf nuklear dev ui + asset inspector tool 2023-01-15 16:59:33 +01:00
Dominik Madarász d00ce4ec80
update flecs 2023-01-14 09:46:19 +00:00
Dominik Madarász f0ccac8e0c ecs: rework crafting to tick-based process 2023-01-14 10:24:57 +01:00
Dominik Madarász e15cdab4ff input system 2022-10-26 09:04:17 +02:00
Vladyslav Hrytsenko 4ae83ebdbb art: updated textures 2022-10-23 13:07:32 +03:00
Dominik Madarász a3a75af9b5 finish up crafting system v0 2022-10-18 19:59:35 +02:00
Vladyslav Hrytsenko 4c778d24ec art: added assembler texture 2022-10-18 20:44:10 +03:00
Dominik Madarász 5e8e760098 wip crafting ui 2022-10-18 19:37:56 +02:00
Dominik Madarász 7ecc5cd0d7 wip craft system automation improvements 2022-10-18 12:37:55 +02:00
Vladyslav Hrytsenko 80d8620ee1 art: added item plitter 2022-10-18 12:31:06 +03:00
Dominik Madarász d3e1f595e5 small recipe changes 2022-10-18 11:29:27 +02:00
Vladyslav Hrytsenko 8eec4ac470 art: updated textures 2022-10-18 11:00:19 +03:00
Dominik Madarász ee7ff6a6c3 add new items 2022-10-18 09:32:25 +02:00
Dominik Madarász f99cbc8018 Merge remote-tracking branch 'origin/master' 2022-10-18 09:22:26 +02:00
Dominik Madarász 3a008427f6 small asset ids changes 2022-10-18 09:22:11 +02:00
Vladyslav Hrytsenko 0740d0a85b art: added new textures 2022-10-18 10:13:47 +03:00
Dominik Madarász 9e368527a3 new crafting system 2022-10-18 08:57:43 +02:00
Dominik Madarász 70bb456a43 Merge remote-tracking branch 'origin/master' 2022-10-17 20:46:03 +02:00
Dominik Madarász 3d104313f8 remove typo leftover 2022-10-17 20:45:58 +02:00
Dominik Madarász e732949856
Create web-build.yml 2022-10-17 20:23:56 +02:00
Dominik Madarász 339bb56dc7 variable tick rate support 2022-10-17 20:09:30 +02:00
Dominik Madarász 4cb85f069f ItemRouter system 2022-10-17 19:44:28 +02:00
Dominik Madarász 6385ea4461 producer supports output node push 2022-10-17 18:28:40 +02:00
Dominik Madarász 3f6235e8a4 disable vsync again 2022-10-17 18:28:18 +02:00
Dominik Madarász 0d58d5f315 update 4coder stuff 2022-10-17 11:52:38 +02:00
Dominik Madarász 06f408f09f add one-shoot web win script 2022-10-17 11:06:42 +02:00
Dominik Madarász 20d35ad653 push water tex 2022-10-16 15:31:07 +02:00
Dominik Madarász 79caba208f fix producer item count again 2022-10-16 15:01:14 +02:00
Dominik Madarász 437aea7df5 tweak item list 2022-10-16 14:38:48 +02:00
Dominik Madarász 0f12724700 fix producer creating extra item 2022-10-16 14:35:10 +02:00
Dominik Madarász 3f30bb5079 fix underlying comp cache issue 2022-10-16 14:27:56 +02:00
Dominik Madarász ec6d489526 dont ask 2022-10-16 13:13:36 +02:00
Dominik Madarász bdd774fd50 enable vsync on desktop 2022-10-16 13:13:04 +02:00
Dominik Madarász 746ec9b00d enable vsync on desktop 2022-10-16 13:12:52 +02:00
Dominik Madarász 143bf1bffa dont show item proxies in item spawner 2022-10-16 13:10:21 +02:00
Dominik Madarász a824731a15 reorg texgen fallback 2022-10-16 13:02:35 +02:00
Dominik Madarász 93612f5462 improve blueprints 2022-10-16 13:00:50 +02:00
Dominik Madarász 71dc349e4e optimize world_view mapping alloc 2022-10-16 12:35:23 +02:00
Dominik Madarász 026a1e01c7 client-side block query api 2022-10-16 12:30:50 +02:00
Dominik Madarász 2527a40231 build mode ui improvements 2022-10-16 11:09:51 +02:00
Dominik Madarász b12c321488 vendor: update flecs 🎉 2022-10-16 11:09:39 +02:00
Dominik Madarász f9906ca1dd debug ui item spawner 2022-10-16 02:53:10 +02:00
Dominik Madarász fe497ae71b fix item render 2022-10-16 02:27:25 +02:00
Dominik Madarász 2d09fd90cd consider non-collision blocks as ground blocks 2022-10-16 02:13:38 +02:00
Dominik Madarász 671445d4a7 improve rendering 2022-10-16 02:00:19 +02:00
Dominik Madarász 174e5a0452 custom dim sprites 2022-10-16 01:48:23 +02:00
Dominik Madarász 50967aa046 z ordering for outer blocks + improve entity aabb collisions 2022-10-16 00:49:29 +02:00
Dominik Madarász a7622ceeec introduce a sorted render queue 2022-10-15 23:10:46 +02:00
Dominik Madarász 2040984666 update minimal texgen 2022-10-15 13:51:22 +02:00
Dominik Madarász 0c099af4e8 texgen overrides 2022-10-15 13:48:05 +02:00
Dominik Madarász 11c3f26126 rename icemaker to coal + textures 2022-10-15 13:26:07 +02:00
Dominik Madarász 2663b713f2 ticked systems 2022-10-05 16:21:43 +02:00
Dominik Madarász 9a6a8b360a durability meter + fix dropping items 2022-09-29 22:49:40 +02:00
Dominik Madarász e51d941010 items can have storage now 2022-09-29 20:49:00 +02:00
Dominik Madarász 3f96594fdb move all static data to lists folder 2022-09-29 20:11:47 +02:00
Dominik Madarász 7f098734f5 rework blueprinting to use asset ids instead 2022-09-29 19:56:00 +02:00
Dominik Madarász 686149829e wake producer when producing items 2022-09-29 19:39:34 +02:00
Dominik Madarász 6ae7aff24c add blueprinting 2022-09-29 19:28:56 +02:00
Dominik Madarász 24e30dd90a add device progress bar 2022-09-29 18:06:08 +02:00
Dominik Madarász ed5fd927ab add more vehicle types 2022-09-29 17:35:43 +02:00
Dominik Madarász 11929260e2 fix all msvc W3 warnings 2022-09-29 16:41:28 +02:00
Vladyslav Hrytsenko b6cf690c25 code: commited fixes to compilation 2022-09-29 17:33:36 +03:00
Dominik Madarász 6a7dc92966 fix invalid calls 2022-09-29 16:29:31 +02:00
Dominik Madarász e718164544 models wip 2022-09-29 16:16:06 +02:00
Dominik Madarász 8e013c4171 make prefabs folder 2022-09-29 16:05:07 +02:00
Vladyslav Hrytsenko 914b72c44f code: fixed memleak in flecs query 2022-09-29 16:21:40 +03:00
Vladyslav Hrytsenko 5d7ad90e0d code: fix build on mac 2022-09-29 16:10:59 +03:00
Dominik Madarász 86b57bd3a1 drop vsync for desktop + TEXTURE_WRAP_CLAMP for chunks 2022-09-29 15:02:40 +02:00
Dominik Madarász f9b00b3b12 add GenFrameRect 2022-09-29 14:19:16 +02:00
Dominik Madarász 583535c138 minimal texgen 2022-09-29 14:17:47 +02:00
Dominik Madarász 85e87b0e81 minimal renderer skeleton 2022-09-29 14:11:42 +02:00
Dominik Madarász 2b9118a206 input code merge 2022-09-29 14:05:35 +02:00
Dominik Madarász 8ae09dd00c texgen helpers 2022-09-29 14:02:22 +02:00
Dominik Madarász 01afd45007 merge glue code between games 2022-09-29 13:59:51 +02:00
Dominik Madarász fd1ea14de5 win fixes 2022-09-29 13:04:25 +02:00
Vladyslav Hrytsenko 8a12661689 code: removed minimal 3d 2022-09-28 23:03:21 +03:00
Vladyslav Hrytsenko 645111b53c code: changed zoom behavior 2022-09-28 23:01:47 +03:00
Vladyslav Hrytsenko 3fd5e282cf code: minor qol changes 2022-09-28 21:40:59 +03:00
Vladyslav Hrytsenko 04175594d4 code: added caching function to ecs_get_mut 2022-09-28 20:10:40 +03:00
Dominik Madarász 0be5d87ede
lots of changes 2022-09-28 13:17:33 +00:00
Dominik Madarász b8e3decc96
add some impl comments 2022-09-28 05:53:52 +00:00
Dominik Madarász 7aadeed518
interim changes 2022-09-28 05:29:32 +00:00
Dominik Madarász 0c95f1148a
Revert "all storage systems are dynamic now"
This reverts commit b6b632899d.
2022-09-27 15:22:13 +00:00
289 changed files with 347526 additions and 27199 deletions

22
.github/workflows/web-build.yml vendored 100644
View File

@ -0,0 +1,22 @@
name: Build web and deploy
on:
workflow_dispatch:
env:
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
BUILD_TYPE: Release
BUTLER_API_KEY: ${{ secrets.BUTLER_KEY }}
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up emsdk
run: web/setup.sh
- name: Build and deploy eco2d
run: web/deploy.sh

8
.gitignore vendored
View File

@ -1,6 +1,6 @@
build
build_rel
build_web
build.*
build_*
emsdk
deploy_web
run_web
@ -20,3 +20,7 @@ GTAGS
pkg
pkg.zip
eco2d.zip
eco2d.db
eco2d.sublime-workspace
.cache

11
CMakePresets.json 100644
View File

@ -0,0 +1,11 @@
{
"version": 2,
"buildPresets": [
{
"name": "vs2022-debug",
"displayName": "Visual Studio Community 2022 Release - x86_amd64 - Debug",
"configurePreset": "vs2022",
"configuration": "Debug"
}
]
}

View File

@ -1,6 +1,6 @@
<div align="center">
<a href="https://zaklaus.itch.io/eco2d"><img src="https://user-images.githubusercontent.com/2182108/111983468-d5593e80-8b12-11eb-9c59-8c78ecc0504e.png" alt="eco2d" /></a>
</div>
<h1>
eco2d
</h1>
<br />
@ -23,7 +23,7 @@
</div>
# Introduction
zpl.eco2d is a small framework/game engine made out of curiosity. It attempts to bridge several libraries to create a playable sandbox with ease of extensibility and with performance in mind. The goal is not to make a generic 2D game engine but to build a game prototype that anyone can use to build various experiments.
eco2d is a experimental set of games made out of curiosity. It attempts to bridge several libraries to create a playable sandbox with ease of extensibility and with performance in mind. The goal is not to make a generic 2D game engine but to build a game prototype that anyone can use to build various experiments.
The game runs on top of [raylib](https://raylib.com/) technologies and makes use of the [zpl](https://zpl.pw/) ecosystem alongside the **cwpack** library for data serialization. The game logic and lifecycle are maintained using [flecs](https://github.com/SanderMertens/flecs/) library and its suite of tools that help us improve the development efficiency.
@ -31,7 +31,7 @@ It was built with networked game sessions in mind from the ground up and therefo
* Networked game (UDP) - networked sessions benefit from the use of [enet](https://github.com/zpl-c/enet/) library.
* Local Only sessions - Data is streamed via local buffers.
In both cases, the game engine does not differentiate between these two options and makes the concept of Server <>client infrastructure entirely abstract. As a result, gameplay logic is only tied to living entities, where the entity might represent a networked client / local controller.
In both cases, the game engine does not differentiate between these two options and makes the concept of Server<>client infrastructure entirely abstract. As a result, gameplay logic is only tied to living entities, where the entity might represent a networked client / local controller.
All data is transferred via packets fully automated by our serialization rule system, which uses the **cwpack** library in the background.
@ -90,7 +90,7 @@ build\eco2d.exe -?
```
# License
zpl.eco2d code is licensed under the BSD 3-Clause license, as seen [here](LICENSE).
eco2d code is licensed under the BSD 3-Clause license, as seen [here](LICENSE).
Assets under the **art** folder are released into [Public Domain](https://creativecommons.org/share-your-work/public-domain/cc0/) unless otherwise stated.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 474 B

BIN
art/gen/bigtree.png 100644

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 361 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 430 B

BIN
art/gen/coal.png 100644

Binary file not shown.

After

Width:  |  Height:  |  Size: 452 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 559 B

BIN
art/gen/enemy1.png 100644

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
art/gen/furnace.png 100644

Binary file not shown.

After

Width:  |  Height:  |  Size: 901 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 422 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 553 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 366 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 528 B

BIN
art/gen/log.png 100644

Binary file not shown.

After

Width:  |  Height:  |  Size: 423 B

BIN
art/gen/plank.png 100644

Binary file not shown.

After

Width:  |  Height:  |  Size: 382 B

BIN
art/gen/player.png 100644

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
art/gen/screws.png 100644

Binary file not shown.

After

Width:  |  Height:  |  Size: 588 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 592 B

BIN
art/gen/water0.png 100644

Binary file not shown.

After

Width:  |  Height:  |  Size: 581 B

BIN
art/gen/water1.png 100644

Binary file not shown.

After

Width:  |  Height:  |  Size: 624 B

BIN
art/gen/water2.png 100644

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 254 B

After

Width:  |  Height:  |  Size: 278 B

View File

@ -0,0 +1,28 @@
-- typedef enum {
-- BLOCK_FLAG_COLLISION = (1 << 1),
-- BLOCK_FLAG_HAZARD = (1 << 2),
-- BLOCK_FLAG_ESSENTIAL = (1 << 3),
-- BLOCK_FLAG_DESTROY_ON_COLLISION = (1 << 4),
-- BLOCK_FLAG_ENTITY = (1 << 5),
-- } block_flags;
INSERT INTO blocks (kind, flags, drag, friction, bounce, velx, vely) VALUES
(asset('EMPTY'), NULL, NULL, NULL, NULL, NULL, NULL),
(asset('GROUND'), NULL, 1.0, 1.0, NULL, NULL, NULL),
(asset('DIRT'), NULL, 2.1, 1.0, NULL, NULL, NULL),
(asset('WALL'), (1<<1), 1.0, 1.0, 1.0, NULL, NULL),
(asset('HILL'), (1<<1), 1.0, 1.0, NULL, NULL, NULL),
(asset('HILL_SNOW'), (1<<1), 1.0, 1.0, NULL, NULL, NULL),
(asset('WATER'), 0, 0.11, 1.0, NULL, NULL, NULL),
(asset('LAVA'), (1<<2), 6.2, 4.0, NULL, NULL, NULL),
(asset('FENCE'), (1<<1), 1.0, 1.0, 1.0, NULL, NULL),
(asset('WOOD'), (1<<1), 1.0, 1.0, 0.0, NULL, NULL),
(asset('TREE'), (1<<1)|(1<<4), 1.0, 1.0, 0.0, NULL, NULL),
(asset('CHEST'), (1<<5), NULL, NULL, NULL, NULL, NULL),
(asset('FURNACE'), (1<<5), NULL, NULL, NULL, NULL, NULL),
(asset('TEST_TALL'), (1<<1), NULL, NULL, NULL, NULL, NULL),
(asset('BELT_LEFT'), NULL, 1.0, 1.0, NULL, -150.0, NULL),
(asset('BELT_RIGHT'), NULL, 1.0, 1.0, NULL, 150.0, NULL),
(asset('BELT_UP'), NULL, 1.0, 1.0, NULL, NULL, -150.0),
(asset('BELT_DOWN'), NULL, 1.0, 1.0, NULL, NULL, 150.0);

View File

@ -0,0 +1,46 @@
-- typedef enum {
-- // NOTE(zaklaus): hardcoded fields for placement ops
-- UKIND_DELETE,
-- UKIND_PLACE,
-- UKIND_PLACE_ITEM,
-- UKIND_PLACE_ITEM_DATA,
-- UKIND_END_PLACE,
--
-- // NOTE(zaklaus): the rest of possible actions
-- UKIND_HOLD,
-- UKIND_PROXY,
-- } item_usage;
--
-- typedef enum {
-- UDATA_NONE,
-- UDATA_ENERGY_SOURCE,
-- } item_attachment;
INSERT INTO items (kind, usage, attachment, max_quantity, place_kind, directional,
proxy_id, place_item_id, producer, energy_level, blueprint_w, blueprint_h, blueprint_plan)
VALUES
(0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
(asset('FENCE'), 5, 0, 64, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
(asset('COAL'), 5, 1, 64, NULL, NULL, NULL, NULL, asset('FURNACE'), 15.0, NULL, NULL, NULL),
(asset('WOOD'), 1, 0, 64, asset('WOOD'), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
(asset('TREE'), 1, 0, 64, asset('TREE'), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
(asset('TEST_TALL'), 1, 0, 64, asset('TEST_TALL'), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
(asset('BELT'), 1, 0, 999, asset('BELT'), 1, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
(asset('BELT_LEFT'), 6, 0, NULL, NULL, NULL, asset('BELT'), NULL, NULL, NULL, NULL, NULL, NULL),
(asset('BELT_RIGHT'), 6, 0, NULL, NULL, NULL, asset('BELT'), NULL, NULL, NULL, NULL, NULL, NULL),
(asset('BELT_UP'), 6, 0, NULL, NULL, NULL, asset('BELT'), NULL, NULL, NULL, NULL, NULL, NULL),
(asset('BELT_DOWN'), 6, 0, NULL, NULL, NULL, asset('BELT'), NULL, NULL, NULL, NULL, NULL, NULL),
(asset('CHEST'), 2, 0, 32, NULL, NULL, NULL, asset('CHEST'), NULL, NULL, NULL, NULL, NULL),
(asset('CRAFTBENCH'), 2, 0, 32, NULL, NULL, NULL, asset('CRAFTBENCH'), NULL, NULL, NULL, NULL, NULL),
(asset('FURNACE'), 2, 0, 32, NULL, NULL, NULL, asset('FURNACE'), NULL, NULL, NULL, NULL, NULL),
(asset('SPLITTER'), 2, 0, 32, NULL, NULL, NULL, asset('SPLITTER'), NULL, NULL, NULL, NULL, NULL),
(asset('ASSEMBLER'), 2, 0, 32, NULL, NULL, NULL, asset('ASSEMBLER'), NULL, NULL, NULL, NULL, NULL),
(asset('CREATURE'), 2, 0, 32, NULL, NULL, NULL, asset('CREATURE'), NULL, NULL, NULL, NULL, NULL),
(asset('IRON_ORE'), 5, 0, 64, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
(asset('IRON_INGOT'), 5, 0, 64, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
(asset('IRON_PLATES'), 5, 0, 64, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
(asset('SCREWS'), 5, 0, 64, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
(asset('LOG'), 5, 0, 64, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
(asset('PLANK'), 5, 0, 64, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
-- (asset('BLUEPRINT_DEMO_HOUSE'), 3, 0, 1, NULL, NULL, NULL, asset('BLUEPRINT'), NULL, NULL, 4, 4, ''),
(asset('CREATURE_FOOD'), 5, 0, 1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);

View File

@ -0,0 +1 @@
Only modify these for eco2d game specifically!

View File

@ -0,0 +1,18 @@
INSERT INTO recipes (product, product_qty, process_ticks, producer) VALUES
(asset('IRON_PLATES'), 4, 20, asset('FURNACE')),
(asset('SCREWS'), 8, 40, asset('CRAFTBENCH')),
(asset('BELT'), 1, 120, asset('ASSEMBLER'));
INSERT INTO reagents (asset_id, qty) VALUES
(asset('IRON_ORE'), 1),
(asset('IRON_PLATES'), 1),
(asset('FENCE'), 1),
(asset('SCREWS'), 4),
(asset('IRON_PLATES'), 2);
INSERT INTO recipe_reagents (recipe_id, reagent_id) VALUES
(1, 1),
(2, 2),
(3, 3),
(3, 4),
(3, 5);

View File

@ -0,0 +1,42 @@
INSERT INTO resources (asset, kind) VALUES
(asset('EMPTY'), 0),
(asset('BLANK'), 0),
(asset('BLOCK_FRAME'), 0),
(asset('BUILDMODE_HIGHLIGHT'), 0),
(asset('COAL'), 0),
(asset('IRON_ORE'), 0),
(asset('IRON_INGOT'), 0),
(asset('IRON_PLATES'), 0),
(asset('SCREWS'), 0),
(asset('LOG'), 0),
(asset('PLANK'), 0),
(asset('CHEST'), 0),
(asset('CREATURE'), 0),
(asset('CREATURE_FOOD'), 0),
(asset('FURNACE'), 0),
(asset('SPLITTER'), 0),
(asset('ASSEMBLER'), 0),
(asset('CRAFTBENCH'), 0),
(asset('BLUEPRINT'), 0),
(asset('BLUEPRINT_DEMO_HOUSE'), 0),
(asset('MOB'), 0),
(asset('PLAYER'), 0),
(asset('FENCE'), 0),
(asset('DEV'), 0),
(asset('GROUND'), 0),
(asset('DIRT'), 0),
(asset('WATER'), 2),
(asset('LAVA'), 0),
(asset('WALL'), 0),
(asset('HILL'), 0),
(asset('HILL_SNOW'), 0),
(asset('HOLE'), 0),
(asset('WOOD'), 0),
(asset('TEST_TALL'), 0),
(asset('TREE'), 0),
(asset('BELT'), 0),
(asset('BELT_LEFT'), 0),
(asset('BELT_RIGHT'), 0),
(asset('BELT_UP'), 0),
(asset('BELT_DOWN'), 0);

View File

@ -0,0 +1,72 @@
CREATE TABLE assets (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name VARCHAR(255) NOT NULL
);
CREATE TABLE resources (
id INTEGER PRIMARY KEY AUTOINCREMENT,
asset INTEGER NOT NULL,
kind INTEGER NOT NULL
);
CREATE TABLE blocks (
id INTEGER PRIMARY KEY AUTOINCREMENT,
kind INTEGER NOT NULL,
flags INTEGER DEFAULT 0,
drag REAL,
friction REAL,
bounce REAL,
velx REAL,
vely REAL,
FOREIGN KEY (kind) REFERENCES assets(id)
);
CREATE TABLE items (
id INTEGER PRIMARY KEY AUTOINCREMENT,
kind INTEGER NOT NULL,
usage INTEGER,
attachment INTEGER,
max_quantity INTEGER,
has_storage BOOLEAN,
place_kind INTEGER,
directional BOOLEAN,
proxy_id INTEGER,
place_item_id INTEGER,
producer INTEGER,
energy_level REAL,
blueprint_w INTEGER,
blueprint_h INTEGER,
blueprint_plan TEXT,
FOREIGN KEY (kind) REFERENCES assets(id)
);
CREATE TABLE reagents (
id INTEGER PRIMARY KEY AUTOINCREMENT,
asset_id INTEGER NOT NULL,
qty INTEGER NOT NULL,
FOREIGN KEY (asset_id) REFERENCES assets(id)
);
CREATE TABLE recipes (
id INTEGER PRIMARY KEY AUTOINCREMENT,
product INTEGER NOT NULL,
product_qty INTEGER NOT NULL,
process_ticks INTEGER NOT NULL,
producer INTEGER NOT NULL,
FOREIGN KEY (product) REFERENCES assets(id),
FOREIGN KEY (producer) REFERENCES assets(id)
);
CREATE TABLE recipe_reagents (
id INTEGER PRIMARY KEY AUTOINCREMENT,
recipe_id INTEGER NOT NULL,
reagent_id INTEGER NOT NULL,
FOREIGN KEY (recipe_id) REFERENCES recipes(id),
FOREIGN KEY (reagent_id) REFERENCES reagents(id)
);

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
art/skins/gwen.png 100644

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

3
build_dbg.bat 100644
View File

@ -0,0 +1,3 @@
@echo off
call win\setup_cl_generic.bat amd64
cmake --build build && build\eco2d

View File

@ -1,20 +1,20 @@
find_package(raylib 3.5 QUIET)
if (NOT raylib_FOUND)
include(FetchContent)
FetchContent_Declare(
raylib
URL https://github.com/zpl-c/raylib/archive/master.tar.gz
)
FetchContent_GetProperties(raylib)
if (NOT raylib_POPULATED)
set(FETCHCONTENT_QUIET NO)
FetchContent_Populate(raylib)
set(BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
add_subdirectory(${raylib_SOURCE_DIR} ${raylib_BINARY_DIR})
endif()
endif()
find_package(raylib 3.5 QUIET)
if (NOT raylib_FOUND)
include(FetchContent)
FetchContent_Declare(
raylib
URL https://github.com/zpl-c/raylib/archive/master.tar.gz
)
FetchContent_GetProperties(raylib)
if (NOT raylib_POPULATED)
set(FETCHCONTENT_QUIET NO)
FetchContent_Populate(raylib)
set(BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
add_subdirectory(${raylib_SOURCE_DIR} ${raylib_BINARY_DIR})
endif()
endif()

View File

@ -8,6 +8,12 @@ function(link_system_libs target_name)
elseif (UNIX)
target_link_libraries(${target_name} pthread m dl atomic)
endif()
if (WIN32)
target_compile_options(${target_name} PRIVATE -WX -W3 -wd5105)
else()
target_compile_options(${target_name} PRIVATE -Werror -Wall -Wextra -Wno-unused-function -Wno-unknown-pragmas -Wno-unused-variable -Wno-unused-parameter)
endif ()
endfunction()
macro(use_cxx11)

View File

@ -3,21 +3,29 @@ file(GLOB PKT_SRCS src/packets/*.h src/packets/*.c)
add_library(eco2d-foundation STATIC
src/core/game.c
src/core/camera.c
src/core/rules_default.c
src/platform/signal_handling.c
src/platform/profiler.c
src/platform/input.c
src/ents/items.c
src/ents/entity.c
src/ents/player.c
src/ents/vehicle.c
src/ents/storage.c
src/ents/device.c
src/models/database.c
src/models/assets.c
src/models/components.c
src/models/items.c
src/models/entity.c
src/models/device.c
src/models/crafting.c
src/models/prefabs/player.c
src/models/prefabs/vehicle.c
src/pkt/packet.c
src/debug/debug_ui.c
src/debug/debug_draw.c
src/gen/texgen_fallback.c
src/dev/debug_ui.c
src/dev/debug_draw.c
src/utils/options.c
src/utils/compress.c
@ -30,20 +38,14 @@ add_library(eco2d-foundation STATIC
src/world/world_view.c
src/world/entity_view.c
src/world/prediction.c
src/world/worldgen/worldgen_test.c
src/gen/assets.c
src/gen/texgen.c
src/ecs/systems.c
src/ecs/components.c
src/systems/systems.c
${PKT_SRCS}
)
target_compile_definitions(eco2d-foundation PRIVATE CLIENT)
include_directories(src ../modules ../../art/gen)
target_link_libraries(eco2d-foundation raylib cwpack flecs-bundle vendors-bundle)
target_compile_options(eco2d-foundation PRIVATE -Werror -Wall -Wextra -Wno-unused-function -Wno-unknown-pragmas -Wno-unused-variable -Wno-unused-parameter)
target_link_libraries(eco2d-foundation raylib raylib_nuklear cwpack flecs-bundle vendors-bundle)
link_system_libs(eco2d-foundation)

View File

@ -0,0 +1,58 @@
#pragma once
#define ASSET_INVALID 0xFF
#define _ASSETS\
X(ASSET_EMPTY)\
X(ASSET_BLANK)\
X(ASSET_BLOCK_FRAME)\
X(ASSET_BUILDMODE_HIGHLIGHT)\
X(ASSET_PLAYER)\
X(ASSET_THING)\
X(ASSET_CREATURE)\
X(ASSET_CREATURE_FOOD)\
X(ASSET_CHEST)\
X(ASSET_SPLITTER)\
X(ASSET_ASSEMBLER)\
X(ASSET_FURNACE)\
X(ASSET_CRAFTBENCH)\
X(ASSET_BLUEPRINT_BEGIN)\
X(ASSET_BLUEPRINT)\
X(ASSET_BLUEPRINT_DEMO_HOUSE)\
X(ASSET_BLUEPRINT_END)\
X(ASSET_FENCE)\
X(ASSET_DEV)\
X(ASSET_GROUND)\
X(ASSET_DIRT)\
X(ASSET_WATER)\
X(ASSET_LAVA)\
X(ASSET_WALL)\
X(ASSET_HILL)\
X(ASSET_HILL_SNOW)\
X(ASSET_HOLE)\
X(ASSET_WOOD)\
X(ASSET_TREE)\
X(ASSET_COAL)\
X(ASSET_IRON_ORE)\
X(ASSET_IRON_INGOT)\
X(ASSET_IRON_PLATES)\
X(ASSET_SCREWS)\
X(ASSET_LOG)\
X(ASSET_PLANK)\
X(ASSET_TEST_TALL)\
X(ASSET_BELT)\
X(ASSET_BELT_LEFT)\
X(ASSET_BELT_RIGHT)\
X(ASSET_BELT_UP)\
X(ASSET_BELT_DOWN)
typedef enum {
#define X(idx) idx,
_ASSETS
#undef X
MAX_INTERNAL_ASSETS,
NEXT_FREE_ASSET = MAX_INTERNAL_ASSETS,
MAX_ASSETS = 255
} asset_id;
extern const char *asset_names[];

View File

@ -3,36 +3,44 @@
#include "platform/platform.h"
#include "world/world.h"
#include "pkt/packet.h"
#include "models/database.h"
#include "platform/signal_handling.h"
#include "net/network.h"
#include "ents/entity.h"
#include "ents/items.h"
#include "models/entity.h"
#include "world/world_view.h"
#include "world/entity_view.h"
#include "core/camera.h"
#include "platform/profiler.h"
#include "platform/renderer.h"
#include "flecs/flecs_os_api_stdcpp.h"
#include "flecs/flecs.h"
#include "flecs.h"
#include "ecs/components.h"
#include "ecs/systems.h"
#include "models/components.h"
#include "systems/systems.h"
#include "packets/pkt_00_init.h"
#include "packets/pkt_01_welcome.h"
#include "packets/pkt_switch_viewer.h"
#define RAYLIB_NUKLEAR_IMPLEMENTATION
ZPL_DIAGNOSTIC_PUSH_WARNLEVEL(0)
#include "raylib-nuklear.h"
ZPL_DIAGNOSTIC_POP
static uint8_t game_mode;
static uint8_t game_should_close;
static world_view *world_viewers;
static world_view *active_viewer;
struct nk_context *game_ui = 0;
static WORLD_PKT_READER(pkt_reader) {
pkt_header header = {0};
uint32_t ok = pkt_header_decode(&header, data, datalen);
header.udata = udata;
if (ok && header.ok) {
return pkt_handlers[header.id].handler(&header) >= 0;
} else {
@ -67,7 +75,7 @@ static WORLD_PKT_WRITER(mp_cli_pkt_writer) {
void world_viewers_init(uint32_t num_viewers) {
zpl_buffer_init(world_viewers, zpl_heap(), num_viewers);
for (uint32_t i = 0; i < num_viewers; i++) {
zpl_buffer_append(world_viewers, world_view_create(i));
}
@ -93,7 +101,7 @@ void game_world_view_cycle_active(int8_t dir) {
game_world_view_set_active_by_idx(zpl_max(0, (idx+dir)%zpl_buffer_count(world_viewers)));
}
void game_world_view_set_active_by_idx(uint16_t idx) {
ZPL_ASSERT(idx >= 0 && idx < zpl_buffer_count(world_viewers));
ZPL_ASSERT(idx < zpl_buffer_count(world_viewers));
game_world_view_set_active(&world_viewers[idx]);
}
@ -126,42 +134,40 @@ float game_time() {
return (float)get_cached_time();
}
void game_init(const char *ip, uint16_t port, game_kind play_mode, uint32_t num_viewers, int32_t seed, uint16_t chunk_size, uint16_t chunk_amount, int8_t is_dash_enabled) {
void game_setup(const char *ip, uint16_t port, game_kind play_mode, uint32_t num_viewers, int32_t seed, uint16_t chunk_size, uint16_t chunk_amount, int8_t is_dash_enabled) {
game_mode = play_mode;
game_should_close = false;
entity_default_spawnlist();
game_init(db_init());
#ifndef _DEBUG
const char *host_ip = "lab.zakto.pw";
#else
const char *host_ip = "127.0.0.1";
#endif
uint16_t host_port = (port > 0) ? port : 27000;
if (ip != NULL) {
host_ip = ip;
}
// NOTE: initialise subsystems
{
assets_setup();
blocks_setup();
item_setup();
entity_spawndef_setup();
}
if (game_mode != GAMEKIND_HEADLESS) {
platform_init();
world_viewers_init(num_viewers);
active_viewer = &world_viewers[0];
camera_reset();
}
Font font = LoadFontEx("art/anonymous_pro_bold.ttf", 14, 0, 0);
game_ui = InitNuklearEx(font, 14);
}
if (game_mode != GAMEKIND_SINGLE) {
network_init();
}
if (game_mode == GAMEKIND_CLIENT) {
world_setup_pkt_handlers(pkt_reader, mp_cli_pkt_writer);
network_client_connect(host_ip, host_port);
@ -170,13 +176,15 @@ void game_init(const char *ip, uint16_t port, game_kind play_mode, uint32_t num_
world_setup_pkt_handlers(pkt_reader, game_mode == GAMEKIND_SINGLE ? sp_pkt_writer : mp_pkt_writer);
world_init(seed, chunk_size, chunk_amount);
if (is_dash_enabled) flecs_dash_init();
if (game_mode == GAMEKIND_HEADLESS) {
network_server_start(0, 27000);
//ecs_set_target_fps(world_ecs(), 60);
}
}
game_init_ecs();
if (game_mode == GAMEKIND_SINGLE) {
for (uint32_t i = 0; i < num_viewers; i++) {
pkt_00_init_send(i);
@ -189,35 +197,29 @@ int8_t game_is_networked() {
}
void game_shutdown() {
db_shutdown();
if (game_mode == GAMEKIND_CLIENT) {
network_client_disconnect();
} else {
world_destroy();
if (game_mode == GAMEKIND_HEADLESS) {
network_server_stop();
}
}
if (game_mode != GAMEKIND_SINGLE) {
network_destroy();
}
if (game_mode != GAMEKIND_HEADLESS) {
world_viewers_destroy();
// TODO(zaklaus): crashes on exit
//platform_shutdown();
}
// NOTE: shutdown subsystems
{
item_cleanup();
entity_spawndef_cleanup();
blocks_cleanup();
assets_cleanup();
}
UnloadNuklear(game_ui);
}
}
uint8_t game_is_running() {
@ -232,23 +234,24 @@ game_kind game_get_kind(void) {
return game_mode;
}
void game_input() {
void game_core_input() {
if (game_mode != GAMEKIND_HEADLESS) {
platform_input();
UpdateNuklear(game_ui);
}
}
void game_update() {
void game_core_update() {
static double last_update = 0.0f;
if (game_mode == GAMEKIND_CLIENT) {
network_client_tick();
}
else {
world_update();
if (game_mode == GAMEKIND_HEADLESS) {
network_server_tick();
static float ms_report = 2.5f;
if (ms_report < get_cached_time()) {
ms_report = get_cached_time() + 5.f;
@ -256,16 +259,20 @@ void game_update() {
}
}
}
last_update = get_cached_time();
}
void game_render() {
void game_core_render() {
if (game_mode != GAMEKIND_HEADLESS) {
platform_render();
}
}
void game_draw_ui() {
DrawNuklear(game_ui);
}
void game_action_send_keystate(game_keystate_data *data) {
pkt_send_keystate_send(active_viewer->view_id, data);
}
@ -284,3 +291,71 @@ void game_request_close() {
platform_request_close();
}
}
static game_world_render_entry* render_queue = NULL;
static void game__world_view_render_push_entry(uint64_t key, entity_view * data) {
if (!data) return;
if (data->kind == EKIND_CHUNK) {
world_view *view = game_world_view_get_active();
float size = (float)(view->chunk_size * WORLD_BLOCK_SIZE);
float offset = 0.0;
for (size_t ty = 0; ty < view->chunk_size; ty++) {
for (size_t tx = 0; tx < view->chunk_size; tx++) {
block_id blk_id = data->outer_blocks[(ty*view->chunk_size)+tx];
if (blk_id != 0) {
game_world_render_entry entry = {
.key = key,
.data = data,
.blk_id = blk_id,
.x = (data->x*size + offset) + (float)tx*WORLD_BLOCK_SIZE + WORLD_BLOCK_SIZE/2,
.y = (data->y*size + offset) + (float)ty*WORLD_BLOCK_SIZE + WORLD_BLOCK_SIZE/2,
.cy = (data->y*size + offset) + (float)ty*WORLD_BLOCK_SIZE + WORLD_BLOCK_SIZE/2,
};
if (!(blocks_get_flags(blk_id) & BLOCK_FLAG_COLLISION)) {
entry.cy = ZPL_F32_MIN;
}
zpl_array_append(render_queue, entry);
}
}
}
return;
}
game_world_render_entry entry = {
.key = key,
.data = data,
.x = data->x,
.y = data->y,
.cy = data->y,
.blk_id = 0,
};
zpl_array_append(render_queue, entry);
}
static void game__world_view_render_ground(uint64_t key, entity_view * data) {
if (data->kind != EKIND_CHUNK) return;
renderer_draw_entry(key, data, 0);
}
void game_world_view_render_world(void) {
if (!render_queue) {
zpl_array_init(render_queue, zpl_heap());
}
zpl_array_clear(render_queue);
profile(PROF_RENDER_PUSH_AND_SORT_ENTRIES) {
game_world_view_active_entity_map(game__world_view_render_push_entry);
zpl_sort_array(render_queue, zpl_array_count(render_queue), zpl_f32_cmp(zpl_offset_of(game_world_render_entry, cy)));
}
game_world_view_active_entity_map(game__world_view_render_ground);
for (zpl_isize i = 0; i < zpl_array_count(render_queue); i++) {
renderer_draw_entry(render_queue[i].key, render_queue[i].data, &render_queue[i]);
}
}

View File

@ -2,6 +2,7 @@
#include "platform/system.h"
#include "world/world_view.h"
#include "packets/pkt_send_keystate.h"
#include "packets/pkt_send_code.h"
typedef enum {
GAMEKIND_SINGLE,
@ -10,7 +11,7 @@ typedef enum {
FORCE_GAMEKIND_UINT8 = UINT8_MAX
} game_kind;
void game_init(const char *ip, uint16_t port, game_kind play_mode, uint32_t num_viewers, int32_t seed, uint16_t chunk_size, uint16_t chunk_amount, int8_t is_dash_enabled);
void game_setup(const char *ip, uint16_t port, game_kind play_mode, uint32_t num_viewers, int32_t seed, uint16_t chunk_size, uint16_t chunk_amount, int8_t is_dash_enabled);
void game_shutdown();
void game_request_close();
uint8_t game_is_running();
@ -19,9 +20,24 @@ float game_time();
game_kind game_get_kind(void);
//~ NOTE(zaklaus): game events
// Implemented by games
void game_init(bool new_db);
void game_init_ecs(); // called once the world is initialised
void game_input();
void game_update();
void game_render();
void game_player_joined(uint64_t ent);
void game_player_departed(uint64_t ent);
void game_player_died(uint64_t ent);
void game_client_receive_code(pkt_send_code data);
// base methods called from games
void game_core_input();
void game_core_update();
void game_core_render();
//~ Called from platform.c
void game_draw_ui();
//~ NOTE(zaklaus): world view management
world_view *game_world_view_get_active(void);
@ -32,6 +48,7 @@ void game_world_view_set_active(world_view *view);
void game_world_view_cycle_active(int8_t dir);
void game_world_view_active_entity_map(void (*map_proc)(uint64_t key, entity_view * value));
entity_view *game_world_view_active_get_entity(uint64_t ent_id);
void game_world_view_render_world(void);
//~ NOTE(zaklaus): viewer -> host actions
void game_action_send_keystate(game_keystate_data *data);

View File

@ -0,0 +1,33 @@
#pragma once
#include "platform/system.h"
typedef struct {
float phy_walk_drag;
uint64_t demo_npc_move_speed;
uint64_t demo_npc_steer_speed;
float item_pick_radius;
float item_merger_radius;
float item_attract_radius;
float item_attract_force;
float item_container_reach_radius;
float item_drop_pickup_time;
float item_drop_merger_time;
float plr_move_speed;
float plr_move_speed_mult;
float vehicle_force;
float vehicle_accel;
float vehicle_decel;
float vehicle_steer;
float vehicle_steer_compensation;
float vehicle_steer_revert;
float vehicle_power;
float vehicle_brake_force;
float veh_enter_radius;
float blueprint_build_time;
// survival rules
} game_rulesdef;
extern game_rulesdef game_rules;
void rules_setup();

View File

@ -0,0 +1,26 @@
#include "core/rules.h"
game_rulesdef game_rules = {
.phy_walk_drag = 4.23f,
.demo_npc_move_speed = 500,
.demo_npc_steer_speed = 300,
.item_pick_radius = 25.0f,
.item_merger_radius = 75.0f,
.item_attract_radius = 75.0f,
.item_attract_force = 1.98f,
.item_container_reach_radius = 105.0f,
.item_drop_pickup_time = 2.5f,
.item_drop_merger_time = 6.5f,
.plr_move_speed = 800.0f,
.plr_move_speed_mult = 1.5f,
.vehicle_force = 240.8f,
.vehicle_accel = 0.032f,
.vehicle_decel = 0.28f,
.vehicle_steer = 35.89f,
.vehicle_steer_compensation = 4.0f,
.vehicle_steer_revert = 6.0941816f,
.vehicle_power = 97.89f,
.vehicle_brake_force = 0.84f,
.veh_enter_radius = 45.0f,
.blueprint_build_time = 1.5f,
};

View File

@ -1,9 +1,9 @@
#include "debug/debug_draw.h"
#include "dev/debug_draw.h"
#include "core/game.h"
static debug_draw_queue draw_queue = {0};
#ifndef _DEBUG
#if !defined(_DEBUG) || 0
static bool draw_is_enabled = false;
#else
static bool draw_is_enabled = true;

View File

@ -1,20 +1,17 @@
#include "debug/debug_replay.h"
#include "dev/debug_replay.h"
#include "core/camera.h"
#include "ents/entity.h"
#include "models/entity.h"
#include "cwpack/cwpack.h"
typedef enum {
RPKIND_KEY,
// NOTE(zaklaus): Special actions
RPKIND_SPAWN_CAR,
RPKIND_PLACE_ICE_RINK,
RPKIND_PLACE_ERASE_CHANGES,
RPKIND_SPAWN_CIRCLING_DRIVER,
RPKIND_SPAWN_ICEMAKER_ITEM,
RPKIND_SPAWN_CHEST,
RPKIND_SPAWN_BELT,
} replay_kind;
typedef struct {
@ -45,17 +42,17 @@ static char replaybuf[sizeof(replay_record)*UINT16_MAX + 32];
void debug_replay_store(void) {
ZPL_ASSERT(replay_filename[0]);
if (!records) return;
cw_pack_context pc = {0};
cw_pack_context_init(&pc, replaybuf, sizeof(replaybuf), 0);
cw_pack_unsigned(&pc, REPLAY_MAGIC);
cw_pack_unsigned(&pc, REPLAY_VERSION);
cw_pack_array_size(&pc, (uint32_t)zpl_array_count(records));
for (int i = 0; i < zpl_array_count(records); i++) {
cw_pack_bin(&pc, &records[i], sizeof(replay_record));
}
zpl_file f = {0};
zpl_file_create(&f, replay_filename);
zpl_file_write(&f, replaybuf, pc.current - pc.start);
@ -64,44 +61,44 @@ void debug_replay_store(void) {
void debug_replay_load(void) {
ZPL_ASSERT(replay_filename[0]);
zpl_file f = {0};
zpl_file_error err = zpl_file_open(&f, replay_filename);
ZPL_ASSERT(err == ZPL_FILE_ERROR_NONE);
size_t file_size = zpl_file_size(&f);
zpl_file_read(&f, replaybuf, file_size);
zpl_file_close(&f);
cw_unpack_context uc = {0};
cw_unpack_context_init(&uc, replaybuf, (uint32_t)file_size, 0);
cw_unpack_next(&uc);
ZPL_ASSERT(uc.item.type == CWP_ITEM_POSITIVE_INTEGER && uc.item.as.u64 == REPLAY_MAGIC);
cw_unpack_next(&uc);
ZPL_ASSERT(uc.item.type == CWP_ITEM_POSITIVE_INTEGER);
uint64_t version = uc.item.as.u64;
ZPL_ASSERT(version >= 2);
cw_unpack_next(&uc);
ZPL_ASSERT(uc.item.type == CWP_ITEM_ARRAY);
size_t items = uc.item.as.array.size;
zpl_array_init_reserve(records, zpl_heap(), sizeof(replay_record)*items);
for (size_t i = 0; i < items; i++) {
cw_unpack_next(&uc);
ZPL_ASSERT(uc.item.type == CWP_ITEM_BIN);
replay_record rec = {0};
switch (version) {
case 2:{
debug_replay_load_record_v2(&rec, uc.item.as.bin.start);
}break;
default:{
zpl_memcopy(&rec, uc.item.as.bin.start, sizeof(replay_record));
}break;
@ -112,10 +109,10 @@ void debug_replay_load(void) {
void debug_replay_start(void) {
is_recording = true;
if (records) zpl_array_free(records);
zpl_array_init_reserve(records, zpl_heap(), UINT16_MAX);
last_record_time = get_cached_time();
SetTargetFPS(60);
}
@ -130,17 +127,17 @@ void debug_replay_clear(void) {
void debug_replay_cleanup_ents(void) {
SetTargetFPS(0);
if (!mime) return;
entity_despawn(mime);
mime = 0;
is_playing = false;
camera_set_follow(plr);
for (int i = 0; i < zpl_array_count(temp_actors); i++) {
entity_despawn(temp_actors[i]);
}
zpl_array_free(temp_actors);
}
@ -157,17 +154,17 @@ void debug_replay_run(void) {
record_pos = 0;
playback_time = get_cached_time();
zpl_array_init(temp_actors, zpl_heap());
plr = camera_get().ent_id;
Position const *p1 = ecs_get(world_ecs(), plr, Position);
mime = entity_spawn(EKIND_MACRO_BOT);
Position *pos = ecs_get_mut(world_ecs(), mime, Position);
*pos = *p1;
ecs_set(world_ecs(), mime, Input, {0});
ecs_set(world_ecs(), mime, Inventory, {0});
camera_set_follow(mime);
SetTargetFPS(60);
}
@ -175,17 +172,17 @@ void debug_replay_run(void) {
void ActPlaceIceRink(void);
void ActSpawnCirclingDriver(void);
void ActEraseWorldChanges(void);
void ActSpawnIcemaker(void);
void ActSpawnCoal(void);
void ActSpawnChest(void);
void ActSpawnBelt(void);
void debug_replay_update(void) {
if (!is_playing) return;
if (playback_time >= get_cached_time()) return;
replay_record *r = &records[record_pos];
playback_time = get_cached_time() + r->delay;
switch (r->kind) {
case RPKIND_KEY: {
Input *i = ecs_get_mut(world_ecs(), mime, Input);
@ -208,12 +205,12 @@ void debug_replay_update(void) {
}
}break;
case RPKIND_SPAWN_CAR: {
ecs_entity_t e = vehicle_spawn();
ecs_entity_t e = vehicle_spawn(EVEH_CAR);
Position const *origin = ecs_get(world_ecs(), mime, Position);
Position *dest = ecs_get_mut(world_ecs(), e, Position);
*dest = *origin;
zpl_array_append(temp_actors, e);
}break;
case RPKIND_PLACE_ICE_RINK: {
@ -225,22 +222,13 @@ void debug_replay_update(void) {
case RPKIND_PLACE_ERASE_CHANGES:{
ActEraseWorldChanges();
}break;
case RPKIND_SPAWN_ICEMAKER_ITEM:{
ActSpawnIcemaker();
}break;
case RPKIND_SPAWN_CHEST:{
ActSpawnChest();
}break;
case RPKIND_SPAWN_BELT:{
ActSpawnBelt();
}break;
default: {
ZPL_PANIC("unreachable");
}break;
}
record_pos += 1;
// NOTE(zaklaus): remove our dummy art exhibist
if (mime && record_pos == zpl_array_count(records)) {
debug_replay_cleanup_ents();
@ -250,13 +238,13 @@ void debug_replay_update(void) {
void debug_replay_record_keystate(pkt_send_keystate state) {
if (!is_recording) return;
double record_time = get_cached_time();
replay_record rec = {
.kind = RPKIND_KEY,
.pkt = state,
.delay = (record_time - last_record_time),
};
zpl_array_append(records, rec);
last_record_time = get_cached_time();
}
@ -265,12 +253,12 @@ void debug_replay_special_action(replay_kind kind) {
ZPL_ASSERT(kind != RPKIND_KEY);
if (!is_recording || is_playing) return;
double record_time = get_cached_time();
replay_record rec = {
.kind = kind,
.delay = (record_time - last_record_time),
};
zpl_array_append(records, rec);
last_record_time = get_cached_time();
}

View File

@ -1,13 +1,17 @@
#include "debug/debug_ui.h"
#include "debug/debug_draw.h"
#include "dev/debug_ui.h"
#include "dev/debug_draw.h"
#include "raylib.h"
#include "ents/vehicle.h"
#include "models/prefabs/vehicle.h"
#include "core/camera.h"
#include "world/world.h"
#include "core/game.h"
#include "sfd.h"
#include "ecs/components.h"
#include "models/components.h"
ZPL_DIAGNOSTIC_PUSH_WARNLEVEL(0)
#include "raylib-nuklear.h"
ZPL_DIAGNOSTIC_POP
typedef enum {
DITEM_RAW,
@ -16,9 +20,11 @@ typedef enum {
DITEM_BUTTON,
DITEM_SLIDER,
DITEM_LIST,
DITEM_TOOL,
DITEM_COND,
DITEM_END,
DITEM_FORCE_UINT8 = UINT8_MAX
} debug_kind;
@ -41,6 +47,8 @@ static uint8_t is_debug_open = 1;
static uint8_t is_handle_ctrl_held;
static float debug_xpos = DBG_START_XPOS;
static float debug_ypos = DBG_START_YPOS;
static zpl_u16 sel_item_id = 0;
static struct nk_context *dev_ui = 0;
typedef enum {
L_NONE = 0,
@ -54,48 +62,58 @@ typedef struct debug_item {
float name_width;
uint8_t skip;
limit_kind limit_to;
union {
union {
char const *text;
uint64_t val;
};
struct {
struct debug_item *items;
uint8_t is_collapsed;
} list;
struct {
float val, min, max;
void (*on_change)(float);
} slider;
struct {
uint8_t is_open;
void (*on_draw)(void);
} tool;
void (*on_click)(void);
uint8_t (*on_success)(void);
};
debug_draw_result (*proc)(struct debug_item*, float, float);
} debug_item;
static void UIDrawText(const char *text, float posX, float posY, int fontSize, Color color);
static int UIMeasureText(const char *text, int fontSize);
#include "debug/debug_replay.c"
#include "dev/debug_replay.c"
#include "debug/debug_ui_actions.c"
#include "debug/debug_ui_widgets.c"
#include "gui/ui_skin.c"
#include "dev/debug_ui_actions.c"
#include "dev/debug_ui_widgets.c"
#include "dev/debug_ui_tools.c"
static debug_item items[] = {
{
.kind = DITEM_LIST,
.name = "general",
.kind = DITEM_LIST,
.name = "general",
.list = {
.is_collapsed = true,
.items = (debug_item[]) {
{ .kind = DITEM_TEXT, .name = "delta time", .proc = DrawDeltaTime },
{ .kind = DITEM_TEXT, .name = "pos", .proc = DrawCameraPos },
{ .kind = DITEM_TEXT, .name = "camera pos", .proc = DrawCameraPos },
{ .kind = DITEM_TEXT, .name = "mouse block", .proc = DrawBlockPos },
{ .kind = DITEM_TEXT, .name = "mouse chunk", .proc = DrawChunkPos },
{ .kind = DITEM_TEXT, .name = "zoom", .proc = DrawZoom },
{ .kind = DITEM_END },
}
@ -109,17 +127,17 @@ static debug_item items[] = {
.items = (debug_item[]) {
{ .kind = DITEM_COND, .on_success = CondIsWorldRunning },
{ .kind = DITEM_BUTTON, .name = "pause", .on_click = ActWorldToggleSim },
{ .kind = DITEM_COND, .on_success = CondIsWorldPaused, .skip = 6 },
{ .kind = DITEM_BUTTON, .name = "resume", .on_click = ActWorldToggleSim },
{ .kind = DITEM_GAP },
{ .kind = DITEM_TEXT, .name = "step size", .proc = DrawWorldStepSize },
{ .kind = DITEM_BUTTON, .name = "single-step", .on_click = ActWorldStep },
{ .kind = DITEM_BUTTON, .name = "increment step size", .on_click = ActWorldIncrementSimStepSize },
{ .kind = DITEM_BUTTON, .name = "decrement step size", .on_click = ActWorldDecrementSimStepSize },
{ .kind = DITEM_END },
},
},
@ -131,14 +149,25 @@ static debug_item items[] = {
.list = {
.is_collapsed = true,
.items = (debug_item[]) {
{ .kind = DITEM_BUTTON, .name = "spawn car", .on_click = ActSpawnCar },
{
.kind = DITEM_LIST,
.name = "spawn item",
.list = {
.items = (debug_item[]) {
{ .kind = DITEM_TEXT, .name = "selected", .proc = DrawSelectedSpawnItem },
{ .kind = DITEM_BUTTON, .name = "Previous", .on_click = ActSpawnItemPrev },
{ .kind = DITEM_BUTTON, .name = "Next", .on_click = ActSpawnItemNext },
{ .kind = DITEM_BUTTON, .name = "Spawn <", .on_click = ActSpawnSelItem },
{ .kind = DITEM_END },
},
.is_collapsed = false
}
},
{ .kind = DITEM_BUTTON, .name = "spawn car", .on_click = ActSpawnCar },
{ .kind = DITEM_BUTTON, .name = "place ice rink", .on_click = ActPlaceIceRink },
{ .kind = DITEM_BUTTON, .name = "erase world changes", .on_click = ActEraseWorldChanges },
{ .kind = DITEM_BUTTON, .name = "spawn circling driver", .on_click = ActSpawnCirclingDriver },
{ .kind = DITEM_BUTTON, .name = "spawn icemaker item", .on_click = ActSpawnIcemaker },
{ .kind = DITEM_BUTTON, .name = "spawn chest", .on_click = ActSpawnChest },
{ .kind = DITEM_BUTTON, .name = "spawn belt", .on_click = ActSpawnBelt },
{
{
.kind = DITEM_LIST,
.name = "demo npcs",
.list = {
@ -164,13 +193,13 @@ static debug_item items[] = {
.items = (debug_item[]) {
{ .kind = DITEM_COND, .on_success = CondClientDisconnected },
{ .kind = DITEM_TEXT, .name = "status", .proc = DrawLiteral, .text = "disconnected" },
{ .kind = DITEM_COND, .on_success = CondClientConnected },
{ .kind = DITEM_TEXT, .name = "status", .proc = DrawLiteral, .text = "connected" },
{ .kind = DITEM_COND, .on_success = CondClientConnected },
{ .kind = DITEM_TEXT, .proc = DrawNetworkStats },
{ .kind = DITEM_END },
},
},
@ -184,30 +213,30 @@ static debug_item items[] = {
.items = (debug_item[]) {
{ .kind = DITEM_TEXT, .name = "macro", .proc = DrawReplayFileName },
{ .kind = DITEM_TEXT, .name = "samples", .proc = DrawReplaySamples },
{ .kind = DITEM_COND, .on_success = CondReplayDataPresentAndNotPlaying },
{ .kind = DITEM_BUTTON, .name = "replay", .on_click = ActReplayRun },
{ .kind = DITEM_COND, .on_success = CondReplayStatusOff },
{ .kind = DITEM_BUTTON, .name = "record", .on_click = ActReplayBegin },
{ .kind = DITEM_COND, .on_success = CondReplayStatusOn },
{ .kind = DITEM_BUTTON, .name = "stop", .on_click = ActReplayEnd },
{ .kind = DITEM_COND, .on_success = CondReplayIsPlaying },
{ .kind = DITEM_BUTTON, .name = "stop", .on_click = ActReplayEnd },
{ .kind = DITEM_COND, .on_success = CondReplayIsNotPlayingOrRecordsNotClear },
{ .kind = DITEM_BUTTON, .name = "clear", .on_click = ActReplayClear },
{ .kind = DITEM_GAP },
{ .kind = DITEM_COND, .on_success = CondReplayIsNotPlaying, .skip = 4 },
{ .kind = DITEM_BUTTON, .name = "new", .on_click = ActReplayNew },
{ .kind = DITEM_BUTTON, .name = "load", .on_click = ActReplayLoad },
{ .kind = DITEM_BUTTON, .name = "save", .on_click = ActReplaySave },
{ .kind = DITEM_BUTTON, .name = "save as...", .on_click = ActReplaySaveAs },
{ .kind = DITEM_END },
},
.is_collapsed = true,
@ -226,12 +255,27 @@ static debug_item items[] = {
{ .kind = DITEM_RAW, .val = PROF_RENDER, .proc = DrawProfilerDelta },
{ .kind = DITEM_RAW, .val = PROF_UPDATE_SYSTEMS, .proc = DrawProfilerDelta },
{ .kind = DITEM_RAW, .val = PROF_ENTITY_LERP, .proc = DrawProfilerDelta },
{ .kind = DITEM_RAW, .val = PROF_INTEGRATE_POS, .proc = DrawProfilerDelta },
{ .kind = DITEM_RAW, .val = PROF_INTEGRATE_POS, .proc = DrawProfilerDelta },
{ .kind = DITEM_RAW, .val = PROF_PHYS_BLOCK_COLS, .proc = DrawProfilerDelta },
{ .kind = DITEM_RAW, .val = PROF_PHYS_BODY_COLS, .proc = DrawProfilerDelta },
{ .kind = DITEM_RAW, .val = PROF_RENDER_PUSH_AND_SORT_ENTRIES, .proc = DrawProfilerDelta },
{ .kind = DITEM_END },
},
.is_collapsed = 1
}
},
},
{
.kind = DITEM_LIST,
.name = "tools",
.list = {
.items = (debug_item[]) {
{ .kind = DITEM_TOOL, .name = "asset inspector", .tool = { .is_open = 0, .on_draw = ToolAssetInspector } },
{ .kind = DITEM_TOOL, .name = "entity inspector", .tool = { .is_open = 0, .on_draw = ToolEntityInspector } },
{ .kind = DITEM_END },
},
.is_collapsed = 0
}
},
#if !defined(PLATFORM_WEB)
{
.kind = DITEM_BUTTON,
@ -253,7 +297,7 @@ debug_draw_result debug_draw_list(debug_item *list, float xpos, float ypos, bool
}break;
case DITEM_COND: {
ZPL_ASSERT(it->on_success);
if (!it->on_success()) {
it += it->skip ? it->skip : 1;
}
@ -267,15 +311,15 @@ debug_draw_result debug_draw_list(debug_item *list, float xpos, float ypos, bool
if (is_btn_pressed(xpos, ypos, it->name_width, DBG_FONT_SIZE, &color)) {
it->list.is_collapsed = !it->list.is_collapsed;
}
UIDrawText(it->name, xpos, ypos, DBG_FONT_SIZE, color);
ypos += DBG_FONT_SPACING;
if (it->list.is_collapsed) break;
debug_draw_result res = debug_draw_list(it->list.items, xpos+DBG_LIST_XPOS_OFFSET, ypos, is_shadow);
ypos = res.y;
}break;
case DITEM_TEXT: {
if (it->name) {
char const *text = TextFormat("%s: ", it->name);
@ -285,18 +329,18 @@ debug_draw_result debug_draw_list(debug_item *list, float xpos, float ypos, bool
UIDrawText(text, xpos, ypos, DBG_FONT_SIZE, RAYWHITE);
ZPL_ASSERT(it->proc);
}
debug_draw_result res = it->proc(it, xpos + it->name_width, ypos);
ypos = res.y;
}break;
case DITEM_RAW: {
ZPL_ASSERT(it->proc);
debug_draw_result res = it->proc(it, xpos, ypos);
ypos = res.y;
}break;
case DITEM_BUTTON: {
char const *text = TextFormat("> %s", it->name);
if (it->name_width == 0) {
@ -306,15 +350,15 @@ debug_draw_result debug_draw_list(debug_item *list, float xpos, float ypos, bool
if (is_btn_pressed(xpos, ypos, it->name_width, DBG_FONT_SIZE, &color) && it->on_click) {
it->on_click();
}
if (!it->on_click) {
color = GRAY;
}
debug_draw_result res = DrawColoredText(xpos, ypos, text, color);
ypos = res.y;
}break;
case DITEM_SLIDER: {
ZPL_ASSERT(it->slider.min != it->slider.max);
char const *text = TextFormat("%s: ", it->name);
@ -323,33 +367,65 @@ debug_draw_result debug_draw_list(debug_item *list, float xpos, float ypos, bool
}
UIDrawText(text, xpos, ypos, DBG_FONT_SIZE, RAYWHITE);
xpos += it->name_width;
DrawRectangleLines((int)xpos, (int)ypos, 100, DBG_FONT_SIZE, RAYWHITE);
float stick_x = xpos + ((it->slider.val / it->slider.max) * 100.0f) - 5.0f;
DrawRectangle((int)stick_x, (int)ypos, 10, DBG_FONT_SIZE, RED);
xpos += 100.0f + 5.0f;
DrawFloat(xpos, ypos, it->slider.val);
ypos += DBG_FONT_SPACING;
}break;
case DITEM_TOOL: {
char const *text = TextFormat("> %s", it->name);
if (it->name_width == 0) {
it->name_width = (float)UIMeasureText(text, DBG_FONT_SIZE);
}
Color color = RAYWHITE;
if (is_btn_pressed(xpos, ypos, it->name_width, DBG_FONT_SIZE, &color)) {
it->tool.is_open ^= 1;
}
debug_draw_result res = DrawColoredText(xpos, ypos, text, color);
ypos = res.y;
if (it->tool.is_open) {
if (is_shadow_rendered) break;
it->tool.on_draw();
}
} break;
default: {
}break;
}
}
return (debug_draw_result){xpos, ypos};
}
void debug_draw(void) {
// NOTE(zaklaus): Flush old debug samples
debug_draw_flush();
set_style(dev_ui, THEME_RED);
static zpl_u8 first_run=0;
if (!first_run) {
first_run = 1;
ActSpawnItemNext();
// Initialize Nuklear ctx
dev_ui = InitNuklear(10);
}
UpdateNuklear(dev_ui);
float xpos = debug_xpos;
float ypos = debug_ypos;
// NOTE(zaklaus): move debug ui
{
debug_area_status area = check_mouse_area(xpos, ypos, DBG_CTRL_HANDLE_DIM, DBG_CTRL_HANDLE_DIM);
@ -359,19 +435,19 @@ void debug_draw(void) {
color = RED;
is_handle_ctrl_held = 1;
}
if (is_handle_ctrl_held) {
debug_xpos = xpos = (float)(GetMouseX() - DBG_CTRL_HANDLE_DIM/2);
debug_ypos = ypos = (float)(GetMouseY() - DBG_CTRL_HANDLE_DIM/2);
if (area == DAREA_PRESS) {
is_handle_ctrl_held = 0;
}
}
DrawRectangle((int)xpos, (int)ypos, DBG_CTRL_HANDLE_DIM, DBG_CTRL_HANDLE_DIM, color);
}
// NOTE(zaklaus): toggle debug ui
{
Color color = BLUE;
@ -385,18 +461,20 @@ void debug_draw(void) {
}
DrawPoly((Vector2){xpos+DBG_CTRL_HANDLE_DIM/2, ypos+15+DBG_CTRL_HANDLE_DIM/2}, 3, 6.0f,is_debug_open ? 0.0f : 180.0f, color);
}
if (is_debug_open) {
xpos += 15;
debug_draw_list(items, xpos+DBG_SHADOW_OFFSET_XPOS, ypos+DBG_SHADOW_OFFSET_YPOS, 1); // NOTE(zaklaus): draw shadow
debug_draw_list(items, xpos, ypos, 0);
}
DrawNuklear(dev_ui);
}
debug_area_status check_mouse_area(float xpos, float ypos, float w, float h) {
if (is_shadow_rendered) return DAREA_OUTSIDE;
bool is_inside = CheckCollisionPointRec(GetMousePosition(), (Rectangle){xpos, ypos, w, h});
if (is_inside) {
return IsMouseButtonReleased(MOUSE_LEFT_BUTTON) ? DAREA_PRESS : IsMouseButtonDown(MOUSE_LEFT_BUTTON) ? DAREA_HELD : DAREA_HOVER;
}
@ -415,34 +493,34 @@ bool is_btn_pressed(float xpos, float ypos, float w, float h, Color *color) {
} else if (area == DAREA_HELD) {
*color = RED;
}
return false;
}
static inline
static inline
void UIDrawText(const char *text, float posX, float posY, int fontSize, Color color) {
// Check if default font has been loaded
if (GetFontDefault().texture.id != 0) {
Vector2 position = { (float)posX , (float)posY };
int defaultFontSize = 10; // Default Font chars height in pixel
int new_spacing = fontSize/defaultFontSize;
DrawTextEx(GetFontDefault(), text, position, (float)fontSize , (float)new_spacing , is_shadow_rendered ? BLACK : color);
}
}
static inline
static inline
int UIMeasureText(const char *text, int fontSize) {
Vector2 vec = { 0.0f, 0.0f };
// Check if default font has been loaded
if (GetFontDefault().texture.id != 0) {
int defaultFontSize = 10; // Default Font chars height in pixel
int new_spacing = fontSize/defaultFontSize;
vec = MeasureTextEx(GetFontDefault(), text, (float)fontSize, (float)new_spacing);
}
return (int)vec.x;
}

View File

@ -1,8 +1,10 @@
#include "debug/debug_ui.h"
#include "dev/debug_ui.h"
#include "world/blocks.h"
#include "ents/items.h"
#include "models/items.h"
#include "net/network.h"
#include "models/entity.h"
void
ActExitGame(void) {
game_request_close();
@ -10,62 +12,54 @@ ActExitGame(void) {
void
ActSpawnCar(void) {
ecs_entity_t e = vehicle_spawn();
ecs_entity_t e = vehicle_spawn(EVEH_CAR);
ecs_entity_t plr = camera_get().ent_id;
Position const* origin = ecs_get(world_ecs(), plr, Position);
Position * dest = ecs_get_mut(world_ecs(), e, Position);
*dest = *origin;
entity_set_position(e, dest->x, dest->y);
debug_replay_special_action(RPKIND_SPAWN_CAR);
}
void
ActSpawnIcemaker(void) {
ecs_entity_t e = item_spawn(ASSET_DEMO_ICEMAKER, 32);
ecs_entity_t plr = camera_get().ent_id;
Position const* origin = ecs_get(world_ecs(), plr, Position);
Position * dest = ecs_get_mut(world_ecs(), e, Position);
*dest = *origin;
entity_set_position(e, dest->x, dest->y);
debug_replay_special_action(RPKIND_SPAWN_ICEMAKER_ITEM);
ActSpawnItemPrev(void) {
while (true) {
--sel_item_id;
item_id id = item_find_no_proxy(sel_item_id);
if (sel_item_id > 0 && id != ASSET_INVALID && (item_get_usage(id) != UKIND_PROXY)) {
break;
}
}
}
void
ActSpawnChest(void) {
ecs_entity_t e = item_spawn(ASSET_CHEST, 32);
ecs_entity_t plr = camera_get().ent_id;
Position const* origin = ecs_get(world_ecs(), plr, Position);
Position * dest = ecs_get_mut(world_ecs(), e, Position);
*dest = *origin;
entity_set_position(e, dest->x, dest->y);
debug_replay_special_action(RPKIND_SPAWN_CHEST);
ActSpawnItemNext(void) {
while (true) {
++sel_item_id;
item_id id = item_find_no_proxy(sel_item_id);
if (sel_item_id > 0 && id != ASSET_INVALID && (item_get_usage(id) != UKIND_PROXY)) {
break;
}
}
}
void
ActSpawnBelt(void) {
ecs_entity_t e = item_spawn(ASSET_BELT, 999);
ActSpawnSelItem(void) {
ecs_entity_t e = item_spawn(sel_item_id, 32);
ecs_entity_t plr = camera_get().ent_id;
Position const* origin = ecs_get(world_ecs(), plr, Position);
Position * dest = ecs_get_mut(world_ecs(), e, Position);
*dest = *origin;
entity_set_position(e, dest->x, dest->y);
debug_replay_special_action(RPKIND_SPAWN_BELT);
entity_set_position(e, origin->x, origin->y);
}
void
ActSpawnCirclingDriver(void) {
ecs_entity_t plr = camera_get().ent_id;
ecs_entity_t ve = vehicle_spawn();
ecs_entity_t ve = vehicle_spawn(EVEH_CAR);
ecs_entity_t e = entity_spawn(EKIND_DEMO_NPC);
Position const *origin = ecs_get(world_ecs(), plr, Position);
Position *veh_dest = ecs_get_mut(world_ecs(), ve, Position);
Position *dest = ecs_get_mut(world_ecs(), e, Position);
@ -73,16 +67,16 @@ ActSpawnCirclingDriver(void) {
*dest = *origin;
entity_set_position(ve, veh_dest->x, veh_dest->y);
entity_set_position(e, dest->x, dest->y);
Input *input = ecs_get_mut(world_ecs(), e, Input);
zpl_zero_item(input);
input->x = input->y = 1.0f;
Vehicle *veh = ecs_get_mut(world_ecs(), ve, Vehicle);
veh->seats[0] = e;
ecs_set(world_ecs(), e, IsInVehicle, { .veh = ve });
debug_replay_special_action(RPKIND_SPAWN_CIRCLING_DRIVER);
}
@ -92,14 +86,14 @@ ActPlaceIceRink(void) {
block_id watr_id = blocks_find(ASSET_WATER);
Position const *p = ecs_get(world_ecs(), plr, Position);
float const bs = WORLD_BLOCK_SIZE;
for (int y = 0; y < 100; y++) {
for (int x = 0; x < 100; x++) {
world_block_lookup l = world_block_from_realpos((p->x - (x*bs)/2.0f), p->y - (y*bs)/2.0f);
world_chunk_place_block(l.chunk_id, l.id, watr_id);
}
}
debug_replay_special_action(RPKIND_PLACE_ICE_RINK);
}
@ -108,13 +102,13 @@ ActEraseWorldChanges(void) {
ecs_entity_t plr = camera_get().ent_id;
Position const *p = ecs_get(world_ecs(), plr, Position);
float const bs = WORLD_BLOCK_SIZE;
for (int y = 0; y < 100; y++) {
for (int x = 0; x < 100; x++) {
world_chunk_destroy_block((p->x - (x*bs)/2.0f), (p->y - (y*bs)/2.0f), true);
}
}
debug_replay_special_action(RPKIND_PLACE_ERASE_CHANGES);
}
@ -181,22 +175,22 @@ void
ActReplaySaveAs(void) {
if (!records) return;
char const *workdir = GetWorkingDirectory();
sfd_Options sfd = {
.title = "Save Macro",
.path = "art",
.filter_name = "eco2d Macro",
.filter = "*.dem",
};
char const *path = sfd_save_dialog(&sfd);
ChangeDirectory(workdir);
if (path) {
zpl_strcpy(replay_filename, zpl_bprintf("%s.dem", path));
debug_replay_store();
}
}
void
@ -210,17 +204,17 @@ ActReplaySave(void) {
void
ActReplayLoad(void) {
char const *workdir = GetWorkingDirectory();
sfd_Options sfd = {
.title = "Load Macro",
.path = "art",
.filter_name = "eco2d Macro",
.filter = "*.dem",
};
char const *path = sfd_open_dialog(&sfd);
ChangeDirectory(workdir);
if (path) {
zpl_zero_size(replay_filename, sizeof(replay_filename));
zpl_strcpy(replay_filename, path);
@ -236,18 +230,17 @@ void
ActSpawnDemoNPCs(void) {
if (!demo_npcs) zpl_array_init(demo_npcs, zpl_heap());
if (zpl_array_count(demo_npcs) >= 100000) return;
for (uint32_t i = 0; i < 1000; i++) {
uint64_t e = entity_spawn(EKIND_DEMO_NPC);
ecs_add(world_ecs(), e, DemoNPC);
uint64_t e = entity_spawn_id(ASSET_CREATURE);
Position *pos = ecs_get_mut(world_ecs(), e, Position);
pos->x=(float)(rand() % world_dim());
pos->y=(float)(rand() % world_dim());
pos->y=(float)(rand() % world_dim());
Velocity *v = ecs_get_mut(world_ecs(), e, Velocity);
v->x = (float)((rand()%3-1) * 10);
v->y = (float)((rand()%3-1) * 10);
zpl_array_append(demo_npcs, e);
}
}
@ -255,9 +248,9 @@ ActSpawnDemoNPCs(void) {
void
ActDespawnDemoNPCs(void) {
if (!demo_npcs) return;
entity_batch_despawn(demo_npcs, zpl_array_count(demo_npcs));
zpl_array_free(demo_npcs);
demo_npcs = 0;
}

View File

@ -0,0 +1,143 @@
// debug tools written with Nuklear UI
#include "models/assets.h"
#include "world/blocks.h"
#include "models/items.h"
extern void tooltip_show_cursor(const char* name);
extern const char *tooltip_find_desc_contents(const char *name);
void ToolAssetInspector(void) {
if (nk_begin(dev_ui, "Asset Inspector", nk_rect(400, 100, 240, 800),
NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_SCALABLE| NK_WINDOW_TITLE))
{
for (int i = 0; i < MAX_ASSETS; i++) {
uint16_t idx = assets_find(i);
if (idx != ASSET_INVALID && nk_tree_push_id(dev_ui, NK_TREE_TAB, asset_names[i], NK_MINIMIZED, i)) {
{
// draw kind
const char *asset_kind_name = assets_get_kind_name(idx);
nk_labelf(dev_ui, NK_TEXT_LEFT, "kind: %s", asset_kind_name);
nk_labelf(dev_ui, NK_TEXT_LEFT, "spawnable entity: %s", entity_spawn_provided(i) ? "true" : "false");
if (nk_button_label(dev_ui, "show tooltip")) {
tooltip_show_cursor(asset_names[i]);
}
if (nk_button_label(dev_ui, "spawn at me")) {
uint64_t e = entity_spawn_id(i);
ecs_entity_t plr = camera_get().ent_id;
Position const* origin = ecs_get(world_ecs(), plr, Position);
entity_set_position(e, origin->x, origin->y);
}
// draw help text
if (nk_tree_push_id(dev_ui, NK_TREE_NODE, "description", NK_MINIMIZED, i)) {
{
const char *desc = tooltip_find_desc_contents(asset_names[i]);
if (desc) {
nk_layout_row_dynamic(dev_ui, 0, 1);
nk_label_wrap(dev_ui, desc);
}
}
nk_tree_pop(dev_ui);
}
// draw block
block_id blk_id = blocks_find(i);
if (blk_id != 0xF) {
if (nk_tree_push_id(dev_ui, NK_TREE_NODE, "block", NK_MINIMIZED, i)) {
{
nk_labelf(dev_ui, NK_TEXT_LEFT, "symbol: %s", zpl_bprintf("%c", blocks_get_symbol(blk_id)));
nk_labelf(dev_ui, NK_TEXT_LEFT, "flags: %u", blocks_get_flags(blk_id));
nk_labelf(dev_ui, NK_TEXT_LEFT, "drag: %f", blocks_get_drag(blk_id));
nk_labelf(dev_ui, NK_TEXT_LEFT, "friction: %f", blocks_get_friction(blk_id));
nk_labelf(dev_ui, NK_TEXT_LEFT, "bounce: %f", blocks_get_bounce(blk_id));
nk_labelf(dev_ui, NK_TEXT_LEFT, "velx: %f", blocks_get_velx(blk_id));
nk_labelf(dev_ui, NK_TEXT_LEFT, "vely: %f", blocks_get_vely(blk_id));
}
nk_tree_pop(dev_ui);
}
}
// draw item
item_id it_id = item_find_no_proxy(i);
if (it_id != ASSET_INVALID) {
if (nk_tree_push_id(dev_ui, NK_TREE_NODE, "item", NK_MINIMIZED, i)) {
{
item_desc it = item_get_desc(it_id);
if (nk_button_label(dev_ui, "spawn")) {
ecs_entity_t e = item_spawn(i, it.max_quantity);
ecs_entity_t plr = camera_get().ent_id;
Position const* origin = ecs_get(world_ecs(), plr, Position);
entity_set_position(e, origin->x, origin->y);
}
nk_labelf(dev_ui, NK_TEXT_LEFT, "usage: %d", it.usage);
nk_labelf(dev_ui, NK_TEXT_LEFT, "attachment: %d", it.attachment);
nk_labelf(dev_ui, NK_TEXT_LEFT, "max quantity: %d", it.max_quantity);
nk_labelf(dev_ui, NK_TEXT_LEFT, "has storage: %s", it.has_storage ? "true" : "false");
// todo: draw item-specific data
}
nk_tree_pop(dev_ui);
}
}
}
nk_tree_pop(dev_ui);
}
}
nk_end(dev_ui);
}
}
void ToolEntityInspector(void) {
if (nk_begin(dev_ui, "Entity Inspector", nk_rect(660, 100, 240, 800),
NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_SCALABLE| NK_WINDOW_TITLE))
{
static ecs_query_t *q = 0;
if (!q) {
q = ecs_query(world_ecs(), {
.filter.terms = {
{ .id = ecs_id(Position) },
{ .id = ecs_id(Classify), .inout = EcsIn }
}
});
}
ecs_iter_t it = ecs_query_iter(world_ecs(), q);
while (ecs_query_next(&it)) {
Position *p = ecs_field(&it, Position, 1);
const Classify *c = ecs_field(&it, Classify, 2);
for (int i = 0; i < it.count; i++) {
if (nk_tree_push_id(dev_ui, NK_TREE_NODE, zpl_bprintf("%lld [%s]", it.entities[i], class_names[c[i].id]), NK_MINIMIZED, (int)it.entities[i])) {
{
nk_label(dev_ui, "position:", NK_TEXT_LEFT);
nk_property_float(dev_ui, "#x:", ZPL_F32_MIN, &p[i].x, ZPL_F32_MAX, 0.1f, 0.2f);
nk_property_float(dev_ui, "#y:", ZPL_F32_MIN, &p[i].y, ZPL_F32_MAX, 0.1f, 0.2f);
if (nk_button_label(dev_ui, "teleport to")) {
ecs_entity_t plr = camera_get().ent_id;
Position const* origin = ecs_get(world_ecs(), it.entities[i], Position);
entity_set_position(plr, origin->x, origin->y);
}
if (nk_button_label(dev_ui, "teleport here")) {
ecs_entity_t plr = camera_get().ent_id;
Position const* origin = ecs_get(world_ecs(), plr, Position);
entity_set_position(it.entities[i], origin->x, origin->y);
}
}
nk_tree_pop(dev_ui);
}
}
}
nk_end(dev_ui);
}
}

View File

@ -1,4 +1,4 @@
#include "debug/debug_ui.h"
#include "dev/debug_ui.h"
#include "raylib.h"
#include "platform/platform.h"
#include "net/network.h"
@ -6,79 +6,96 @@
//~ NOTE(zaklaus): helpers
static inline debug_draw_result
static inline debug_draw_result
DrawFloat(float xpos, float ypos, float val) {
char const *text = TextFormat("%.02f\n", val);
UIDrawText(text, xpos, ypos, DBG_FONT_SIZE, RAYWHITE);
return (debug_draw_result){.x = xpos + UIMeasureText(text, DBG_FONT_SIZE), .y = ypos + DBG_FONT_SPACING};
}
static inline debug_draw_result
static inline debug_draw_result
DrawColoredText(float xpos, float ypos, char const *text, Color color) {
ZPL_ASSERT(text);
UIDrawText(text, xpos, ypos, DBG_FONT_SIZE, color);
char const *p = text;
uint8_t newlines = 1;
do {
if (*p == '\n')
++newlines;
} while (*p++ != 0);
return (debug_draw_result){.x = xpos + UIMeasureText(text, DBG_FONT_SIZE), .y = ypos + DBG_FONT_SPACING*newlines};
}
static inline debug_draw_result
static inline debug_draw_result
DrawFormattedText(float xpos, float ypos, char const *text) {
return DrawColoredText(xpos, ypos, text, RAYWHITE);
}
//~ NOTE(zaklaus): widgets
static inline debug_draw_result
static inline debug_draw_result
DrawCameraPos(debug_item *it, float xpos, float ypos) {
(void)it;
camera cam = camera_get();
return DrawFormattedText(xpos, ypos, TextFormat("%d %d", (int)(cam.x/WORLD_BLOCK_SIZE), (int)(cam.y/WORLD_BLOCK_SIZE)));
}
static inline debug_draw_result
static inline debug_draw_result
DrawChunkPos(debug_item *it, float xpos, float ypos) {
float mx, my;
platform_get_block_realpos(&mx, &my);
int csize = world_chunk_size();
return DrawFormattedText(xpos, ypos, TextFormat("%d %d", (int)(mx/WORLD_BLOCK_SIZE/csize), (int)(my/WORLD_BLOCK_SIZE/csize)));
}
static inline debug_draw_result
DrawBlockPos(debug_item *it, float xpos, float ypos) {
float mx, my;
platform_get_block_realpos(&mx, &my);
return DrawFormattedText(xpos, ypos, TextFormat("%d %d", (int)(mx/WORLD_BLOCK_SIZE), (int)(my/WORLD_BLOCK_SIZE)));
}
static inline debug_draw_result
DrawUnmeasuredTime(debug_item *it, float xpos, float ypos) {
(void)it;
float total_time = (float)profiler_delta(PROF_TOTAL_TIME);
float acc_time = (float)profiler_delta(PROF_MAIN_LOOP);
return DrawFormattedText(xpos, ypos, TextFormat("%.02f ms", (total_time-acc_time) * 1000.0f));
}
static inline debug_draw_result
static inline debug_draw_result
DrawDeltaTime(debug_item *it, float xpos, float ypos) {
(void)it;
float dt = GetFrameTime();
return DrawFormattedText(xpos, ypos, TextFormat("%.02f (%.02f fps)", dt * 1000.0f, 1.0f/dt));
}
static inline debug_draw_result
static inline debug_draw_result
DrawZoom(debug_item *it, float xpos, float ypos) {
(void)it;
return DrawFloat(xpos, ypos, platform_zoom_get());
}
static inline debug_draw_result
static inline debug_draw_result
DrawLiteral(debug_item *it, float xpos, float ypos) {
ZPL_ASSERT(it->text);
return DrawFormattedText(xpos, ypos, it->text);
}
static inline debug_draw_result
static inline debug_draw_result
DrawProfilerDelta(debug_item *it, float xpos, float ypos) {
float dt = (float)profiler_delta(it->val);
return DrawFormattedText(xpos, ypos, TextFormat("%s: %.02f ms", profiler_name(it->val), dt * 1000.0f));
}
static inline debug_draw_result
static inline debug_draw_result
DrawReplaySamples(debug_item *it, float xpos, float ypos) {
(void)it;
size_t cnt = 0;
@ -88,7 +105,7 @@ DrawReplaySamples(debug_item *it, float xpos, float ypos) {
return DrawFormattedText(xpos, ypos, TextFormat("%d of %d", record_pos, cnt));
}
static inline debug_draw_result
static inline debug_draw_result
DrawReplayFileName(debug_item *it, float xpos, float ypos) {
(void)it;
return DrawFormattedText(xpos, ypos, TextFormat("%s", replay_filename[0] ? replay_filename : "<unnamed>"));
@ -96,41 +113,46 @@ DrawReplayFileName(debug_item *it, float xpos, float ypos) {
// NOTE(zaklaus): demo npcs
static inline debug_draw_result
static inline debug_draw_result
DrawDemoNPCCount(debug_item *it, float xpos, float ypos) {
(void)it;
return DrawFormattedText(xpos, ypos, TextFormat("%d", demo_npcs ? zpl_array_count(demo_npcs) : 0));
}
static inline debug_draw_result
DrawSelectedSpawnItem(debug_item *it, float xpos, float ypos) {
(void)it;
return DrawFormattedText(xpos, ypos, TextFormat("%s", asset_names[sel_item_id]));
}
// NOTE(zaklaus): world simulation
static inline debug_draw_result
// NOTE(zaklaus): world simulation
static inline debug_draw_result
DrawWorldStepSize(debug_item *it, float xpos, float ypos) {
(void)it;
return DrawFormattedText(xpos, ypos, TextFormat("%d ms", (int16_t)(sim_step_size*1000.f)));
}
// NOTE(zaklaus): network stats
static inline debug_draw_result
static inline debug_draw_result
DrawNetworkStats(debug_item *it, float xpos, float ypos) {
(void)it;
network_client_stats s = network_client_fetch_stats();
#define _kb(x) ((x) / 1024)
debug_draw_result r;
r = DrawFormattedText(xpos, ypos, TextFormat("recv total: %lld kb", _kb(s.total_received)));
r = DrawFormattedText(xpos, r.y, TextFormat("sent total: %lld kb", _kb(s.total_sent)));
r = DrawFormattedText(xpos, r.y, TextFormat("dn rate: %.02f kb/sec (%.02f kbit/sec)", _kb(s.incoming_bandwidth), _kb(s.incoming_bandwidth * 8.0f)));
r = DrawFormattedText(xpos, r.y, TextFormat("up rate: %.02f kb/sec (%.02f kbit/sec)", _kb(s.outgoing_bandwidth), _kb(s.outgoing_bandwidth * 8.0f)));
r = DrawFormattedText(xpos, r.y, TextFormat("packets sent: %lld", s.packets_sent));
r = DrawFormattedText(xpos, r.y, TextFormat("packets lost: %d (%.02f%%)", s.packets_lost, s.packet_loss));
r = DrawFormattedText(xpos, r.y, TextFormat("ping: %d ms", s.ping));
#undef _kb
return r;
}

View File

@ -1,41 +0,0 @@
#include "ecs/components.h"
ECS_COMPONENT_DECLARE(Vector2D);
ECS_COMPONENT_DECLARE(Position);
ECS_COMPONENT_DECLARE(Velocity);
ECS_COMPONENT_DECLARE(Chunk);
ECS_COMPONENT_DECLARE(Drawable);
ECS_COMPONENT_DECLARE(Input);
ECS_COMPONENT_DECLARE(ClientInfo);
ECS_COMPONENT_DECLARE(Health);
ECS_COMPONENT_DECLARE(Classify);
ECS_COMPONENT_DECLARE(Vehicle);
ECS_COMPONENT_DECLARE(IsInVehicle);
ECS_COMPONENT_DECLARE(ItemDrop);
ECS_COMPONENT_DECLARE(Inventory);
ECS_COMPONENT_DECLARE(ItemContainer);
ECS_COMPONENT_DECLARE(Device);
ECS_COMPONENT_DECLARE(DemoNPC);
ECS_COMPONENT_DECLARE(StreamInfo);
void ComponentsImport(ecs_world_t *ecs) {
ECS_MODULE(ecs, Components);
ECS_COMPONENT_DEFINE(ecs, Vector2D);
ECS_COMPONENT_DEFINE(ecs, Position);
ECS_COMPONENT_DEFINE(ecs, Velocity);
ECS_COMPONENT_DEFINE(ecs, Chunk);
ECS_COMPONENT_DEFINE(ecs, Drawable);
ECS_COMPONENT_DEFINE(ecs, Input);
ECS_COMPONENT_DEFINE(ecs, ClientInfo);
ECS_COMPONENT_DEFINE(ecs, Health);
ECS_COMPONENT_DEFINE(ecs, Classify);
ECS_COMPONENT_DEFINE(ecs, Vehicle);
ECS_COMPONENT_DEFINE(ecs, IsInVehicle);
ECS_COMPONENT_DEFINE(ecs, ItemDrop);
ECS_COMPONENT_DEFINE(ecs, Inventory);
ECS_COMPONENT_DEFINE(ecs, ItemContainer);
ECS_COMPONENT_DEFINE(ecs, Device);
ECS_COMPONENT_DEFINE(ecs, DemoNPC);
ECS_COMPONENT_DEFINE(ecs, StreamInfo);
}

View File

@ -1,143 +0,0 @@
#pragma once
#include "flecs/flecs.h"
#ifndef ecs_get_mut_if
#define ecs_get_mut_if(world, entity, component)\
(ecs_get(world, entity, component) ? ecs_get_mut(world, entity, component) : NULL)
#endif
#define ITEMS_INVENTORY_SIZE 9
#define ITEMS_CONTAINER_SIZE 16
typedef struct {
float x;
float y;
} Vector2D;
typedef struct {
uint32_t id;
int16_t x;
int16_t y;
uint8_t is_dirty;
} Chunk;
typedef struct {
uint16_t id;
} Drawable;
typedef Vector2D Position;
typedef Vector2D Velocity;
typedef struct {
float x;
float y;
float mx;
float my;
float bx;
float by;
uint8_t use;
uint8_t sprint;
uint8_t ctrl;
uint8_t pick;
uint8_t is_blocked;
ecs_entity_t pick_ent;
ecs_entity_t sel_ent;
// NOTE(zaklaus): inventory
ecs_entity_t storage_ent;
uint8_t storage_action;
uint8_t selected_item;
uint8_t storage_selected_item;
uint8_t drop;
uint8_t swap;
uint8_t swap_storage;
uint8_t swap_from;
uint8_t swap_to;
// NOTE(zaklaus): build mode
uint8_t num_placements;
float placements_x[20];
float placements_y[20];
uint8_t deletion_mode;
} Input;
typedef struct {
uintptr_t peer;
uint16_t view_id;
uint8_t active;
} ClientInfo;
typedef struct {
float hp;
float max_hp;
//NOTE(zaklaus): Intentionally global, to allow for creative use of damage combos
float pain_time;
float heal_time;
} Health;
typedef struct {
uint16_t id;
} Classify;
typedef struct {
uint64_t seats[4];
float force;
float heading;
float steer;
float wheel_base;
float speed;
float reverse_speed;
} Vehicle;
typedef struct {
ecs_entity_t veh;
} IsInVehicle;
typedef struct {
uint16_t kind;
uint32_t quantity;
float merger_time;
} ItemDrop;
typedef struct {
ItemDrop items[ITEMS_CONTAINER_SIZE];
float pickup_time;
} Inventory;
typedef struct {
ItemDrop items[ITEMS_CONTAINER_SIZE];
} ItemContainer;
typedef struct {
uint16_t asset;
} Device;
typedef struct {
double last_update;
double tick_delay;
} StreamInfo;
typedef struct {char _unused;} DemoNPC;
extern ECS_COMPONENT_DECLARE(Vector2D);
extern ECS_COMPONENT_DECLARE(Position);
extern ECS_COMPONENT_DECLARE(Velocity);
extern ECS_COMPONENT_DECLARE(Chunk);
extern ECS_COMPONENT_DECLARE(Drawable);
extern ECS_COMPONENT_DECLARE(Input);
extern ECS_COMPONENT_DECLARE(ClientInfo);
extern ECS_COMPONENT_DECLARE(Health);
extern ECS_COMPONENT_DECLARE(Classify);
extern ECS_COMPONENT_DECLARE(Vehicle);
extern ECS_COMPONENT_DECLARE(IsInVehicle);
extern ECS_COMPONENT_DECLARE(ItemDrop);
extern ECS_COMPONENT_DECLARE(Inventory);
extern ECS_COMPONENT_DECLARE(ItemContainer);
extern ECS_COMPONENT_DECLARE(Device);
extern ECS_COMPONENT_DECLARE(DemoNPC);
extern ECS_COMPONENT_DECLARE(StreamInfo);
void ComponentsImport(ecs_world_t *ecs);

View File

@ -1,16 +0,0 @@
#define DEMO_NPC_MOVE_SPEED 500
#define DEMO_NPC_STEER_SPEED 300
#include <math.h>
void DemoNPCMoveAround(ecs_iter_t *it) {
Velocity *v = ecs_field(it, Velocity, 1);
for (int i = 0; i < it->count; i++) {
float d = zpl_quake_rsqrt(v[i].x*v[i].x + v[i].y*v[i].y);
v[i].x += (v[i].x*d*DEMO_NPC_MOVE_SPEED*safe_dt(it) + zpl_cos(zpl_to_radians((float)(rand()%360)))*DEMO_NPC_STEER_SPEED*safe_dt(it));
v[i].y += (v[i].y*d*DEMO_NPC_MOVE_SPEED*safe_dt(it) + zpl_sin(zpl_to_radians((float)(rand()%360)))*DEMO_NPC_STEER_SPEED*safe_dt(it));
entity_wake(it->entities[i]);
}
}

View File

@ -1,355 +0,0 @@
#include "ents/items.h"
#define ITEM_PICK_RADIUS 25.0f
#define ITEM_MERGER_RADIUS 75.0f
#define ITEM_ATTRACT_RADIUS 75.0f
#define ITEM_ATTRACT_FORCE .98f
#define ITEM_CONTAINER_REACH_RADIUS 105.0f
void PickItem(ecs_iter_t *it) {
Position *p = ecs_field(it, Position, 2);
Inventory *inv = ecs_field(it, Inventory, 3);
for (int i = 0; i < it->count; i++) {
if (inv[i].pickup_time > game_time()) continue;
size_t ents_count;
int64_t *ents = world_chunk_query_entities(it->entities[i], &ents_count, 2);
for (size_t j = 0; j < ents_count; j++) {
ItemDrop *drop = 0;
if ((drop = ecs_get_mut_if(it->world, ents[j], ItemDrop))) {
Position *p2 = ecs_get_mut(it->world, ents[j], Position);
Velocity *v2 = ecs_get_mut(it->world, ents[j], Velocity);
float dx = p2->x - p[i].x;
float dy = p2->y - p[i].y;
float range = zpl_sqrt(dx*dx + dy*dy);
if (range <= ITEM_PICK_RADIUS) {
uint16_t drop_id = item_find(drop->kind);
for (size_t k = 0; k < ITEMS_INVENTORY_SIZE; k += 1) {
ItemDrop *item = &inv[i].items[k];
uint16_t item_id = item_find(item->kind);
if (item_id != ASSET_INVALID && (item->quantity == 0 || (item->quantity != 0 && item->kind == drop->kind)) && item->quantity < item_max_quantity(drop_id)) {
uint32_t picked_count = zpl_max(0, drop->quantity);
picked_count = zpl_clamp(picked_count, 0, item_max_quantity(drop_id) - item->quantity);
item->quantity += picked_count;
drop->quantity -= picked_count;
item->kind = drop->kind;
entity_wake(ents[j]);
if (drop->quantity == 0)
item_despawn(ents[j]);
break;
}
}
} else if (range <= ITEM_ATTRACT_RADIUS) {
v2->x = (p[i].x - p2->x) * ITEM_ATTRACT_FORCE;
v2->y = (p[i].y - p2->y) * ITEM_ATTRACT_FORCE;
}
}
}
}
}
#define ITEM_DROP_PICKUP_TIME 2.5f
#define ITEM_DROP_MERGER_TIME 6.5f
void DropItem(ecs_iter_t *it) {
Input *in = ecs_field(it, Input, 1);
Position *p = ecs_field(it, Position, 2);
Inventory *inv = ecs_field(it, Inventory, 3);
for (int i = 0; i < it->count; i++) {
if (!in[i].drop) continue;
ItemDrop *items = inv[i].items;
if (in[i].storage_action){
if (world_entity_valid(in[i].storage_ent)){
ItemContainer *ic = 0;
if ((ic = ecs_get_mut_if(it->world, in[i].storage_ent, ItemContainer))){
items = ic->items;
}else{
continue;
}
}else{
continue;
}
}
ItemDrop *item = &items[in[i].storage_action ? in[i].storage_selected_item : in[i].selected_item];
if (item->quantity <= 0)
continue;
uint32_t dropped_count = item->quantity;
if (in[i].sprint) {
dropped_count /= 2;
} else if (in[i].ctrl) {
dropped_count = dropped_count > 0 ? 1 : 0;
}
if (dropped_count == 0)
continue;
ecs_entity_t te = item_spawn(item->kind, dropped_count);
item->quantity -= dropped_count;
ItemDrop *d = ecs_get_mut(world_ecs(), te, ItemDrop);
*d = (ItemDrop){
.kind = item->kind,
.quantity = dropped_count,
.merger_time = game_time() + ITEM_DROP_MERGER_TIME,
};
Position *ipos = ecs_get_mut(it->world, te, Position);
*ipos = p[i];
Velocity *v = ecs_get_mut(it->world, te, Velocity);
v->x = in[i].mx * 800.0f;
v->y = in[i].my * 800.0f;
inv[i].pickup_time = game_time() + ITEM_DROP_PICKUP_TIME;
in[i].drop = false;
if (item->quantity == 0) {
item->kind = 0;
}
}
}
void MergeItems(ecs_iter_t *it) {
Position *p = ecs_field(it, Position, 1);
ItemDrop *id = ecs_field(it, ItemDrop, 2);
for (int i = 0; i < it->count; i += 1) {
ItemDrop *item = &id[i];
if (item->merger_time < game_time())
continue;
size_t ents_count;
int64_t *ents = world_chunk_query_entities(it->entities[i], &ents_count, 1);
for (size_t j = 0; j < ents_count; j++) {
ItemDrop *drop = 0;
if ((drop = ecs_get_mut_if(it->world, ents[j], ItemDrop))) {
if (drop->kind != item->kind || (ecs_entity_t)ents[j] == it->entities[i] || drop->quantity == 0 || item->quantity == 0)
continue;
Position const* p2 = ecs_get(it->world, ents[j], Position);
float dx = p2->x - (p[i].x);
float dy = p2->y - (p[i].y);
float range = zpl_sqrt(dx*dx + dy*dy);
if (range <= ITEM_MERGER_RADIUS) {
drop->quantity += item->quantity;
item_despawn(it->entities[i]);
break;
}
}
}
}
}
void SwapItems(ecs_iter_t *it) {
Input *in = ecs_field(it, Input, 1);
Inventory *inv = ecs_field(it, Inventory, 2);
for (int i = 0; i < it->count; i++) {
if (!in[i].swap) continue;
ItemDrop *items = inv[i].items;
if (in[i].storage_action){
if (world_entity_valid(in[i].storage_ent)){
ItemContainer *ic = 0;
if ((ic = ecs_get_mut_if(it->world, in[i].storage_ent, ItemContainer))){
items = ic->items;
}else{
continue;
}
}else{
continue;
}
}
ItemDrop *to = 0;
ItemDrop *from = 0;
if (in[i].swap_storage){
in[i].swap_storage = false;
if (in[i].storage_action){
from = &inv[i].items[in[i].swap_from];
to = &items[in[i].swap_to];
}else{
if (world_entity_valid(in[i].storage_ent)){
ItemContainer *ic = 0;
if ((ic = ecs_get_mut_if(it->world, in[i].storage_ent, ItemContainer))){
from = &ic->items[in[i].swap_from];
}else{
continue;
}
}else{
continue;
}
to = &items[in[i].swap_to];
}
}else{
from = &items[in[i].swap_from];
to = &items[in[i].swap_to];
}
ZPL_ASSERT(from && to);
uint16_t to_id = item_find(to->kind);
if (to == from) {
// NOTE(zaklaus): do nothing
} else if (to->kind == from->kind && to->quantity > 0) {
uint32_t swapped_count = from->quantity;
if (in[i].sprint) {
swapped_count /= 2;
} else if (in[i].ctrl) {
swapped_count = 1;
}
swapped_count = zpl_clamp(swapped_count, 0, item_max_quantity(to_id) - to->quantity);
to->quantity += swapped_count;
from->quantity -= swapped_count;
if (swapped_count == 0) {
ItemDrop tmp = *to;
*to = *from;
*from = tmp;
}
} else if ((in[i].ctrl || in[i].sprint) && to->quantity == 0 && from->quantity > 0) {
// NOTE(zaklaus): item split
uint32_t split_count = from->quantity / 2;
if (in[i].ctrl) {
split_count = 1;
}
to->quantity = split_count;
from->quantity -= split_count;
to->kind = from->kind;
} else {
ItemDrop tmp = *to;
*to = *from;
*from = tmp;
}
in[i].swap = false;
}
}
void UseItem(ecs_iter_t *it) {
Input *in = ecs_field(it, Input, 1);
Position *p = ecs_field(it, Position, 2);
Inventory *inv = ecs_field(it, Inventory, 3);
for (int i = 0; i < it->count; i++) {
if (!in[i].use && !in[i].num_placements) continue;
if (in[i].storage_action){
continue;
}
ItemDrop *item = &inv[i].items[in[i].selected_item];
uint16_t item_id = 0;
item_usage usage = UKIND_DELETE;
if (!in[i].deletion_mode){
item_id = item_find(item->kind);
usage = item_get_usage(item_id);
if (!item || item->quantity <= 0) continue;
}
if (!in[i].use && usage == UKIND_DELETE){
for (size_t j = 0; j < in[i].num_placements; j++) {
world_chunk_destroy_block(in[i].placements_x[j], in[i].placements_y[j], true);
}
}
else if (in[i].use && usage > UKIND_END_PLACE)
item_use(it->world, item, p[i], 0);
else if (in[i].num_placements > 0 && usage < UKIND_END_PLACE) {
asset_id ofs = 0;
if (item_get_place_directional(item_id) && in[i].num_placements >= 2) {
float p1x = in[i].placements_x[0];
float p1y = in[i].placements_y[0];
float p2x = in[i].placements_x[1];
float p2y = in[i].placements_y[1];
float sx = zpl_sign0(p2x-p1x);
float sy = zpl_sign0(p2y-p1y);
ofs = (sx < 0.0f) ? 1 : 2;
if (sx == 0.0f) {
ofs = (sy < 0.0f) ? 3 : 4;
}
} else if(item_get_place_directional(item_id)) {
// NOTE(zaklaus): ensure we pick the first variant
ofs = 1;
}
for (size_t j = 0; j < in[i].num_placements; j++) {
Position pos = {.x = in[i].placements_x[j], .y = in[i].placements_y[j]};
item_use(it->world, item, pos, ofs);
}
in[i].num_placements = 0;
}
entity_wake(it->entities[i]);
}
}
void InspectContainers(ecs_iter_t *it) {
Input *in = ecs_field(it, Input, 1);
for (int i = 0; i < it->count; ++i) {
if (!in[i].pick) continue;
if ((in[i].sel_ent && ecs_get(it->world, in[i].sel_ent, ItemContainer)) || !in[i].sel_ent)
in[i].storage_ent = in[i].sel_ent;
}
}
void HarvestIntoContainers(ecs_iter_t *it) {
ItemContainer *in = ecs_field(it, ItemContainer, 1);
Position *p = ecs_field(it, Position, 2);
for (int i = 0; i < it->count; ++i) {
// NOTE(zaklaus): find any item
size_t ents_count;
int64_t *ents = world_chunk_query_entities(it->entities[i], &ents_count, 0);
for (size_t j = 0; j < ents_count; j++) {
ItemDrop *drop = 0;
if ((drop = ecs_get_mut_if(it->world, ents[j], ItemDrop))) {
const Position *p2 = ecs_get(it->world, ents[j], Position);
float dx = p2->x - p[i].x;
float dy = p2->y - p[i].y;
float range = zpl_sqrt(dx*dx + dy*dy);
if (range <= ITEM_PICK_RADIUS) {
uint16_t drop_id = item_find(drop->kind);
for (size_t k = 0; k < ITEMS_CONTAINER_SIZE; k += 1) {
ItemDrop *item = &in->items[k];
uint16_t item_id = item_find(item->kind);
if (item_id != ASSET_INVALID && (item->quantity == 0 || (item->quantity != 0 && item->kind == drop->kind)) && item->quantity < item_max_quantity(drop_id)) {
uint32_t picked_count = zpl_max(0, drop->quantity);
picked_count = zpl_clamp(picked_count, 0, item_max_quantity(drop_id) - item->quantity);
item->quantity += picked_count;
drop->quantity -= picked_count;
item->kind = drop->kind;
entity_wake(ents[j]);
entity_wake(it->entities[i]);
if (drop->quantity == 0)
item_despawn(ents[j]);
}
}
}
}
}
}
}

View File

@ -1,226 +0,0 @@
#include "zpl.h"
#include "ecs/systems.h"
#include "ecs/components.h"
#include "world/world.h"
#include "world/blocks.h"
#include "platform/profiler.h"
#include "debug/debug_draw.h"
#include "core/game.h"
#define PHY_BLOCK_COLLISION 1
#define PHY_WALK_DRAG 4.23f
#define PHY_LOOKAHEAD(x) (zpl_sign(x)*16.0f)
#include "modules/system_onfoot.c"
#include "modules/system_demo.c"
#include "modules/system_vehicle.c"
#include "modules/system_items.c"
static inline float physics_correction(float x, float vx, float bounce) {
float r = (((zpl_max(0.0f, (WORLD_BLOCK_SIZE/2.0f) - zpl_abs(x))*zpl_sign(x)))*(WORLD_BLOCK_SIZE/2.0f));
return r + (-vx*bounce);
}
void IntegratePositions(ecs_iter_t *it) {
profile(PROF_INTEGRATE_POS) {
Position *p = ecs_field(it, Position, 1);
Velocity *v = ecs_field(it, Velocity, 2);
for (int i = 0; i < it->count; i++) {
if (ecs_get(it->world, it->entities[i], IsInVehicle)) {
continue;
}
if (zpl_abs(v[i].x) >= 0.001f || zpl_abs(v[i].y) >= 0.001f) {
// NOTE(zaklaus): world bounds
{
float w = (float)world_dim();
p[i].x = zpl_clamp(p[i].x, 0, w-1);
p[i].y = zpl_clamp(p[i].y, 0, w-1);
}
#if PHY_BLOCK_COLLISION==1
// NOTE(zaklaus): X axis
{
world_block_lookup lookup = world_block_from_realpos(p[i].x+PHY_LOOKAHEAD(v[i].x), p[i].y);
uint32_t flags = blocks_get_flags(lookup.bid);
float bounce = blocks_get_bounce(lookup.bid);
if (flags & BLOCK_FLAG_COLLISION) {
v[i].x = physics_correction(lookup.ox, v[i].x, bounce);
}
}
// NOTE(zaklaus): Y axis
{
world_block_lookup lookup = world_block_from_realpos(p[i].x, p[i].y+PHY_LOOKAHEAD(v[i].y));
uint32_t flags = blocks_get_flags(lookup.bid);
float bounce = blocks_get_bounce(lookup.bid);
if (flags & BLOCK_FLAG_COLLISION) {
v[i].y = physics_correction(lookup.oy, v[i].y, bounce);
}
}
#endif
entity_set_position(it->entities[i], p[i].x+v[i].x*safe_dt(it), p[i].y+v[i].y*safe_dt(it));
}
{
debug_v2 a = {p[i].x, p[i].y};
debug_v2 b = {p[i].x+v[i].x, p[i].y+v[i].y};
debug_push_line(a, b, 0xFFFFFFFF);
}
}
}
}
#define HAZARD_BLOCK_TIME 1.0f
#define HAZARD_BLOCK_DMG 5.0f
void HurtOnHazardBlock(ecs_iter_t *it) {
Position *p = ecs_field(it, Position, 1);
Health *h = ecs_field(it, Health, 2);
for (int i = 0; i < it->count; i++) {
if (h->pain_time < 0.0f) {
h->pain_time = HAZARD_BLOCK_TIME;
world_block_lookup l = world_block_from_realpos(p[i].x, p[i].y);
if (blocks_get_flags(l.bid) & BLOCK_FLAG_HAZARD) {
h->hp -= HAZARD_BLOCK_DMG;
h->hp = zpl_max(0.0f, h->hp);
}
}
}
}
#define HP_REGEN_TIME 2.0f
#define HP_REGEN_PAIN_COOLDOWN 5.0f
#define HP_REGEN_RECOVERY 15.0f
void RegenerateHP(ecs_iter_t *it) {
Health *h = ecs_field(it, Health, 1);
for (int i = 0; i < it->count; i++) {
if (h[i].pain_time < 0.0f) {
if (h[i].heal_time < 0.0f && h[i].hp < h[i].max_hp) {
h[i].heal_time = HP_REGEN_TIME;
h[i].hp += HP_REGEN_RECOVERY;
h[i].hp = zpl_min(h[i].max_hp, h[i].hp);
entity_wake(it->entities[i]);
} else {
h[i].heal_time -= safe_dt(it);
}
} else {
h[i].pain_time -= safe_dt(it);
}
}
}
void ResetActivators(ecs_iter_t *it) {
Input *in = ecs_field(it, Input, 1);
for (int i = 0; i < it->count; i++) {
in[i].use = false;
in[i].swap = false;
in[i].drop = false;
in[i].pick = false;
in[i].num_placements = 0;
}
}
void ApplyWorldDragOnVelocity(ecs_iter_t *it) {
Position *p = ecs_field(it, Position, 1);
Velocity *v = ecs_field(it, Velocity, 2);
for (int i = 0; i < it->count; i++) {
if (zpl_abs(v[i].x) < 0.001f && zpl_abs(v[i].y) < 0.001f) continue;
if (ecs_get(it->world, it->entities[i], IsInVehicle)) {
continue;
}
world_block_lookup lookup = world_block_from_realpos(p[i].x, p[i].y);
float drag = zpl_clamp(blocks_get_drag(lookup.bid), 0.0f, 1.0f);
float friction = blocks_get_friction(lookup.bid);
float velx = blocks_get_velx(lookup.bid);
float vely = blocks_get_vely(lookup.bid);
v[i].x = zpl_lerp(v[i].x, zpl_max(0.0f, zpl_abs(velx))*zpl_sign(velx), PHY_WALK_DRAG*drag*friction*safe_dt(it));
v[i].y = zpl_lerp(v[i].y, zpl_max(0.0f, zpl_abs(vely))*zpl_sign(vely), PHY_WALK_DRAG*drag*friction*safe_dt(it));
if ( zpl_abs(v[i].x) > ENTITY_ACTION_VELOCITY_THRESHOLD
|| zpl_abs(v[i].y) > ENTITY_ACTION_VELOCITY_THRESHOLD) {
entity_wake(it->entities[i]);
}
}
}
#define PLAYER_MAX_INTERACT_RANGE 35.0f
void PlayerClosestInteractable(ecs_iter_t *it){
Input *in = ecs_field(it, Input, 1);
for (int i = 0; i < it->count; ++i) {
size_t ents_count;
int64_t *ents = world_chunk_fetch_entities_realpos(in[i].bx, in[i].by, &ents_count);
ecs_entity_t closest_pick = 0;
float min_pick = ZPL_F32_MAX;
for (size_t j = 0; j < ents_count; j++) {
const Position *p2 = ecs_get(it->world, ents[j], Position);
if (!p2) continue;
float dx = p2->x - in[i].bx;
float dy = p2->y - in[i].by;
float range = zpl_sqrt(dx*dx + dy*dy);
if (range <= PLAYER_MAX_INTERACT_RANGE && range < min_pick) {
min_pick = range;
closest_pick = ents[j];
}
}
in[i].pick_ent = closest_pick;
if (in[i].pick)
in[i].sel_ent = (in[i].sel_ent == closest_pick) ? 0 : closest_pick;
}
}
void EnableWorldEdit(ecs_iter_t *it) {
world_set_stage(it->world);
}
void DisableWorldEdit(ecs_iter_t *it) {
(void)it;
world_set_stage(NULL);
}
void SystemsImport(ecs_world_t *ecs) {
ECS_MODULE(ecs, Systems);
ECS_SYSTEM(ecs, EnableWorldEdit, EcsOnLoad);
ECS_SYSTEM(ecs, MovementImpulse, EcsOnLoad, components.Input, components.Velocity, components.Position, !components.IsInVehicle);
ECS_SYSTEM(ecs, DemoNPCMoveAround, EcsOnLoad, components.Velocity, components.DemoNPC);
ECS_SYSTEM(ecs, ApplyWorldDragOnVelocity, EcsOnUpdate, components.Position, components.Velocity);
ECS_SYSTEM(ecs, HurtOnHazardBlock, EcsOnUpdate, components.Position, components.Health);
ECS_SYSTEM(ecs, RegenerateHP, EcsOnUpdate, components.Health);
ECS_SYSTEM(ecs, VehicleHandling, EcsOnUpdate, components.Vehicle, components.Position, components.Velocity);
ECS_SYSTEM(ecs, IntegratePositions, EcsOnValidate, components.Position, components.Velocity);
ECS_SYSTEM(ecs, EnterVehicle, EcsPostUpdate, components.Input, components.Position, !components.IsInVehicle);
ECS_SYSTEM(ecs, LeaveVehicle, EcsPostUpdate, components.Input, components.IsInVehicle, components.Velocity);
ECS_SYSTEM(ecs, PlayerClosestInteractable, EcsPostUpdate, components.Input);
ECS_SYSTEM(ecs, PickItem, EcsPostUpdate, components.Input, components.Position, components.Inventory, !components.IsInVehicle);
ECS_SYSTEM(ecs, DropItem, EcsPostUpdate, components.Input, components.Position, components.Inventory, !components.IsInVehicle);
ECS_SYSTEM(ecs, SwapItems, EcsPostUpdate, components.Input, components.Inventory);
//ECS_SYSTEM(ecs, MergeItems, EcsPostUpdate, components.Position, components.ItemDrop);
ECS_SYSTEM(ecs, UseItem, EcsPostUpdate, components.Input, components.Position, components.Inventory, !components.IsInVehicle);
ECS_SYSTEM(ecs, InspectContainers, EcsPostUpdate, components.Input, !components.IsInVehicle);
ECS_SYSTEM(ecs, HarvestIntoContainers, EcsPostUpdate, components.ItemContainer, components.Position);
ECS_SYSTEM(ecs, ResetActivators, EcsPostUpdate, components.Input);
ECS_SYSTEM(ecs, ClearVehicle, EcsUnSet, components.Vehicle);
ECS_SYSTEM(ecs, DisableWorldEdit, EcsPostUpdate);
}

View File

@ -1,8 +0,0 @@
#pragma once
#include "flecs/flecs.h"
static inline float safe_dt(ecs_iter_t *it) {
return zpl_min(it->delta_time, 0.03334f);
}
void SystemsImport(ecs_world_t *ecs);

View File

@ -1,8 +0,0 @@
// NOTE(zaklaus): access to spawners
#include "ents/storage.h"
static spawndef *entity_spawnlist = 0;
void entity_spawndef_setup(void) {
entity_spawndef_register((spawndef){ .id = ASSET_CHEST, .proc = storage_spawn });
}

View File

@ -1,130 +0,0 @@
#include "ents/items.h"
#include "ents/entity.h"
#include "world/entity_view.h"
#include "world/world.h"
#include "world/blocks.h"
#include "ecs/components.h"
#include "zpl.h"
#include "items_list.c"
void item_cleanup() {
zpl_array_free(items); items = NULL;
}
void item_register(item_desc desc) {
if (!items) {
zpl_array_init(items, zpl_heap());
}
zpl_array_append(items, desc);
}
static inline item_id item_resolve_proxy(item_id id) {
ZPL_ASSERT(id >= 0 && id < zpl_array_count(items));
item_usage usage = items[id].usage;
if (usage == UKIND_PROXY) {
return item_find(items[id].proxy.id);
}
return id;
}
static inline asset_id item_fix_kind(asset_id id) {
return items[item_find(id)].kind;
}
uint64_t item_spawn(asset_id kind, uint32_t qty) {
ecs_entity_t e = entity_spawn(EKIND_ITEM);
ItemDrop *d = ecs_get_mut(world_ecs(), e, ItemDrop);
*d = (ItemDrop){
.kind = item_fix_kind(kind),
.quantity = qty,
.merger_time = 0,
};
return (uint64_t)e;
}
item_id item_find(asset_id kind) {
for (item_id i=0; i<zpl_array_count(items); i++) {
if (items[i].kind == kind)
return item_resolve_proxy(i);
}
return ASSET_INVALID;
}
void item_use(ecs_world_t *ecs, ItemDrop *it, Position p, uint64_t udata) {
(void)ecs;
uint16_t it_id = item_find(it->kind);
item_desc *desc = &items[it_id];
if (it->quantity <= 0) return;
switch (item_get_usage(it_id)) {
case UKIND_HOLD: /* NOOP */ break;
case UKIND_PLACE:{
world_block_lookup l = world_block_from_realpos(p.x, p.y);
if (l.is_outer && l.bid > 0) {
asset_id item_asset = blocks_get_asset(l.bid);
item_id item_asset_id = item_find(item_asset);
if (item_asset_id == ASSET_INVALID) return;
// NOTE(zaklaus): If we replace the same item, refund 1 qty and let it replace it
if (item_asset_id == it_id) {
it->quantity++;
} else {
return;
}
}
// NOTE(zaklaus): This is an inner layer block, we can't build over it if it has a collision!
else if (l.bid > 0 && blocks_get_flags(l.bid) & (BLOCK_FLAG_COLLISION|BLOCK_FLAG_ESSENTIAL)) {
return;
}
world_chunk_replace_block(l.chunk_id, l.id, blocks_find(desc->place.kind + (asset_id)udata));
it->quantity--;
}break;
case UKIND_PLACE_ITEM:{
world_block_lookup l = world_block_from_realpos(p.x, p.y);
if (l.is_outer && l.bid > 0) {
return;
}
// NOTE(zaklaus): This is an inner layer block, we can't build over it if it has a collision!
else if (l.bid > 0 && blocks_get_flags(l.bid) & (BLOCK_FLAG_COLLISION|BLOCK_FLAG_ESSENTIAL)) {
return;
}
ecs_entity_t e = entity_spawn_id(desc->place_item.id);
ZPL_ASSERT(world_entity_valid(e));
entity_set_position(e, p.x, p.y);
it->quantity--;
}break;
case UKIND_DELETE:
case UKIND_END_PLACE:
case UKIND_PROXY:
break;
}
}
void item_despawn(uint64_t id) {
entity_despawn(id);
}
uint32_t item_max_quantity(item_id id) {
ZPL_ASSERT(id >= 0 && id < zpl_array_count(items));
return items[id].max_quantity;
}
item_usage item_get_usage(item_id id) {
ZPL_ASSERT(id >= 0 && id < zpl_array_count(items));
return items[id].usage;
}
bool item_get_place_directional(item_id id) {
ZPL_ASSERT(id >= 0 && id < zpl_array_count(items));
return items[id].place.directional;
}

View File

@ -1,21 +0,0 @@
#include "ents/items.h"
#include "world/entity_view.h"
#include "items_list_helpers.h"
static item_desc *items = 0;
void item_setup() {
item_register((item_desc){ .kind = 0, .max_quantity = 0, });
item_register(ITEM_BLOCK(ASSET_DEMO_ICEMAKER, 64, ASSET_WATER));
item_register(ITEM_SELF(ASSET_FENCE, 64));
item_register(ITEM_SELF(ASSET_WOOD, 64));
item_register(ITEM_HOLD(ASSET_TREE, 64));
item_register(ITEM_SELF_DIR(ASSET_BELT, 999));
item_register(ITEM_PROXY(ASSET_BELT_LEFT, ASSET_BELT));
item_register(ITEM_PROXY(ASSET_BELT_RIGHT, ASSET_BELT));
item_register(ITEM_PROXY(ASSET_BELT_UP, ASSET_BELT));
item_register(ITEM_PROXY(ASSET_BELT_DOWN, ASSET_BELT));
item_register(ITEM_ENT(ASSET_CHEST, 32, ASSET_CHEST));
}

View File

@ -1,51 +0,0 @@
#pragma once
#define ITEM_HOLD(asset, qty)\
(item_desc){\
.kind = asset,\
.usage = UKIND_HOLD,\
.max_quantity = qty,\
}
#define ITEM_BLOCK(asset, qty, build_asset)\
(item_desc){\
.kind = asset,\
.usage = UKIND_PLACE,\
.max_quantity = qty,\
.place = {\
.kind = build_asset,\
}\
}
#define ITEM_BLOCK_DIR(asset, qty, build_asset)\
(item_desc){\
.kind = asset,\
.usage = UKIND_PLACE,\
.max_quantity = qty,\
.place = {\
.kind = build_asset,\
.directional = true,\
}\
}
#define ITEM_PROXY(asset, proxy_id)\
(item_desc){\
.kind = asset,\
.usage = UKIND_PROXY,\
.proxy = {\
.id = proxy_id,\
}\
}
#define ITEM_ENT(asset, qty, eid)\
(item_desc){\
.kind = asset,\
.usage = UKIND_PLACE_ITEM,\
.max_quantity = qty,\
.place_item = {\
.id = eid\
}\
}
#define ITEM_SELF(asset, qty) ITEM_BLOCK(asset, qty, asset)
#define ITEM_SELF_DIR(asset, qty) ITEM_BLOCK_DIR(asset, qty, asset)

View File

@ -1,34 +0,0 @@
#include "ents/player.h"
#include "ents/entity.h"
#include "world/entity_view.h"
#include "flecs/flecs.h"
#include "librg.h"
#include "world/world.h"
#include "ecs/components.h"
#include "ecs/systems.h"
#include "zpl.h"
#define PLAYER_MAX_HP 100.0f
uint64_t player_spawn(char *name) {
ecs_entity_t e = entity_spawn(EKIND_PLAYER);
if (!name) {
name = zpl_bprintf("player_%d", e);
}
ecs_set_name(world_ecs(), e, name);
ecs_set(world_ecs(), e, ClientInfo, {0});
ecs_set(world_ecs(), e, Input, {0});
ecs_set(world_ecs(), e, Inventory, {0});
ecs_set(world_ecs(), e, Health, {.hp = PLAYER_MAX_HP, .max_hp = PLAYER_MAX_HP});
librg_entity_owner_set(world_tracker(), e, (int64_t)e);
return (uint64_t)e;
}
void player_despawn(uint64_t ent_id) {
entity_despawn(ent_id);
}

View File

@ -1,19 +0,0 @@
#include "ents/storage.h"
#include "ents/device.h"
#include "ents/entity.h"
#include "world/entity_view.h"
#include "world/world.h"
#include "ecs/components.h"
uint64_t storage_spawn(void) {
ecs_entity_t e = device_spawn(ASSET_CHEST);
ItemContainer *storage = ecs_get_mut(world_ecs(), e, ItemContainer);
*storage = (ItemContainer){0};
return (uint64_t)e;
}
void storage_despawn(uint64_t ent_id) {
entity_despawn(ent_id);
}

View File

@ -1,7 +0,0 @@
#pragma once
#include "platform/system.h"
uint64_t storage_spawn(void);
void storage_despawn(uint64_t id);

View File

@ -1,23 +0,0 @@
#include "ents/vehicle.h"
#include "ents/entity.h"
#include "world/entity_view.h"
#include "world/world.h"
#include "ecs/components.h"
uint64_t vehicle_spawn(void) {
ecs_entity_t e = entity_spawn(EKIND_VEHICLE);
Vehicle *veh = ecs_get_mut(world_ecs(), e, Vehicle);
*veh = (Vehicle){
.wheel_base = 50.0f,
.speed = 50.0f,
.reverse_speed = -20.0f,
.force = 0.0f,
};
return (uint64_t)e;
}
void vehicle_despawn(uint64_t ent_id) {
entity_despawn(ent_id);
}

View File

@ -1,7 +0,0 @@
#pragma once
#include "platform/system.h"
uint64_t vehicle_spawn(void);
void vehicle_despawn(uint64_t id);

View File

@ -1,121 +0,0 @@
#include "gen/assets.h"
#include "raylib.h"
#include "gen/texgen.h"
typedef struct {
asset_id id;
asset_kind kind;
union {
Texture2D tex;
Sound snd;
};
// NOTE(zaklaus): metadata
} asset;
#include "assets_list.c"
#define ASSET_FRAME_RENDER_MS (1.0/5.0)
#define ASSET_FRAME_SKIP 4
static int64_t assets_resources_frame_counter = 1;
static double assets_resources_frame_next_draw = 0.0;
#include <time.h>
void assets_register(asset_desc a) {
if (!assets) {
zpl_array_init(assets, zpl_heap());
}
zpl_array_append(assets, ((asset){ .id = a.id, .kind = a.kind }));
}
void assets_cleanup(void) {
zpl_array_free(assets); assets = NULL;
}
int32_t assets_resources_setup(void) {
for (zpl_isize i=0; i<zpl_array_count(assets); i++) {
asset *b = &assets[i];
switch (b->kind) {
case AKIND_TEXTURE: {
b->tex = texgen_build_sprite(b->id);
}break;
case AKIND_ANIM: {
b->tex = texgen_build_anim(b->id, 0);
}break;
case AKIND_SOUND: {
// TODO(zaklaus): soundgen
}break;
default: break;
}
}
assets_resources_frame_next_draw = get_cached_time() + ASSET_FRAME_RENDER_MS;
return 0;
}
int32_t assets_resources_frame(void) {
if (assets_resources_frame_next_draw < get_cached_time()) {
for (zpl_isize i=0; i<zpl_array_count(assets); i++) {
asset *b = &assets[i];
switch (b->kind) {
case AKIND_ANIM: {
UnloadTexture(b->tex);
b->tex = texgen_build_anim(b->id, assets_resources_frame_counter);
}break;
default: break;
}
}
assets_resources_frame_next_draw = get_cached_time() + ASSET_FRAME_RENDER_MS;
assets_resources_frame_counter += ASSET_FRAME_SKIP;
}
return 0;
}
void assets_resources_destroy(void) {
for (zpl_isize i=0; i<zpl_array_count(assets); i++) {
switch (assets[i].kind) {
case AKIND_ANIM:
case AKIND_TEXTURE: {
UnloadTexture(assets[i].tex);
}break;
case AKIND_SOUND: {
// TODO(zaklaus): soundgen
}break;
default: break;
}
}
}
uint16_t assets_find(asset_id id) {
for (zpl_isize i=0; i<zpl_array_count(assets); i++) {
if (assets[i].id == id)
return i;
}
ZPL_PANIC("Unknown asset id: %d\n", id);
return ASSET_INVALID;
}
asset_kind assets_get_kind(uint16_t id) {
return assets[id].kind;
}
void *assets_get_snd(uint16_t id) {
return (void*)&assets[id].snd;;
}
void *assets_get_tex(uint16_t id) {
return (void*)&assets[id].tex;
}

View File

@ -1,85 +0,0 @@
#pragma once
#include "platform/system.h"
#define ASSET_INVALID 0xFF
#define ASSET_ENTRY(asset, asset_kind)\
(asset_desc){\
.id = asset,\
.kind = asset_kind,\
}
#define ASSET_SND(asset) ASSET_ENTRY(asset, AKIND_SOUND)
#define ASSET_TEX(asset) ASSET_ENTRY(asset, AKIND_TEXTURE)
#define ASSET_ANI(asset) ASSET_ENTRY(asset, AKIND_ANIM)
typedef enum {
// NOTE(zaklaus): Debug
ASSET_EMPTY,
ASSET_BLANK,
ASSET_BUILDMODE_HIGHLIGHT,
// NOTE(zaklaus): entities
ASSET_PLAYER,
ASSET_THING,
ASSET_CHEST,
// NOTE(zaklaus): items
ASSET_DEMO_ICEMAKER,
// NOTE(zaklaus): blocks
ASSET_FENCE,
ASSET_DEV,
ASSET_GROUND,
ASSET_DIRT,
ASSET_WATER,
ASSET_LAVA,
ASSET_WALL,
ASSET_HILL,
ASSET_HILL_SNOW,
ASSET_HOLE,
ASSET_WOOD,
ASSET_TREE,
ASSET_BELT,
ASSET_BELT_LEFT,
ASSET_BELT_RIGHT,
ASSET_BELT_UP,
ASSET_BELT_DOWN,
ASSET_NEXT_FREE,
MAX_ASSETS = 1024,
} asset_id;
typedef enum {
AKIND_TEXTURE,
AKIND_ANIM,
AKIND_SOUND,
FORCE_AKIND_UINT8 = UINT8_MAX
} asset_kind;
typedef struct {
asset_id id;
asset_kind kind;
} asset_desc;
void assets_setup(void);
void assets_cleanup(void);
void assets_register(asset_desc desc);
// resources
int32_t assets_resources_setup(void);
void assets_resources_destroy(void);
int32_t assets_resources_frame(void);
uint16_t assets_find(asset_id id);
asset_kind assets_get_kind(uint16_t id);
void *assets_get_snd(uint16_t id);
void *assets_get_tex(uint16_t id);
// NOTE(zaklaus): client only
#define ASSET_SRC_RECT() ((Rectangle){0, 0, 64, 64})
#define ASSET_DST_RECT(x,y) ((Rectangle){x, y, 64, 64})

View File

@ -1,31 +0,0 @@
#include "gen/assets.h"
static asset *assets = 0;
void assets_setup() {
assets_register(ASSET_TEX(ASSET_EMPTY));
assets_register(ASSET_TEX(ASSET_BLANK));
assets_register(ASSET_TEX(ASSET_BUILDMODE_HIGHLIGHT));
assets_register(ASSET_TEX(ASSET_DEMO_ICEMAKER));
assets_register(ASSET_TEX(ASSET_CHEST));
// NOTE: blocks
assets_register(ASSET_TEX(ASSET_FENCE));
assets_register(ASSET_TEX(ASSET_DEV));
assets_register(ASSET_TEX(ASSET_GROUND));
assets_register(ASSET_TEX(ASSET_DIRT));
assets_register(ASSET_ANI(ASSET_WATER));
assets_register(ASSET_TEX(ASSET_LAVA));
assets_register(ASSET_TEX(ASSET_WALL));
assets_register(ASSET_TEX(ASSET_HILL));
assets_register(ASSET_TEX(ASSET_HILL_SNOW));
assets_register(ASSET_TEX(ASSET_HOLE));
assets_register(ASSET_TEX(ASSET_WOOD));
assets_register(ASSET_TEX(ASSET_TREE));
assets_register(ASSET_TEX(ASSET_BELT));
assets_register(ASSET_TEX(ASSET_BELT_LEFT));
assets_register(ASSET_TEX(ASSET_BELT_RIGHT));
assets_register(ASSET_TEX(ASSET_BELT_UP));
assets_register(ASSET_TEX(ASSET_BELT_DOWN));
};

View File

@ -1,77 +0,0 @@
#include "gen/texgen.h"
#include "world/world.h"
#include "texgen_data.c"
#include "zpl.h"
static inline
Texture2D LoadTexEco(const char *name) {
static char filename[128];
zpl_snprintf(filename, 128, "art/gen/%s.png", name);
return LoadTexture(filename);
}
static inline
Image LoadImageEco(const char *name) {
static char filename[128];
zpl_snprintf(filename, 128, "art/gen/%s.png", name);
return LoadImage(filename);
}
static inline
Texture2D Image2TexEco(Image image) {
Texture2D tex = LoadTextureFromImage(image);
UnloadImage(image);
return tex;
}
static inline
Texture2D GenColorEco(Color color) {
Image img = GenImageColor(1, 1, color);
return Image2TexEco(img);
}
Texture2D texgen_build_anim(asset_id id, int64_t counter) {
(void)counter;
switch (id) {
case ASSET_WATER: {
Image img = LoadImageEco("water");
ImageColorBrightness(&img, zpl_abs((counter % 64 - 32)*2));
return Image2TexEco(img);
}break;
default: return GenColorEco(PINK); break;
}
}
Texture2D texgen_build_sprite(asset_id id) {
switch (id) {
case ASSET_BLANK: return GenColorEco(WHITE); break;
case ASSET_BUILDMODE_HIGHLIGHT: return GenColorEco(WHITE); break;
// NOTE(zaklaus): items
case ASSET_DEMO_ICEMAKER: return LoadTexEco("demo_icemaker");
// NOTE(zaklaus): blocks
case ASSET_FENCE: return LoadTexEco("fence");
case ASSET_GROUND: return LoadTexEco("grass");
case ASSET_DIRT: return LoadTexEco("dirt");
case ASSET_WALL: return LoadTexEco("asphalt");
case ASSET_HILL_SNOW:
case ASSET_HILL: return LoadTexEco("rock");
case ASSET_LAVA: return LoadTexEco("lava");
case ASSET_WOOD: return LoadTexEco("wood");
case ASSET_TREE: return LoadTexEco("tree");
// case ASSET_WATER: return LoadTexEco("water");
case ASSET_BELT:
case ASSET_BELT_RIGHT: return LoadTexEco("belt_right");
case ASSET_BELT_LEFT: return LoadTexEco("belt_left");
case ASSET_BELT_UP: return LoadTexEco("belt_up");
case ASSET_BELT_DOWN: return LoadTexEco("belt_down");
// NOTE(zaklaus): devices
case ASSET_CHEST: return LoadTexEco("chest");
default: return GenColorEco(PINK); break;
}
}

View File

@ -2,7 +2,11 @@
#include "platform/system.h"
#include "raylib.h"
#include "world/blocks.h"
#include "gen/assets.h"
#include "models/assets.h"
Texture2D texgen_build_anim(asset_id id, int64_t counter);
Texture2D texgen_build_sprite(asset_id id);
// NOTE(zak): this is a fallback for when the asset is not defined by the game
Texture2D texgen_build_anim_fallback(asset_id id, int64_t counter);
Texture2D texgen_build_sprite_fallback(asset_id id);

View File

@ -1,2 +0,0 @@
// NOTE(zaklaus): contains collection of packed images used by texgen
// TODO(zaklaus): we will use files for now

View File

@ -0,0 +1,68 @@
#include "gen/texgen.h"
#include "world/world.h"
#include "zpl.h"
#include "utils/raylib_helpers.h"
Texture2D texgen_build_anim_fallback(asset_id id, int64_t counter) {
(void)counter;
switch (id) {
case ASSET_WATER: {
return LoadTexEco(zpl_bprintf("%s%d", "water", counter%3));
}break;
default: return GenColorEco(PINK); break;
}
}
Texture2D texgen_build_sprite_fallback(asset_id id) {
switch (id) {
case ASSET_BLANK: return GenColorEco(WHITE); break;
case ASSET_BUILDMODE_HIGHLIGHT: return GenColorEco(WHITE); break;
case ASSET_BLOCK_FRAME: return GenFrameRect(); break;
// NOTE(zaklaus): items
case ASSET_COAL: return LoadTexEco("coal");
case ASSET_IRON_ORE: return LoadTexEco("iron_ore");
case ASSET_IRON_INGOT: return LoadTexEco("iron_ingot");
case ASSET_IRON_PLATES: return LoadTexEco("iron_plate");
case ASSET_SCREWS: return LoadTexEco("screws");
case ASSET_LOG: return LoadTexEco("log");
case ASSET_PLANK: return LoadTexEco("plank");
case ASSET_CREATURE: return GenColorEco(YELLOW);
case ASSET_CREATURE_FOOD: return GenColorEco(GREEN);
// NOTE(zaklaus): blocks
case ASSET_FENCE: return LoadTexEco("fence");
case ASSET_GROUND: return LoadTexEco("grass");
case ASSET_DIRT: return LoadTexEco("dirt");
case ASSET_WALL: return LoadTexEco("asphalt");
case ASSET_HILL_SNOW:
case ASSET_HILL: return LoadTexEco("rock");
case ASSET_LAVA: return LoadTexEco("lava");
case ASSET_WOOD: return LoadTexEco("wood");
case ASSET_TREE: return LoadTexEco("bigtree");
case ASSET_TEST_TALL: return LoadTexEco("test-tall");
// case ASSET_WATER: return LoadTexEco("water");
case ASSET_BELT:
case ASSET_BELT_RIGHT: return LoadTexEco("belt_right");
case ASSET_BELT_LEFT: return LoadTexEco("belt_left");
case ASSET_BELT_UP: return LoadTexEco("belt_up");
case ASSET_BELT_DOWN: return LoadTexEco("belt_down");
// NOTE(zaklaus): devices
case ASSET_CHEST: return LoadTexEco("chest");
case ASSET_FURNACE: return LoadTexEco("furnace");
case ASSET_CRAFTBENCH: return LoadTexEco("craftbench");
case ASSET_SPLITTER: return LoadTexEco("item_splitter");
case ASSET_ASSEMBLER: return LoadTexEco("assembler");
default: break;
}
if (id > ASSET_BLUEPRINT_BEGIN && id < ASSET_BLUEPRINT_END) {
return LoadTexEco("blueprint");
}
return GenColorEco(PINK);
}

View File

@ -1,5 +1,5 @@
#include "core/camera.h"
#include "ents/item_placement.h"
#include "models/item_placement.h"
static bool build_submit_placements = false;
static bool build_is_in_draw_mode = false;
@ -28,6 +28,8 @@ void buildmode_draw(void) {
cam.x = (double)mx;
cam.y = (double)my;
renderer_draw_single((float)cam.x, (float)cam.y, ASSET_BLOCK_FRAME, WHITE);
// NOTE(zaklaus): Check distance
double dx = old_cam.x - cam.x;
double dy = old_cam.y - cam.y;
@ -39,13 +41,13 @@ void buildmode_draw(void) {
buildmode_clear_buffers();
}
if (IsKeyPressed(KEY_B)){
if (input_is_pressed(IN_TOGGLE_DEMOLITION)){
build_is_deletion_mode = !build_is_deletion_mode;
}
ItemDrop *item = &e->items[e->selected_item];
Item *item = &e->items[e->selected_item];
if (e->has_items && !e->inside_vehicle && item->quantity > 0 && (!is_outside_range || build_is_deletion_mode)) {
if (e->has_items && !e->inside_vehicle && (build_is_deletion_mode || (item->quantity > 0 && !is_outside_range))) {
item_usage usage = 0;
uint16_t item_id = 0;
if (!build_is_deletion_mode){
@ -67,8 +69,9 @@ void buildmode_draw(void) {
qty = item->quantity;
}
world_block_lookup l = world_block_from_realpos((float)cam.x, (float)cam.y);
world_view_block_lookup l = world_view_block_from_realpos(game_world_view_get_active(), (float)cam.x, (float)cam.y);
if (build_is_deletion_mode && !l.is_outer){
renderer_draw_single((float)cam.x, (float)cam.y, ASSET_BUILDMODE_HIGHLIGHT, ColorAlpha(RED, 0.4f));
goto build_skip_placements;
}
@ -102,8 +105,12 @@ void buildmode_draw(void) {
}
if (!is_outside_range)
renderer_draw_single((float)cam.x, (float)cam.y, ASSET_BUILDMODE_HIGHLIGHT, ColorAlpha(build_is_deletion_mode ? RED : WHITE, 0.2f));
if (!is_outside_range) {
if (build_is_deletion_mode)
renderer_draw_single((float)cam.x, (float)cam.y, ASSET_BUILDMODE_HIGHLIGHT, ColorAlpha(RED, 0.2f));
else
renderer_draw_single((float)cam.x, (float)cam.y, item->kind, ColorAlpha(WHITE, 0.2f));
}
build_skip_placements:
build_num_placements = zpl_min(build_num_placements, qty);
@ -112,7 +119,7 @@ void buildmode_draw(void) {
for (size_t i = 0; i < build_num_placements; i++) {
item_placement *it = &build_placements[i];
renderer_draw_single(it->x, it->y, ASSET_BUILDMODE_HIGHLIGHT, ColorAlpha(build_is_deletion_mode ? RED : WHITE, 0.4f));
renderer_draw_single(it->x, it->y, !build_is_deletion_mode ? item->kind : ASSET_BUILDMODE_HIGHLIGHT, ColorAlpha(build_is_deletion_mode ? RED : RAYWHITE, 0.6f));
}
if (build_is_in_draw_mode) {

View File

@ -0,0 +1,287 @@
#include "models/crafting.h"
typedef struct {
uint8_t selected_item;
bool drop_item;
bool item_is_held;
uint8_t held_item_idx;
Item held_item;
bool is_inside;
bool storage_action;
bool swap;
uint8_t swap_from;
uint8_t swap_to;
uint16_t craft_item;
} inv_keystate;
static inv_keystate player_inv = {0};
static inv_keystate storage_inv = {0};
bool inv_is_open = false;
bool inv_is_inside = false;
bool inv_is_storage_action = false;
bool inv_swap_storage = false;
// TODO(zaklaus):
// TODO(zaklaus): MOVE TO COMMON UI MODULE
// TODO(zaklaus):
typedef struct {
float x, y;
} inv_draw_result;
static inline
int UIMeasureText(const char *text, int fontSize) {
Vector2 vec = { 0.0f, 0.0f };
// Check if default font has been loaded
if (GetFontDefault().texture.id != 0) {
int defaultFontSize = 10; // Default Font chars height in pixel
int new_spacing = fontSize/defaultFontSize;
vec = MeasureTextEx(GetFontDefault(), text, (float)fontSize, (float)new_spacing);
}
return (int)vec.x;
}
static inline
void UIDrawText(const char *text, float posX, float posY, int fontSize, Color color) {
// Check if default font has been loaded
if (GetFontDefault().texture.id != 0) {
Vector2 position = { (float)posX , (float)posY };
int defaultFontSize = 22; // Default Font chars height in pixel
int new_spacing = fontSize/defaultFontSize;
DrawTextEx(GetFontDefault(), text, position, (float)fontSize , (float)new_spacing , color);
}
}
static inline inv_draw_result
DrawColoredText(float xpos, float ypos, char const *text, Color color) {
ZPL_ASSERT(text);
UIDrawText(text, xpos, ypos, 22, color);
char const *p = text;
uint8_t newlines = 1;
do {
if (*p == '\n')
++newlines;
} while (*p++ != 0);
return (inv_draw_result){.x = xpos + UIMeasureText(text, 22), .y = ypos + 22*newlines};
}
static inline
inv_draw_result inventory_draw_crafting_btn(float xpos, float ypos, const char *name, uint16_t id, Color color) {
float name_width=0.0f;
char const *text = TextFormat("> %s", name);
name_width = (float)UIMeasureText(text, 22);
Color new_color = color;
if (is_btn_pressed(xpos, ypos, name_width, 22, &new_color)) {
inv_is_inside = true;
player_inv.craft_item = id;
}
if (check_mouse_area(xpos, ypos, name_width, 22) != DAREA_OUTSIDE) {
Vector2 mpos = GetMousePosition();
recipe rp = craft_get_recipe_data(craft_get_recipe_id_from_product(id));
if (nk_begin(game_ui , name, nk_rect(mpos.x+15, mpos.y+15, name_width+5, 1200),
NK_WINDOW_BORDER | NK_WINDOW_NO_INPUT | NK_WINDOW_NO_SCROLLBAR | NK_WINDOW_DYNAMIC)) {
if (nk_tree_push_id(game_ui, NK_TREE_NODE, "Overview", NK_MAXIMIZED, id)) {
{
tooltip_draw_contents(tooltip_find_desc(name));
}
nk_tree_pop(game_ui);
}
if (nk_tree_push_id(game_ui, NK_TREE_NODE, "Reagents", NK_MAXIMIZED, id)) {
for (asset_id i = 0; rp.reagents[i].id; i++) {
nk_label(game_ui, asset_names[rp.reagents[i].id], NK_TEXT_LEFT);
}
nk_tree_pop(game_ui);
}
nk_end(game_ui);
}
}
Color _c_compare_lol = BLACK;
if (!zpl_memcompare(&color, &_c_compare_lol, sizeof(Color))) {
new_color = BLACK;
}
inv_draw_result res = DrawColoredText(xpos, ypos, text, new_color);
ypos = res.y;
return res;
}
static inline
bool inventory_draw_crafting_list(entity_view *e, float xpos, float ypos) {
float start_xpos = xpos;
float start_ypos = ypos;
for (uint16_t i = 0; e->craftables[i]; ++i) {
asset_id id = e->craftables[i];
inventory_draw_crafting_btn(start_xpos+1, ypos+1, asset_names[id], id, BLACK);
inv_draw_result entry = inventory_draw_crafting_btn(start_xpos, ypos, asset_names[id], id, RAYWHITE);
ypos = entry.y;
xpos = zpl_max(xpos, entry.x);
}
return check_mouse_area(start_xpos, start_ypos, xpos-start_xpos, ypos-start_ypos) != DAREA_OUTSIDE;
}
void inventory_draw_panel(entity_view *e, bool is_player, float sx, float sy){
if (!e->has_items && is_player)
return;
if (!e->has_storage_items && !is_player)
return;
float x = sx;
float y = sy;
const int32_t grid_size = (is_player) ? (64*3) : (64*4);
const int32_t inv_size = (is_player) ? ITEMS_INVENTORY_SIZE : ITEMS_CONTAINER_SIZE;
const int32_t inv_cols = (is_player) ? 3 : 4;
inv_keystate *inv = (!is_player) ? &storage_inv : &player_inv;
inv_keystate *inv2 = (is_player) ? &storage_inv : &player_inv;
bool inside_craft = !is_player && inventory_draw_crafting_list(e, screenWidth/2.0f - 684, screenHeight/2.0f - 128);
inv->is_inside = check_mouse_area(sx, sy, (float)grid_size, (float)grid_size) != DAREA_OUTSIDE;
inv_is_inside |= inv->is_inside || inside_craft;
for (int32_t i = 0; i < inv_size; i += 1) {
{
debug_area_status area = check_mouse_area(x, y, 64, 64);
Color color = RAYWHITE;
Item *item = (is_player) ? &e->items[i] : &e->storage_items[i];
if (area == DAREA_HOVER) {
color = YELLOW;
} else if (area == DAREA_PRESS && inv2->item_is_held){
color = VIOLET;
inv_swap_storage = true;
inv_is_storage_action = true;
inv->item_is_held = false;
inv2->item_is_held = false;
inv->selected_item = i;
inv->swap = true;
inv->swap_from = inv2->held_item_idx;
inv->swap_to = i;
} else if (area == DAREA_PRESS && !inv->item_is_held && !inv2->item_is_held) {
color = VIOLET;
inv_is_storage_action = true;
inv->selected_item = i;
} else if (area == DAREA_PRESS && inv->item_is_held) {
color = VIOLET;
inv_is_storage_action = true;
inv->selected_item = i;
inv->item_is_held = false;
inv->swap = true;
inv->swap_from = inv->held_item_idx;
inv->swap_to = i;
} else if (area == DAREA_HELD && item->quantity > 0 && !inv->item_is_held && !inv2->item_is_held) {
inv_is_storage_action = true;
inv->selected_item = i;
inv->item_is_held = true;
inv->held_item = *item;
inv->held_item_idx = i;
} else if (i == inv->selected_item) {
color = RED;
}
DrawRectangleLinesEco(x, y, 64, 64, color);
if (item->quantity > 0) {
Texture2D tex = GetSpriteTexture2D(assets_find(item->kind));
float aspect = tex.width/(float)tex.height;
float size = WORLD_BLOCK_SIZE * aspect;
float ofs_x = (WORLD_BLOCK_SIZE-size)/2.0f;
DrawTexturePro(tex, ASSET_SRC_RECT_TEX(tex.width, tex.height), ASSET_DST_RECT_TEX(x+ofs_x, y, size, WORLD_BLOCK_SIZE), (Vector2){0.5f,0.5f}, 0.0f, WHITE);
}
if (item->quantity > 1) {
DrawTextEco(zpl_bprintf("%d", item->quantity), x+5, y+5, 16, RAYWHITE, 0.0f);
}
if (item->quantity > 0 && item->durability < 1.0f) {
DrawRectangleEco(x, y+56, 64, 8, BLACK);
DrawRectangleEco(x, y+56, 64*item->durability, 8, BlendColor(RED, GREEN, item->durability));
}
}
x += 64;
if ((i+1) % inv_cols == 0) {
x = sx;
y += 64;
}
}
// NOTE(zaklaus): switch it off if is_player
if (is_player)
inv_is_storage_action = false;
}
void inventory_render_held_item(bool is_player){
inv_keystate *inv = (!is_player) ? &storage_inv : &player_inv;
inv_keystate *inv2 = (is_player) ? &storage_inv : &player_inv;
if (inv->item_is_held) {
Vector2 mpos = GetMousePosition();
mpos.x -= 32;
mpos.y -= 32;
Texture2D tex = GetSpriteTexture2D(assets_find(inv->held_item.kind));
float aspect = tex.width/(float)tex.height;
float size = WORLD_BLOCK_SIZE * aspect;
float ofs_x = (WORLD_BLOCK_SIZE-size)/2.0f;
DrawTexturePro(tex, ASSET_SRC_RECT_TEX(tex.width, tex.height), ASSET_DST_RECT_TEX(mpos.x+ofs_x, mpos.y, size, WORLD_BLOCK_SIZE), (Vector2){0.5f,0.5f}, 0.0f, ColorAlpha(WHITE, 0.8f));
DrawTextEco(zpl_bprintf("%d", inv->held_item.quantity), mpos.x, mpos.y, 16, RAYWHITE, 0.0f);
if (!inv->is_inside && IsMouseButtonReleased(MOUSE_LEFT_BUTTON) && !inv2->is_inside) {
inv->drop_item = true;
inv->item_is_held = false;
inv_is_storage_action = inv == &storage_inv;
}
}
}
void inventory_reset_states(inv_keystate *ik) {
ik->drop_item = false;
ik->swap = false;
ik->craft_item = 0;
}
void inventory_draw() {
inv_is_storage_action = false;
inv_is_inside = false;
inv_swap_storage = false;
inventory_reset_states(&player_inv);
inventory_reset_states(&storage_inv);
camera cam = camera_get();
entity_view *e = game_world_view_active_get_entity(cam.ent_id);
if (!e || !e->has_items) return;
if (input_is_pressed(IN_TOGGLE_INV)) {
inv_is_open = !inv_is_open;
}
if (!inv_is_open || build_is_in_draw_mode) {
return;
}
inventory_draw_panel(e, true, screenWidth/2.0f + 128, screenHeight/2.0f - 96);
inventory_draw_panel(e, false, screenWidth/2.0f - 384, screenHeight/2.0f - 128);
inventory_render_held_item(true);
inventory_render_held_item(false);
}

View File

@ -0,0 +1,112 @@
#define MAX_NOTIFICATIONS_ON_SCREEN 5
typedef struct {
zpl_string title;
zpl_string text;
} notification;
static notification *notifications = 0;
static bool show_notification_list = 0;
void notification_push(const char* title1, const char* text1) {
if (!notifications) {
zpl_array_init(notifications, zpl_heap());
}
zpl_string title = zpl_string_make(zpl_heap(), title1);
zpl_string text = zpl_string_make(zpl_heap(), text1);
zpl_array_append(notifications, ((notification) { title, text }));
}
void notification_clear(void) {
for (zpl_isize i = 0; i < zpl_array_count(notifications); i++) {
zpl_string_free(notifications[i].title);
zpl_string_free(notifications[i].text);
}
zpl_array_clear(notifications);
}
void notification_draw(void) {
float width = (float)GetScreenWidth();
float height = (float)GetScreenHeight();
// draw ctrl panel
if (nk_begin(game_ui, "Notifications", nk_rect(width - 220, 20, 200, 80),
NK_WINDOW_BORDER | NK_WINDOW_NO_SCROLLBAR | NK_WINDOW_TITLE | NK_WINDOW_DYNAMIC)) {
{
nk_layout_row_dynamic(game_ui, 0, 2);
if (nk_button_label(game_ui, "Clear All")) {
notification_clear();
}
if (nk_button_label(game_ui, show_notification_list ? "Hide Manager" : "Show All")) {
show_notification_list ^= 1;
}
}
nk_end(game_ui);
}
float ypos = 100;
zpl_isize cnt = zpl_min(zpl_array_count(notifications), MAX_NOTIFICATIONS_ON_SCREEN)-1;
for (zpl_isize i = cnt; i >= 0; --i) {
notification *notif = (notifications + i);
if (nk_begin_titled(game_ui, zpl_bprintf("%d%fnotif%s", i, ypos, notif->title), notif->title, nk_rect(width - 320, ypos, 300, 1200),
NK_WINDOW_DYNAMIC|NK_WINDOW_NO_SCROLLBAR)) {
{
if (nk_tree_push_id(game_ui, NK_TREE_TAB, notif->title, NK_MAXIMIZED, (int)i)) {
nk_label_wrap(game_ui, notif->text);
if (nk_button_label(game_ui, "OK")) {
zpl_string_free(notifications[i].title);
zpl_string_free(notifications[i].text);
zpl_array_remove_at(notifications, i);
}
nk_tree_pop(game_ui);
}
}
ypos += nk_window_get_panel(game_ui)->row.height + 80;
nk_end(game_ui);
}
}
if (show_notification_list) {
if (nk_begin(game_ui, "Notifications Manager", nk_rect(width/2.0f - 320, height/2.0f - 240, 640, 480),
NK_WINDOW_BORDER | NK_WINDOW_NO_SCROLLBAR | NK_WINDOW_TITLE | NK_WINDOW_MOVABLE | NK_WINDOW_DYNAMIC )) {
{
nk_layout_row_dynamic(game_ui, 5 , 1);
{
for (zpl_isize i = 0; i < zpl_array_count(notifications); ++i) {
notification *notif = (notifications + i);
if (nk_tree_push_id(game_ui, NK_TREE_TAB, notif->title, NK_MINIMIZED, (int)i)) {
{
nk_label_wrap(game_ui, notif->text);
if (nk_button_label(game_ui, "OK")) {
zpl_string_free(notifications[i].title);
zpl_string_free(notifications[i].text);
zpl_array_remove_at(notifications, i); --i;
}
}
nk_tree_pop(game_ui);
}
}
}
nk_layout_row_dynamic(game_ui, 0, 2);
if (nk_button_label(game_ui, "Clear All")) {
notification_clear();
}
if (nk_button_label(game_ui, "Hide Manager")) {
show_notification_list = 0 ;
}
}
nk_end(game_ui);
}
}
}

View File

@ -0,0 +1,3 @@
#pragma once
void notification_push(const char* title, const char* text);

View File

@ -0,0 +1,14 @@
void spritesheet_viewer(struct nk_context *ctx, struct nk_image spritesheet, Vector2 frameSize, int framesPerRow) {
const int maxFrames = (int)((spritesheet.w*spritesheet.h) / (frameSize.x*frameSize.y));
nk_layout_row_static(ctx, 32, 32, (int)(nk_window_get_size(ctx).x / frameSize.x) -1);
for(int frame = 0; frame < maxFrames; frame++) {
float ox = (frame % framesPerRow) * frameSize.x;
float oy = (int)(frame / framesPerRow) * frameSize.y;
spritesheet.region[0] = (nk_ushort)ox;
spritesheet.region[1] = (nk_ushort)oy;
spritesheet.region[2] = (nk_ushort)frameSize.x;
spritesheet.region[3] = (nk_ushort)frameSize.y;
nk_image(ctx, spritesheet);
nk_labelf(ctx, NK_TEXT_ALIGN_LEFT, "%d", frame);
}
}

View File

@ -0,0 +1,254 @@
// Tooltip system with multilevel modal support
typedef struct _tooltip {
const char *name;
const char *content;
const char **links;
} tooltip;
static tooltip *tooltips = 0;
//~ registration
void tooltip_register(tooltip desc) {
if (!tooltips) {
zpl_array_init(tooltips, zpl_heap());
}
desc.links = 0;
zpl_array_append(tooltips, desc);
}
void tooltip_destroy_all(void) {
if (!tooltips) return;
for (zpl_isize i = 0; i < zpl_array_count(tooltips); ++i) {
tooltip *tp = (tooltips + i);
if (tp->links) {
zpl_array_free(tp->links);
}
}
zpl_array_free(tooltips);
}
void tooltip_build_links(void) {
for (zpl_isize i = 0; i < zpl_array_count(tooltips); ++i) {
tooltip *tp = (tooltips + i);
for (zpl_isize j = 0; j < zpl_array_count(tooltips); ++j) {
tooltip *linked_tp = (tooltips + j);
if (tp == linked_tp)
continue;
if (strstr(tp->content, linked_tp->name)) {
if (!tp->links) {
zpl_array_init(tp->links, zpl_heap());
}
zpl_array_append(tp->links, linked_tp->name);
}
}
}
}
void tooltip_register_defaults(void) {
// test
tooltip_register( (tooltip) { .name = "ASSET_WOOD", .content = "Used as a building material or fuel for the ASSET_FURNACE." } );
tooltip_register( (tooltip) { .name = "ASSET_FURNACE", .content = "Producer used to smelt ASSET_IRON_ORE into ASSET_IRON_INGOT." } );
tooltip_register( (tooltip) { .name = "ASSET_IRON_ORE", .content = "Natural resource that can be smelted in ASSET_FURNACE." } );
tooltip_register( (tooltip) { .name = "ASSET_IRON_INGOT", .content = "Used as a building material. It is smelted from ASSET_IRON_ORE." } );
tooltip_register( (tooltip) { .name = "ASSET_SCREWS", .content = "Used as a building material. It is crafted from ASSET_IRON_PLATES." } );
tooltip_register( (tooltip) { .name = "craft", .content = "Crafting is the process of constructing tools, items, and blocks." } );
tooltip_register( (tooltip) { .name = "smelt", .content = "Smelting is a process of applying heat to ore, to extract a base metal. It is a form of extractive metallurgy. It is used to extract many metals from their ores, including silver, iron, copper, and other base metals." } );
}
//~ rendering
#define TOOLTIP_MOUSE_DIST 400.0f
typedef struct _tooltip_node {
float xpos, ypos;
tooltip *desc;
struct _tooltip_node *next;
} tooltip_node;
static tooltip_node main_tooltip = { 0 };
static bool tooltip__should_stay_open = false;
tooltip *tooltip_find_desc(const char *name) {
for (zpl_isize i = 0; i < zpl_array_count(tooltips); ++i) {
tooltip *tp = (tooltips + i);
if (!strcmp(tp->name, name))
return tp;
}
return 0;
}
const char *tooltip_find_desc_contents(const char *name) {
if (!tooltips) return 0;
for (zpl_isize i = 0; i < zpl_array_count(tooltips); ++i) {
tooltip *tp = (tooltips + i);
if (!strcmp(tp->name, name))
return tp->content;
}
return 0;
}
void tooltip_clear(void);
void tooltip_show(const char* name, float xpos, float ypos) {
if (!tooltips) return;
tooltip *desc = tooltip_find_desc(name);
if (!name) return;
tooltip_clear();
main_tooltip = (tooltip_node) {
.xpos = xpos,
.ypos = ypos,
.desc = desc,
.next = 0
};
}
void tooltip_show_cursor(const char* name) {
Vector2 mpos = GetMousePosition();
tooltip_show(name, mpos.x + 15, mpos.y + 15);
}
void tooltip__clear_node(tooltip_node *node) {
if (node->next) {
tooltip__clear_node(node->next);
zpl_mfree(node->next);
}
}
void tooltip_clear(void) {
tooltip__clear_node(&main_tooltip);
main_tooltip = (tooltip_node) {0};
}
void tooltip_draw_contents(tooltip *desc) {
if (!desc) return;
nk_layout_row_dynamic(game_ui, 0, 1);
nk_label_wrap(game_ui, desc->content);
}
void tooltip__draw_node(tooltip_node *node) {
if (!node) return;
if (!node->desc) return;
tooltip *desc = node->desc;
Vector2 mpos = GetMousePosition();
if (nk_begin_titled(game_ui, zpl_bprintf("%d%s", (int)node->xpos, desc->name), desc->name, nk_rect(node->xpos, node->ypos, 500, 3200),
NK_WINDOW_BORDER | NK_WINDOW_NO_SCROLLBAR | NK_WINDOW_DYNAMIC | NK_WINDOW_TITLE | NK_WINDOW_MOVABLE)) {
tooltip_draw_contents(desc);
if (desc->links) {
nk_label(game_ui, "See Also:", NK_TEXT_LEFT);
nk_layout_row_dynamic(game_ui, 20, 2);
for (zpl_isize i = 0; i < zpl_array_count(desc->links); ++i) {
if (nk_button_label(game_ui, desc->links[i])) {
if (node->next) tooltip__clear_node(node->next);
if (!node->next) node->next = zpl_malloc(sizeof(tooltip_node));
*node->next = (tooltip_node) {
.xpos = mpos.x+15,
.ypos = mpos.y+15,
.desc = tooltip_find_desc(desc->links[i]),
.next = 0
};
}
}
}
// suggest closing tooltip
struct nk_vec2 wpos = nk_window_get_position(game_ui);
struct nk_vec2 wsize = nk_window_get_content_region_size(game_ui);
struct nk_panel *wpanel = nk_window_get_panel(game_ui);
Vector2 tp_pos = (Vector2) { .x = wpos.x + wsize.x/2.0f, .y = wpos.y + wpanel->row.height / 2.0f };
if (Vector2Distance(mpos, tp_pos) <= TOOLTIP_MOUSE_DIST) {
tooltip__should_stay_open = true;
}
#if 0
{
DrawCircleV(tp_pos, TOOLTIP_MOUSE_DIST, BLUE);
}
#endif
nk_end(game_ui);
// draw nested tooltip
if (node->next) {
tooltip__draw_node(node->next);
}
}
}
void tooltip_draw(void) {
// draw tooltip
tooltip__draw_node(&main_tooltip);
if (!tooltip__should_stay_open) {
tooltip_clear();
}
tooltip__should_stay_open = false;
// draw search bar
float width = (float)GetScreenWidth();
float height = (float)GetScreenHeight();
if (nk_begin(game_ui, "#searchbar", nk_rect(width / 2.0f - 200, 15.f, 400, 600), NK_WINDOW_DYNAMIC | NK_WINDOW_BORDER | NK_WINDOW_NO_SCROLLBAR)) {
{
static int len=0; static char buffer[256] = { 0 };
static bool show_all = false;
if (len > 0) {
nk_layout_row_dynamic(game_ui, 15, 1);
if (nk_button_label(game_ui, "clear all")) {
len = 0;
}
}
nk_layout_row_dynamic(game_ui, 35, 1);
if (!(nk_edit_string(game_ui, NK_EDIT_SIMPLE, buffer, &len, 255, nk_filter_ascii) & NK_WIDGET_STATE_ACTIVE) && len == 0 ) {
show_all = true;
}
buffer[len] = 0;
if (len > 0 || show_all) {
if (nk_tree_push(game_ui, NK_TREE_TAB, "results", NK_MAXIMIZED)) {
for (zpl_isize i = 0; i < zpl_array_count(tooltips); ++i) {
tooltip *tp = (tooltips + i);
if (strstr(tp->name, buffer) || show_all) {
if (nk_button_label(game_ui, tp->name)) {
tooltip_show_cursor(tp->name);
}
}
}
nk_tree_pop(game_ui);
}
}
if (IsMouseButtonReleased(MOUSE_BUTTON_LEFT) || len > 0) {
show_all = false;
}
}
nk_end(game_ui);
}
}

View File

@ -0,0 +1,483 @@
enum theme {THEME_BLACK, THEME_WHITE, THEME_RED, THEME_BLUE, THEME_DARK, THEME_ECO};
static void set_style(struct nk_context *ctx, enum theme theme)
{
struct nk_color table[NK_COLOR_COUNT];
if (theme == THEME_WHITE) {
table[NK_COLOR_TEXT] = nk_rgba(70, 70, 70, 255);
table[NK_COLOR_WINDOW] = nk_rgba(175, 175, 175, 255);
table[NK_COLOR_HEADER] = nk_rgba(175, 175, 175, 255);
table[NK_COLOR_BORDER] = nk_rgba(0, 0, 0, 255);
table[NK_COLOR_BUTTON] = nk_rgba(185, 185, 185, 255);
table[NK_COLOR_BUTTON_HOVER] = nk_rgba(170, 170, 170, 255);
table[NK_COLOR_BUTTON_ACTIVE] = nk_rgba(160, 160, 160, 255);
table[NK_COLOR_TOGGLE] = nk_rgba(150, 150, 150, 255);
table[NK_COLOR_TOGGLE_HOVER] = nk_rgba(120, 120, 120, 255);
table[NK_COLOR_TOGGLE_CURSOR] = nk_rgba(175, 175, 175, 255);
table[NK_COLOR_SELECT] = nk_rgba(190, 190, 190, 255);
table[NK_COLOR_SELECT_ACTIVE] = nk_rgba(175, 175, 175, 255);
table[NK_COLOR_SLIDER] = nk_rgba(190, 190, 190, 255);
table[NK_COLOR_SLIDER_CURSOR] = nk_rgba(80, 80, 80, 255);
table[NK_COLOR_SLIDER_CURSOR_HOVER] = nk_rgba(70, 70, 70, 255);
table[NK_COLOR_SLIDER_CURSOR_ACTIVE] = nk_rgba(60, 60, 60, 255);
table[NK_COLOR_PROPERTY] = nk_rgba(175, 175, 175, 255);
table[NK_COLOR_EDIT] = nk_rgba(150, 150, 150, 255);
table[NK_COLOR_EDIT_CURSOR] = nk_rgba(0, 0, 0, 255);
table[NK_COLOR_COMBO] = nk_rgba(175, 175, 175, 255);
table[NK_COLOR_CHART] = nk_rgba(160, 160, 160, 255);
table[NK_COLOR_CHART_COLOR] = nk_rgba(45, 45, 45, 255);
table[NK_COLOR_CHART_COLOR_HIGHLIGHT] = nk_rgba( 255, 0, 0, 255);
table[NK_COLOR_SCROLLBAR] = nk_rgba(180, 180, 180, 255);
table[NK_COLOR_SCROLLBAR_CURSOR] = nk_rgba(140, 140, 140, 255);
table[NK_COLOR_SCROLLBAR_CURSOR_HOVER] = nk_rgba(150, 150, 150, 255);
table[NK_COLOR_SCROLLBAR_CURSOR_ACTIVE] = nk_rgba(160, 160, 160, 255);
table[NK_COLOR_TAB_HEADER] = nk_rgba(180, 180, 180, 255);
nk_style_from_table(ctx, table);
} else if (theme == THEME_RED) {
table[NK_COLOR_TEXT] = nk_rgba(190, 190, 190, 255);
table[NK_COLOR_WINDOW] = nk_rgba(30, 33, 40, 215);
table[NK_COLOR_HEADER] = nk_rgba(181, 45, 69, 220);
table[NK_COLOR_BORDER] = nk_rgba(51, 55, 67, 255);
table[NK_COLOR_BUTTON] = nk_rgba(181, 45, 69, 255);
table[NK_COLOR_BUTTON_HOVER] = nk_rgba(190, 50, 70, 255);
table[NK_COLOR_BUTTON_ACTIVE] = nk_rgba(195, 55, 75, 255);
table[NK_COLOR_TOGGLE] = nk_rgba(51, 55, 67, 255);
table[NK_COLOR_TOGGLE_HOVER] = nk_rgba(45, 60, 60, 255);
table[NK_COLOR_TOGGLE_CURSOR] = nk_rgba(181, 45, 69, 255);
table[NK_COLOR_SELECT] = nk_rgba(51, 55, 67, 255);
table[NK_COLOR_SELECT_ACTIVE] = nk_rgba(181, 45, 69, 255);
table[NK_COLOR_SLIDER] = nk_rgba(51, 55, 67, 255);
table[NK_COLOR_SLIDER_CURSOR] = nk_rgba(181, 45, 69, 255);
table[NK_COLOR_SLIDER_CURSOR_HOVER] = nk_rgba(186, 50, 74, 255);
table[NK_COLOR_SLIDER_CURSOR_ACTIVE] = nk_rgba(191, 55, 79, 255);
table[NK_COLOR_PROPERTY] = nk_rgba(51, 55, 67, 255);
table[NK_COLOR_EDIT] = nk_rgba(51, 55, 67, 225);
table[NK_COLOR_EDIT_CURSOR] = nk_rgba(190, 190, 190, 255);
table[NK_COLOR_COMBO] = nk_rgba(51, 55, 67, 255);
table[NK_COLOR_CHART] = nk_rgba(51, 55, 67, 255);
table[NK_COLOR_CHART_COLOR] = nk_rgba(170, 40, 60, 255);
table[NK_COLOR_CHART_COLOR_HIGHLIGHT] = nk_rgba( 255, 0, 0, 255);
table[NK_COLOR_SCROLLBAR] = nk_rgba(30, 33, 40, 255);
table[NK_COLOR_SCROLLBAR_CURSOR] = nk_rgba(64, 84, 95, 255);
table[NK_COLOR_SCROLLBAR_CURSOR_HOVER] = nk_rgba(70, 90, 100, 255);
table[NK_COLOR_SCROLLBAR_CURSOR_ACTIVE] = nk_rgba(75, 95, 105, 255);
table[NK_COLOR_TAB_HEADER] = nk_rgba(181, 45, 69, 220);
nk_style_from_table(ctx, table);
} else if (theme == THEME_ECO) {
table[NK_COLOR_TEXT] = nk_rgba(190, 190, 190, 255);
table[NK_COLOR_WINDOW] = nk_rgba(40, 43, 10, 235);
table[NK_COLOR_HEADER] = nk_rgba(32, 96, 64 , 220);
table[NK_COLOR_BORDER] = nk_rgba(51, 55, 67, 255);
table[NK_COLOR_BUTTON] = nk_rgba(20, 23, 30, 215);
table[NK_COLOR_BUTTON_HOVER] = nk_rgba(32, 96, 64 , 235);
table[NK_COLOR_BUTTON_ACTIVE] = nk_rgba(52, 116, 84 , 255);
table[NK_COLOR_TOGGLE] = nk_rgba(51, 55, 67, 255);
table[NK_COLOR_TOGGLE_HOVER] = nk_rgba(45, 60, 60, 255);
table[NK_COLOR_TOGGLE_CURSOR] = nk_rgba(181, 45, 69, 255);
table[NK_COLOR_SELECT] = nk_rgba(20, 23, 30, 215);
table[NK_COLOR_SELECT_ACTIVE] = nk_rgba(181, 45, 69, 255);
table[NK_COLOR_SLIDER] = nk_rgba(51, 55, 67, 255);
table[NK_COLOR_SLIDER_CURSOR] = nk_rgba(181, 45, 69, 255);
table[NK_COLOR_SLIDER_CURSOR_HOVER] = nk_rgba(186, 50, 74, 255);
table[NK_COLOR_SLIDER_CURSOR_ACTIVE] = nk_rgba(191, 55, 79, 255);
table[NK_COLOR_PROPERTY] = nk_rgba(51, 55, 67, 255);
table[NK_COLOR_EDIT] = nk_rgba(51, 55, 67, 225);
table[NK_COLOR_EDIT_CURSOR] = nk_rgba(190, 190, 190, 255);
table[NK_COLOR_COMBO] = nk_rgba(51, 55, 67, 255);
table[NK_COLOR_CHART] = nk_rgba(51, 55, 67, 255);
table[NK_COLOR_CHART_COLOR] = nk_rgba(170, 40, 60, 255);
table[NK_COLOR_CHART_COLOR_HIGHLIGHT] = nk_rgba( 255, 0, 0, 255);
table[NK_COLOR_SCROLLBAR] = nk_rgba(30, 33, 40, 255);
table[NK_COLOR_SCROLLBAR_CURSOR] = nk_rgba(64, 84, 95, 255);
table[NK_COLOR_SCROLLBAR_CURSOR_HOVER] = nk_rgba(70, 90, 100, 255);
table[NK_COLOR_SCROLLBAR_CURSOR_ACTIVE] = nk_rgba(75, 95, 105, 255);
table[NK_COLOR_TAB_HEADER] = nk_rgba(32, 96, 64 , 220);
nk_style_from_table(ctx, table);
} else if (theme == THEME_BLUE) {
table[NK_COLOR_TEXT] = nk_rgba(20, 20, 20, 255);
table[NK_COLOR_WINDOW] = nk_rgba(202, 212, 214, 215);
table[NK_COLOR_HEADER] = nk_rgba(137, 182, 224, 220);
table[NK_COLOR_BORDER] = nk_rgba(140, 159, 173, 255);
table[NK_COLOR_BUTTON] = nk_rgba(137, 182, 224, 255);
table[NK_COLOR_BUTTON_HOVER] = nk_rgba(142, 187, 229, 255);
table[NK_COLOR_BUTTON_ACTIVE] = nk_rgba(147, 192, 234, 255);
table[NK_COLOR_TOGGLE] = nk_rgba(177, 210, 210, 255);
table[NK_COLOR_TOGGLE_HOVER] = nk_rgba(182, 215, 215, 255);
table[NK_COLOR_TOGGLE_CURSOR] = nk_rgba(137, 182, 224, 255);
table[NK_COLOR_SELECT] = nk_rgba(177, 210, 210, 255);
table[NK_COLOR_SELECT_ACTIVE] = nk_rgba(137, 182, 224, 255);
table[NK_COLOR_SLIDER] = nk_rgba(177, 210, 210, 255);
table[NK_COLOR_SLIDER_CURSOR] = nk_rgba(137, 182, 224, 245);
table[NK_COLOR_SLIDER_CURSOR_HOVER] = nk_rgba(142, 188, 229, 255);
table[NK_COLOR_SLIDER_CURSOR_ACTIVE] = nk_rgba(147, 193, 234, 255);
table[NK_COLOR_PROPERTY] = nk_rgba(210, 210, 210, 255);
table[NK_COLOR_EDIT] = nk_rgba(210, 210, 210, 225);
table[NK_COLOR_EDIT_CURSOR] = nk_rgba(20, 20, 20, 255);
table[NK_COLOR_COMBO] = nk_rgba(210, 210, 210, 255);
table[NK_COLOR_CHART] = nk_rgba(210, 210, 210, 255);
table[NK_COLOR_CHART_COLOR] = nk_rgba(137, 182, 224, 255);
table[NK_COLOR_CHART_COLOR_HIGHLIGHT] = nk_rgba( 255, 0, 0, 255);
table[NK_COLOR_SCROLLBAR] = nk_rgba(190, 200, 200, 255);
table[NK_COLOR_SCROLLBAR_CURSOR] = nk_rgba(64, 84, 95, 255);
table[NK_COLOR_SCROLLBAR_CURSOR_HOVER] = nk_rgba(70, 90, 100, 255);
table[NK_COLOR_SCROLLBAR_CURSOR_ACTIVE] = nk_rgba(75, 95, 105, 255);
table[NK_COLOR_TAB_HEADER] = nk_rgba(156, 193, 220, 255);
nk_style_from_table(ctx, table);
} else if (theme == THEME_DARK) {
table[NK_COLOR_TEXT] = nk_rgba(210, 210, 210, 255);
table[NK_COLOR_WINDOW] = nk_rgba(57, 67, 71, 215);
table[NK_COLOR_HEADER] = nk_rgba(51, 51, 56, 220);
table[NK_COLOR_BORDER] = nk_rgba(46, 46, 46, 255);
table[NK_COLOR_BUTTON] = nk_rgba(48, 83, 111, 255);
table[NK_COLOR_BUTTON_HOVER] = nk_rgba(58, 93, 121, 255);
table[NK_COLOR_BUTTON_ACTIVE] = nk_rgba(63, 98, 126, 255);
table[NK_COLOR_TOGGLE] = nk_rgba(50, 58, 61, 255);
table[NK_COLOR_TOGGLE_HOVER] = nk_rgba(45, 53, 56, 255);
table[NK_COLOR_TOGGLE_CURSOR] = nk_rgba(48, 83, 111, 255);
table[NK_COLOR_SELECT] = nk_rgba(57, 67, 61, 255);
table[NK_COLOR_SELECT_ACTIVE] = nk_rgba(48, 83, 111, 255);
table[NK_COLOR_SLIDER] = nk_rgba(50, 58, 61, 255);
table[NK_COLOR_SLIDER_CURSOR] = nk_rgba(48, 83, 111, 245);
table[NK_COLOR_SLIDER_CURSOR_HOVER] = nk_rgba(53, 88, 116, 255);
table[NK_COLOR_SLIDER_CURSOR_ACTIVE] = nk_rgba(58, 93, 121, 255);
table[NK_COLOR_PROPERTY] = nk_rgba(50, 58, 61, 255);
table[NK_COLOR_EDIT] = nk_rgba(50, 58, 61, 225);
table[NK_COLOR_EDIT_CURSOR] = nk_rgba(210, 210, 210, 255);
table[NK_COLOR_COMBO] = nk_rgba(50, 58, 61, 255);
table[NK_COLOR_CHART] = nk_rgba(50, 58, 61, 255);
table[NK_COLOR_CHART_COLOR] = nk_rgba(48, 83, 111, 255);
table[NK_COLOR_CHART_COLOR_HIGHLIGHT] = nk_rgba(255, 0, 0, 255);
table[NK_COLOR_SCROLLBAR] = nk_rgba(50, 58, 61, 255);
table[NK_COLOR_SCROLLBAR_CURSOR] = nk_rgba(48, 83, 111, 255);
table[NK_COLOR_SCROLLBAR_CURSOR_HOVER] = nk_rgba(53, 88, 116, 255);
table[NK_COLOR_SCROLLBAR_CURSOR_ACTIVE] = nk_rgba(58, 93, 121, 255);
table[NK_COLOR_TAB_HEADER] = nk_rgba(48, 83, 111, 255);
nk_style_from_table(ctx, table);
} else {
nk_style_default(ctx);
}
}
#if 0
typedef struct media {
GLint skin;
struct nk_image menu;
struct nk_image check;
struct nk_image check_cursor;
struct nk_image option;
struct nk_image option_cursor;
struct nk_image header;
struct nk_image window;
struct nk_image scrollbar_inc_button;
struct nk_image scrollbar_inc_button_hover;
struct nk_image scrollbar_dec_button;
struct nk_image scrollbar_dec_button_hover;
struct nk_image button;
struct nk_image button_hover;
struct nk_image button_active;
struct nk_image tab_minimize;
struct nk_image tab_maximize;
struct nk_image slider;
struct nk_image slider_hover;
struct nk_image slider_active;
} media;
void nk_skin_gwen(void) {
media.skin = image_load("../skins/gwen.png");
media.check = nk_subimage_id(media.skin, 512,512, nk_rect(464,32,15,15));
media.check_cursor = nk_subimage_id(media.skin, 512,512, nk_rect(450,34,11,11));
media.option = nk_subimage_id(media.skin, 512,512, nk_rect(464,64,15,15));
media.option_cursor = nk_subimage_id(media.skin, 512,512, nk_rect(451,67,9,9));
media.header = nk_subimage_id(media.skin, 512,512, nk_rect(128,0,127,24));
media.window = nk_subimage_id(media.skin, 512,512, nk_rect(128,23,127,104));
media.scrollbar_inc_button = nk_subimage_id(media.skin, 512,512, nk_rect(464,256,15,15));
media.scrollbar_inc_button_hover = nk_subimage_id(media.skin, 512,512, nk_rect(464,320,15,15));
media.scrollbar_dec_button = nk_subimage_id(media.skin, 512,512, nk_rect(464,224,15,15));
media.scrollbar_dec_button_hover = nk_subimage_id(media.skin, 512,512, nk_rect(464,288,15,15));
media.button = nk_subimage_id(media.skin, 512,512, nk_rect(384,336,127,31));
media.button_hover = nk_subimage_id(media.skin, 512,512, nk_rect(384,368,127,31));
media.button_active = nk_subimage_id(media.skin, 512,512, nk_rect(384,400,127,31));
media.tab_minimize = nk_subimage_id(media.skin, 512,512, nk_rect(451, 99, 9, 9));
media.tab_maximize = nk_subimage_id(media.skin, 512,512, nk_rect(467,99,9,9));
media.slider = nk_subimage_id(media.skin, 512,512, nk_rect(418,33,11,14));
media.slider_hover = nk_subimage_id(media.skin, 512,512, nk_rect(418,49,11,14));
media.slider_active = nk_subimage_id(media.skin, 512,512, nk_rect(418,64,11,14));
/* window */
ctx.style.window.background = nk_rgb(204,204,204);
ctx.style.window.fixed_background = nk_style_item_image(media.window);
ctx.style.window.border_color = nk_rgb(67,67,67);
ctx.style.window.combo_border_color = nk_rgb(67,67,67);
ctx.style.window.contextual_border_color = nk_rgb(67,67,67);
ctx.style.window.menu_border_color = nk_rgb(67,67,67);
ctx.style.window.group_border_color = nk_rgb(67,67,67);
ctx.style.window.tooltip_border_color = nk_rgb(67,67,67);
ctx.style.window.scrollbar_size = nk_vec2(16,16);
ctx.style.window.border_color = nk_rgba(0,0,0,0);
ctx.style.window.padding = nk_vec2(8,4);
ctx.style.window.border = 3;
/* window header */
ctx.style.window.header.normal = nk_style_item_image(media.header);
ctx.style.window.header.hover = nk_style_item_image(media.header);
ctx.style.window.header.active = nk_style_item_image(media.header);
ctx.style.window.header.label_normal = nk_rgb(95,95,95);
ctx.style.window.header.label_hover = nk_rgb(95,95,95);
ctx.style.window.header.label_active = nk_rgb(95,95,95);
/* scrollbar */
ctx.style.scrollv.normal = nk_style_item_color(nk_rgb(184,184,184));
ctx.style.scrollv.hover = nk_style_item_color(nk_rgb(184,184,184));
ctx.style.scrollv.active = nk_style_item_color(nk_rgb(184,184,184));
ctx.style.scrollv.cursor_normal = nk_style_item_color(nk_rgb(220,220,220));
ctx.style.scrollv.cursor_hover = nk_style_item_color(nk_rgb(235,235,235));
ctx.style.scrollv.cursor_active = nk_style_item_color(nk_rgb(99,202,255));
ctx.style.scrollv.dec_symbol = NK_SYMBOL_NONE;
ctx.style.scrollv.inc_symbol = NK_SYMBOL_NONE;
ctx.style.scrollv.show_buttons = nk_true;
ctx.style.scrollv.border_color = nk_rgb(81,81,81);
ctx.style.scrollv.cursor_border_color = nk_rgb(81,81,81);
ctx.style.scrollv.border = 1;
ctx.style.scrollv.rounding = 0;
ctx.style.scrollv.border_cursor = 1;
ctx.style.scrollv.rounding_cursor = 2;
/* scrollbar buttons */
ctx.style.scrollv.inc_button.normal = nk_style_item_image(media.scrollbar_inc_button);
ctx.style.scrollv.inc_button.hover = nk_style_item_image(media.scrollbar_inc_button_hover);
ctx.style.scrollv.inc_button.active = nk_style_item_image(media.scrollbar_inc_button_hover);
ctx.style.scrollv.inc_button.border_color = nk_rgba(0,0,0,0);
ctx.style.scrollv.inc_button.text_background = nk_rgba(0,0,0,0);
ctx.style.scrollv.inc_button.text_normal = nk_rgba(0,0,0,0);
ctx.style.scrollv.inc_button.text_hover = nk_rgba(0,0,0,0);
ctx.style.scrollv.inc_button.text_active = nk_rgba(0,0,0,0);
ctx.style.scrollv.inc_button.border = 0.0f;
ctx.style.scrollv.dec_button.normal = nk_style_item_image(media.scrollbar_dec_button);
ctx.style.scrollv.dec_button.hover = nk_style_item_image(media.scrollbar_dec_button_hover);
ctx.style.scrollv.dec_button.active = nk_style_item_image(media.scrollbar_dec_button_hover);
ctx.style.scrollv.dec_button.border_color = nk_rgba(0,0,0,0);
ctx.style.scrollv.dec_button.text_background = nk_rgba(0,0,0,0);
ctx.style.scrollv.dec_button.text_normal = nk_rgba(0,0,0,0);
ctx.style.scrollv.dec_button.text_hover = nk_rgba(0,0,0,0);
ctx.style.scrollv.dec_button.text_active = nk_rgba(0,0,0,0);
ctx.style.scrollv.dec_button.border = 0.0f;
/* checkbox toggle */
{struct nk_style_toggle *toggle;
toggle = &ctx.style.checkbox;
toggle->normal = nk_style_item_image(media.check);
toggle->hover = nk_style_item_image(media.check);
toggle->active = nk_style_item_image(media.check);
toggle->cursor_normal = nk_style_item_image(media.check_cursor);
toggle->cursor_hover = nk_style_item_image(media.check_cursor);
toggle->text_normal = nk_rgb(95,95,95);
toggle->text_hover = nk_rgb(95,95,95);
toggle->text_active = nk_rgb(95,95,95);}
/* option toggle */
{struct nk_style_toggle *toggle;
toggle = &ctx.style.option;
toggle->normal = nk_style_item_image(media.option);
toggle->hover = nk_style_item_image(media.option);
toggle->active = nk_style_item_image(media.option);
toggle->cursor_normal = nk_style_item_image(media.option_cursor);
toggle->cursor_hover = nk_style_item_image(media.option_cursor);
toggle->text_normal = nk_rgb(95,95,95);
toggle->text_hover = nk_rgb(95,95,95);
toggle->text_active = nk_rgb(95,95,95);}
/* default button */
ctx.style.button.normal = nk_style_item_image(media.button);
ctx.style.button.hover = nk_style_item_image(media.button_hover);
ctx.style.button.active = nk_style_item_image(media.button_active);
ctx.style.button.border_color = nk_rgba(0,0,0,0);
ctx.style.button.text_background = nk_rgba(0,0,0,0);
ctx.style.button.text_normal = nk_rgb(95,95,95);
ctx.style.button.text_hover = nk_rgb(95,95,95);
ctx.style.button.text_active = nk_rgb(95,95,95);
/* default text */
ctx.style.text.color = nk_rgb(95,95,95);
/* contextual button */
ctx.style.contextual_button.normal = nk_style_item_color(nk_rgb(206,206,206));
ctx.style.contextual_button.hover = nk_style_item_color(nk_rgb(229,229,229));
ctx.style.contextual_button.active = nk_style_item_color(nk_rgb(99,202,255));
ctx.style.contextual_button.border_color = nk_rgba(0,0,0,0);
ctx.style.contextual_button.text_background = nk_rgba(0,0,0,0);
ctx.style.contextual_button.text_normal = nk_rgb(95,95,95);
ctx.style.contextual_button.text_hover = nk_rgb(95,95,95);
ctx.style.contextual_button.text_active = nk_rgb(95,95,95);
/* menu button */
ctx.style.menu_button.normal = nk_style_item_color(nk_rgb(206,206,206));
ctx.style.menu_button.hover = nk_style_item_color(nk_rgb(229,229,229));
ctx.style.menu_button.active = nk_style_item_color(nk_rgb(99,202,255));
ctx.style.menu_button.border_color = nk_rgba(0,0,0,0);
ctx.style.menu_button.text_background = nk_rgba(0,0,0,0);
ctx.style.menu_button.text_normal = nk_rgb(95,95,95);
ctx.style.menu_button.text_hover = nk_rgb(95,95,95);
ctx.style.menu_button.text_active = nk_rgb(95,95,95);
/* tree */
ctx.style.tab.text = nk_rgb(95,95,95);
ctx.style.tab.tab_minimize_button.normal = nk_style_item_image(media.tab_minimize);
ctx.style.tab.tab_minimize_button.hover = nk_style_item_image(media.tab_minimize);
ctx.style.tab.tab_minimize_button.active = nk_style_item_image(media.tab_minimize);
ctx.style.tab.tab_minimize_button.text_background = nk_rgba(0,0,0,0);
ctx.style.tab.tab_minimize_button.text_normal = nk_rgba(0,0,0,0);
ctx.style.tab.tab_minimize_button.text_hover = nk_rgba(0,0,0,0);
ctx.style.tab.tab_minimize_button.text_active = nk_rgba(0,0,0,0);
ctx.style.tab.tab_maximize_button.normal = nk_style_item_image(media.tab_maximize);
ctx.style.tab.tab_maximize_button.hover = nk_style_item_image(media.tab_maximize);
ctx.style.tab.tab_maximize_button.active = nk_style_item_image(media.tab_maximize);
ctx.style.tab.tab_maximize_button.text_background = nk_rgba(0,0,0,0);
ctx.style.tab.tab_maximize_button.text_normal = nk_rgba(0,0,0,0);
ctx.style.tab.tab_maximize_button.text_hover = nk_rgba(0,0,0,0);
ctx.style.tab.tab_maximize_button.text_active = nk_rgba(0,0,0,0);
ctx.style.tab.node_minimize_button.normal = nk_style_item_image(media.tab_minimize);
ctx.style.tab.node_minimize_button.hover = nk_style_item_image(media.tab_minimize);
ctx.style.tab.node_minimize_button.active = nk_style_item_image(media.tab_minimize);
ctx.style.tab.node_minimize_button.text_background = nk_rgba(0,0,0,0);
ctx.style.tab.node_minimize_button.text_normal = nk_rgba(0,0,0,0);
ctx.style.tab.node_minimize_button.text_hover = nk_rgba(0,0,0,0);
ctx.style.tab.node_minimize_button.text_active = nk_rgba(0,0,0,0);
ctx.style.tab.node_maximize_button.normal = nk_style_item_image(media.tab_maximize);
ctx.style.tab.node_maximize_button.hover = nk_style_item_image(media.tab_maximize);
ctx.style.tab.node_maximize_button.active = nk_style_item_image(media.tab_maximize);
ctx.style.tab.node_maximize_button.text_background = nk_rgba(0,0,0,0);
ctx.style.tab.node_maximize_button.text_normal = nk_rgba(0,0,0,0);
ctx.style.tab.node_maximize_button.text_hover = nk_rgba(0,0,0,0);
ctx.style.tab.node_maximize_button.text_active = nk_rgba(0,0,0,0);
/* selectable */
ctx.style.selectable.normal = nk_style_item_color(nk_rgb(206,206,206));
ctx.style.selectable.hover = nk_style_item_color(nk_rgb(206,206,206));
ctx.style.selectable.pressed = nk_style_item_color(nk_rgb(206,206,206));
ctx.style.selectable.normal_active = nk_style_item_color(nk_rgb(185,205,248));
ctx.style.selectable.hover_active = nk_style_item_color(nk_rgb(185,205,248));
ctx.style.selectable.pressed_active = nk_style_item_color(nk_rgb(185,205,248));
ctx.style.selectable.text_normal = nk_rgb(95,95,95);
ctx.style.selectable.text_hover = nk_rgb(95,95,95);
ctx.style.selectable.text_pressed = nk_rgb(95,95,95);
ctx.style.selectable.text_normal_active = nk_rgb(95,95,95);
ctx.style.selectable.text_hover_active = nk_rgb(95,95,95);
ctx.style.selectable.text_pressed_active = nk_rgb(95,95,95);
/* slider */
ctx.style.slider.normal = nk_style_item_hide();
ctx.style.slider.hover = nk_style_item_hide();
ctx.style.slider.active = nk_style_item_hide();
ctx.style.slider.bar_normal = nk_rgb(156,156,156);
ctx.style.slider.bar_hover = nk_rgb(156,156,156);
ctx.style.slider.bar_active = nk_rgb(156,156,156);
ctx.style.slider.bar_filled = nk_rgb(156,156,156);
ctx.style.slider.cursor_normal = nk_style_item_image(media.slider);
ctx.style.slider.cursor_hover = nk_style_item_image(media.slider_hover);
ctx.style.slider.cursor_active = nk_style_item_image(media.slider_active);
ctx.style.slider.cursor_size = nk_vec2(16.5f,21);
ctx.style.slider.bar_height = 1;
/* progressbar */
ctx.style.progress.normal = nk_style_item_color(nk_rgb(231,231,231));
ctx.style.progress.hover = nk_style_item_color(nk_rgb(231,231,231));
ctx.style.progress.active = nk_style_item_color(nk_rgb(231,231,231));
ctx.style.progress.cursor_normal = nk_style_item_color(nk_rgb(63,242,93));
ctx.style.progress.cursor_hover = nk_style_item_color(nk_rgb(63,242,93));
ctx.style.progress.cursor_active = nk_style_item_color(nk_rgb(63,242,93));
ctx.style.progress.border_color = nk_rgb(114,116,115);
ctx.style.progress.padding = nk_vec2(0,0);
ctx.style.progress.border = 2;
ctx.style.progress.rounding = 1;
/* combo */
ctx.style.combo.normal = nk_style_item_color(nk_rgb(216,216,216));
ctx.style.combo.hover = nk_style_item_color(nk_rgb(216,216,216));
ctx.style.combo.active = nk_style_item_color(nk_rgb(216,216,216));
ctx.style.combo.border_color = nk_rgb(95,95,95);
ctx.style.combo.label_normal = nk_rgb(95,95,95);
ctx.style.combo.label_hover = nk_rgb(95,95,95);
ctx.style.combo.label_active = nk_rgb(95,95,95);
ctx.style.combo.border = 1;
ctx.style.combo.rounding = 1;
/* combo button */
ctx.style.combo.button.normal = nk_style_item_color(nk_rgb(216,216,216));
ctx.style.combo.button.hover = nk_style_item_color(nk_rgb(216,216,216));
ctx.style.combo.button.active = nk_style_item_color(nk_rgb(216,216,216));
ctx.style.combo.button.text_background = nk_rgb(216,216,216);
ctx.style.combo.button.text_normal = nk_rgb(95,95,95);
ctx.style.combo.button.text_hover = nk_rgb(95,95,95);
ctx.style.combo.button.text_active = nk_rgb(95,95,95);
/* property */
ctx.style.property.normal = nk_style_item_color(nk_rgb(216,216,216));
ctx.style.property.hover = nk_style_item_color(nk_rgb(216,216,216));
ctx.style.property.active = nk_style_item_color(nk_rgb(216,216,216));
ctx.style.property.border_color = nk_rgb(81,81,81);
ctx.style.property.label_normal = nk_rgb(95,95,95);
ctx.style.property.label_hover = nk_rgb(95,95,95);
ctx.style.property.label_active = nk_rgb(95,95,95);
ctx.style.property.sym_left = NK_SYMBOL_TRIANGLE_LEFT;
ctx.style.property.sym_right = NK_SYMBOL_TRIANGLE_RIGHT;
ctx.style.property.rounding = 10;
ctx.style.property.border = 1;
/* edit */
ctx.style.edit.normal = nk_style_item_color(nk_rgb(240,240,240));
ctx.style.edit.hover = nk_style_item_color(nk_rgb(240,240,240));
ctx.style.edit.active = nk_style_item_color(nk_rgb(240,240,240));
ctx.style.edit.border_color = nk_rgb(62,62,62);
ctx.style.edit.cursor_normal = nk_rgb(99,202,255);
ctx.style.edit.cursor_hover = nk_rgb(99,202,255);
ctx.style.edit.cursor_text_normal = nk_rgb(95,95,95);
ctx.style.edit.cursor_text_hover = nk_rgb(95,95,95);
ctx.style.edit.text_normal = nk_rgb(95,95,95);
ctx.style.edit.text_hover = nk_rgb(95,95,95);
ctx.style.edit.text_active = nk_rgb(95,95,95);
ctx.style.edit.selected_normal = nk_rgb(99,202,255);
ctx.style.edit.selected_hover = nk_rgb(99,202,255);
ctx.style.edit.selected_text_normal = nk_rgb(95,95,95);
ctx.style.edit.selected_text_hover = nk_rgb(95,95,95);
ctx.style.edit.border = 1;
ctx.style.edit.rounding = 2;
/* property buttons */
ctx.style.property.dec_button.normal = nk_style_item_color(nk_rgb(216,216,216));
ctx.style.property.dec_button.hover = nk_style_item_color(nk_rgb(216,216,216));
ctx.style.property.dec_button.active = nk_style_item_color(nk_rgb(216,216,216));
ctx.style.property.dec_button.text_background = nk_rgba(0,0,0,0);
ctx.style.property.dec_button.text_normal = nk_rgb(95,95,95);
ctx.style.property.dec_button.text_hover = nk_rgb(95,95,95);
ctx.style.property.dec_button.text_active = nk_rgb(95,95,95);
ctx.style.property.inc_button = ctx.style.property.dec_button;
/* property edit */
ctx.style.property.edit.normal = nk_style_item_color(nk_rgb(216,216,216));
ctx.style.property.edit.hover = nk_style_item_color(nk_rgb(216,216,216));
ctx.style.property.edit.active = nk_style_item_color(nk_rgb(216,216,216));
ctx.style.property.edit.border_color = nk_rgba(0,0,0,0);
ctx.style.property.edit.cursor_normal = nk_rgb(95,95,95);
ctx.style.property.edit.cursor_hover = nk_rgb(95,95,95);
ctx.style.property.edit.cursor_text_normal = nk_rgb(216,216,216);
ctx.style.property.edit.cursor_text_hover = nk_rgb(216,216,216);
ctx.style.property.edit.text_normal = nk_rgb(95,95,95);
ctx.style.property.edit.text_hover = nk_rgb(95,95,95);
ctx.style.property.edit.text_active = nk_rgb(95,95,95);
ctx.style.property.edit.selected_normal = nk_rgb(95,95,95);
ctx.style.property.edit.selected_hover = nk_rgb(95,95,95);
ctx.style.property.edit.selected_text_normal = nk_rgb(216,216,216);
ctx.style.property.edit.selected_text_hover = nk_rgb(216,216,216);
/* chart */
ctx.style.chart.background = nk_style_item_color(nk_rgb(216,216,216));
ctx.style.chart.border_color = nk_rgb(81,81,81);
ctx.style.chart.color = nk_rgb(95,95,95);
ctx.style.chart.selected_color = nk_rgb(255,0,0);
ctx.style.chart.border = 1;
}
#endif

View File

@ -4,7 +4,7 @@
// use your favorite editor to quickly navigate between various files.
// 1) Register a new Asset ID
#include "gen/assets.h"
#include "models/assets.h"
// 2) Add the asset to the asset list
#include "assets_list.c"
@ -20,4 +20,3 @@
// NOTE(zaklaus): Register an item
#include "items_list.c"

View File

@ -0,0 +1,154 @@
#include "models/assets.h"
#include "raylib.h"
#include "gen/texgen.h"
#include "models/database.h"
#include <stdint.h>
//#define ASSETS_COUNT (sizeof(assets)/sizeof(asset))
typedef struct {
asset_id id;
asset_kind kind;
union {
Texture2D tex;
Sound snd;
};
// NOTE(zaklaus): metadata
} asset;
//#include "lists/assets_list.c"
static asset *assets;
#define ASSETS_COUNT (zpl_array_count(assets))
#define ASSET_FRAME_RENDER_MS (1.0/1.0)
#define ASSET_FRAME_SKIP 4
static int64_t assets_frame_counter = 1;
static double assets_frame_next_draw = 0.0;
#include <time.h>
static uint16_t asset_counter;
void assets_new(const char *name) {
assert(asset_counter < MAX_ASSETS);
db_exec(zpl_bprintf("INSERT INTO assets (id, name) VALUES (%d, '%s');", asset_counter++, name));
}
void assets_db_init(void) {
for (uint16_t i=0; i<MAX_INTERNAL_ASSETS; i++) {
assets_new(asset_names[i]+6);
}
asset_counter = NEXT_FREE_ASSET;
}
void assets_db(void) {
zpl_array_init(assets, zpl_heap());
db_push("SELECT * FROM resources;");
for (size_t i=0, end=db_rows(); i<end; i++) {
asset a={0};
a.id = db_int("asset", i);
a.kind = db_int("kind", i);
zpl_array_append(assets, a);
}
db_pop();
}
int32_t assets_setup(void) {
for (uint32_t i=0; i<ASSETS_COUNT; i++) {
asset *b = &assets[i];
switch (b->kind) {
case AKIND_TEXTURE: {
b->tex = texgen_build_sprite(b->id);
}break;
case AKIND_ANIM: {
b->tex = texgen_build_anim(b->id, 0);
}break;
case AKIND_SOUND: {
// TODO(zaklaus): soundgen
}break;
default: break;
}
}
assets_frame_next_draw = get_cached_time() + ASSET_FRAME_RENDER_MS;
return 0;
}
int32_t assets_frame(void) {
if (assets_frame_next_draw < get_cached_time()) {
for (uint32_t i=0; i<ASSETS_COUNT; i++) {
asset *b = &assets[i];
switch (b->kind) {
case AKIND_ANIM: {
UnloadTexture(b->tex);
b->tex = texgen_build_anim(b->id, assets_frame_counter);
}break;
default: break;
}
}
assets_frame_next_draw = get_cached_time() + ASSET_FRAME_RENDER_MS;
assets_frame_counter += ASSET_FRAME_SKIP;
}
return 0;
}
void assets_destroy(void) {
for (uint32_t i=0; i<ASSETS_COUNT; i++) {
switch (assets[i].kind) {
case AKIND_ANIM:
case AKIND_TEXTURE: {
UnloadTexture(assets[i].tex);
}break;
case AKIND_SOUND: {
// TODO(zaklaus): soundgen
}break;
default: break;
}
}
}
uint16_t assets_find(asset_id id) {
for (uint16_t i=0; i<ASSETS_COUNT; i++) {
if (assets[i].id == id)
return i;
}
//ZPL_PANIC("Unknown asset id: %d\n", id);
return ASSET_INVALID;
}
asset_kind assets_get_kind(uint16_t id) {
return assets[id].kind;
}
const char* assets_get_kind_name(uint16_t id) {
static const char* names[] = { "Texture", "Animated Texture", "Sound" };
return names[assets[id].kind];
}
void *assets_get_snd(uint16_t id) {
return (void*)&assets[id].snd;;
}
void *assets_get_tex(uint16_t id) {
return (void*)&assets[id].tex;
}
const char *asset_names[] = {
#define X(id) #id,
_ASSETS
#undef X
};

View File

@ -0,0 +1,33 @@
#pragma once
#include "platform/system.h"
#include "assets_ids.h"
typedef enum {
AKIND_TEXTURE,
AKIND_ANIM,
AKIND_SOUND,
FORCE_AKIND_UINT8 = UINT8_MAX
} asset_kind;
void assets_db_init(void);
void assets_db(void);
void assets_new(const char *name);
int32_t assets_setup(void);
int32_t assets_frame(void);
void assets_destroy(void);
uint16_t assets_find(asset_id id);
asset_kind assets_get_kind(uint16_t id);
const char *assets_get_kind_name(uint16_t id);
void *assets_get_snd(uint16_t id);
void *assets_get_tex(uint16_t id);
uint16_t assets_resolve_proxy(uint16_t id);
// NOTE(zaklaus): client only
#define ASSET_SRC_RECT() ((Rectangle){0, 0, 64, 64})
#define ASSET_DST_RECT(x,y) ((Rectangle){x, y, 64, 64})
#define ASSET_SRC_RECT_TEX(w,h) ((Rectangle){0, 0, (float)w, (float)h})
#define ASSET_DST_RECT_TEX(x,y,w,h) ((Rectangle){x, y, (float)w, (float)h})

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