Compare commits
162 Commits
isolation_
...
master
Author | SHA1 | Date |
---|---|---|
Dominik Madarász | 2d593809d7 | |
Dominik Madarász | 23645ed32a | |
Dominik Madarász | 29d9b9306d | |
Dominik Madarász | 6e09c09037 | |
Dominik Madarász | b348400c1a | |
Dominik Madarász | a9ea1e9335 | |
Dominik Madarász | e2e6ef9185 | |
Dominik Madarász | 3fba1bc1d4 | |
Dominik Madarász | e43b167435 | |
Dominik Madarász | a9efa0f01c | |
Dominik Madarász | 213710e922 | |
Dominik Madarász | d864661e65 | |
Dominik Madarász | 9c669407fc | |
Dominik Madarász | a1d576fe8a | |
Dominik Madarász | 200d0a1e6d | |
Dominik Madarász | 00f0a672f8 | |
Dominik Madarász | 4a07e4ff4c | |
Dominik Madarász | c022b104d0 | |
Dominik Madarász | a9898527ee | |
Dominik Madarász | e302d1c865 | |
Dominik Madarász | eccaa14bda | |
Dominik Madarász | 94c49e770b | |
Dominik Madarász | 3e4814222e | |
Dominik Madarász | 410d6e5f11 | |
DavoSK | cf200e8bf5 | |
DavoSK | ea9b201a08 | |
DavoSK | c21cb39140 | |
DavoSK | 3a9196d19a | |
DavoSK | 98b9f3431e | |
Dominik Madarász | d15e7da7cc | |
DavoSK | 7356168b6f | |
DavoSK | 1631e9199b | |
Dominik Madarász | 7ed35706fc | |
DavoSK | e89cd75388 | |
DavoSK | f89b35a856 | |
Dominik Madarász | 8c288dc193 | |
Dominik Madarász | fc9997d4db | |
DavoSK | 5473ca3c46 | |
DavoSK | 698d3d2089 | |
Dominik Madarász | 78c05fd9da | |
DavoSK | f6d5c76d1b | |
Dominik Madarász | e8934ac2f3 | |
DavoSK | 755f7e7a86 | |
DavoSK | 1f451f10be | |
Dominik Madarász | 91f005b4bb | |
Dominik Madarász | 11549eb324 | |
Dominik Madarász | 65766d8748 | |
Dominik Madarász | 0760d1809d | |
Dominik Madarász | 6e6243e9df | |
Dominik Madarász | 89fea143d3 | |
Dominik Madarász | 5aa90fc5af | |
DavoSK | bdd43143f8 | |
Dominik Madarász | f35c9b8a1c | |
Dominik Madarász | 6e0e747756 | |
DavoSK | b578ceffef | |
Dominik Madarász | 3f5d999d44 | |
Dominik Madarász | 719b002989 | |
Dominik Madarász | 4d1a90d5cb | |
Dominik Madarász | 36a4a010c8 | |
Dominik Madarász | 1c68c73028 | |
Dominik Madarász | 4fd2856a25 | |
Dominik Madarász | 391106417b | |
Dominik Madarász | a31f4f6f25 | |
Dominik Madarász | 3174b8a3c3 | |
Dominik Madarász | 267a60af32 | |
Dominik Madarász | 0e614b53a5 | |
Dominik Madarász | d0edc058eb | |
Dominik Madarász | 3165d21f2b | |
Dominik Madarász | 701c15fde1 | |
Dominik Madarász | 82a8bbdaf8 | |
Dominik Madarász | 847289c6de | |
Dominik Madarász | 341040abc2 | |
Dominik Madarász | b9e29dd7ab | |
Dominik Madarász | c8b21e86b5 | |
Dominik Madarász | 31cf65ad50 | |
Dominik Madarász | ba78e5360e | |
Dominik Madarász | f24ab7dc04 | |
Dominik Madarász | d51d88002d | |
Dominik Madarász | 553afd44d0 | |
Dominik Madarász | 72005402cf | |
Dominik Madarász | d00ce4ec80 | |
Dominik Madarász | f0ccac8e0c | |
Dominik Madarász | e15cdab4ff | |
Vladyslav Hrytsenko | 4ae83ebdbb | |
Dominik Madarász | a3a75af9b5 | |
Vladyslav Hrytsenko | 4c778d24ec | |
Dominik Madarász | 5e8e760098 | |
Dominik Madarász | 7ecc5cd0d7 | |
Vladyslav Hrytsenko | 80d8620ee1 | |
Dominik Madarász | d3e1f595e5 | |
Vladyslav Hrytsenko | 8eec4ac470 | |
Dominik Madarász | ee7ff6a6c3 | |
Dominik Madarász | f99cbc8018 | |
Dominik Madarász | 3a008427f6 | |
Vladyslav Hrytsenko | 0740d0a85b | |
Dominik Madarász | 9e368527a3 | |
Dominik Madarász | 70bb456a43 | |
Dominik Madarász | 3d104313f8 | |
Dominik Madarász | e732949856 | |
Dominik Madarász | 339bb56dc7 | |
Dominik Madarász | 4cb85f069f | |
Dominik Madarász | 6385ea4461 | |
Dominik Madarász | 3f6235e8a4 | |
Dominik Madarász | 0d58d5f315 | |
Dominik Madarász | 06f408f09f | |
Dominik Madarász | 20d35ad653 | |
Dominik Madarász | 79caba208f | |
Dominik Madarász | 437aea7df5 | |
Dominik Madarász | 0f12724700 | |
Dominik Madarász | 3f30bb5079 | |
Dominik Madarász | ec6d489526 | |
Dominik Madarász | bdd774fd50 | |
Dominik Madarász | 746ec9b00d | |
Dominik Madarász | 143bf1bffa | |
Dominik Madarász | a824731a15 | |
Dominik Madarász | 93612f5462 | |
Dominik Madarász | 71dc349e4e | |
Dominik Madarász | 026a1e01c7 | |
Dominik Madarász | 2527a40231 | |
Dominik Madarász | b12c321488 | |
Dominik Madarász | f9906ca1dd | |
Dominik Madarász | fe497ae71b | |
Dominik Madarász | 2d09fd90cd | |
Dominik Madarász | 671445d4a7 | |
Dominik Madarász | 174e5a0452 | |
Dominik Madarász | 50967aa046 | |
Dominik Madarász | a7622ceeec | |
Dominik Madarász | 2040984666 | |
Dominik Madarász | 0c099af4e8 | |
Dominik Madarász | 11c3f26126 | |
Dominik Madarász | 2663b713f2 | |
Dominik Madarász | 9a6a8b360a | |
Dominik Madarász | e51d941010 | |
Dominik Madarász | 3f96594fdb | |
Dominik Madarász | 7f098734f5 | |
Dominik Madarász | 686149829e | |
Dominik Madarász | 6ae7aff24c | |
Dominik Madarász | 24e30dd90a | |
Dominik Madarász | ed5fd927ab | |
Dominik Madarász | 11929260e2 | |
Vladyslav Hrytsenko | b6cf690c25 | |
Dominik Madarász | 6a7dc92966 | |
Dominik Madarász | e718164544 | |
Dominik Madarász | 8e013c4171 | |
Vladyslav Hrytsenko | 914b72c44f | |
Vladyslav Hrytsenko | 5d7ad90e0d | |
Dominik Madarász | 86b57bd3a1 | |
Dominik Madarász | f9b00b3b12 | |
Dominik Madarász | 583535c138 | |
Dominik Madarász | 85e87b0e81 | |
Dominik Madarász | 2b9118a206 | |
Dominik Madarász | 8ae09dd00c | |
Dominik Madarász | 01afd45007 | |
Dominik Madarász | fd1ea14de5 | |
Vladyslav Hrytsenko | 8a12661689 | |
Vladyslav Hrytsenko | 645111b53c | |
Vladyslav Hrytsenko | 3fd5e282cf | |
Vladyslav Hrytsenko | 04175594d4 | |
Dominik Madarász | 0be5d87ede | |
Dominik Madarász | b8e3decc96 | |
Dominik Madarász | 7aadeed518 | |
Dominik Madarász | 0c95f1148a |
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"version": 2,
|
||||
"buildPresets": [
|
||||
{
|
||||
"name": "vs2022-debug",
|
||||
"displayName": "Visual Studio Community 2022 Release - x86_amd64 - Debug",
|
||||
"configurePreset": "vs2022",
|
||||
"configuration": "Debug"
|
||||
}
|
||||
]
|
||||
}
|
12
README.md
|
@ -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.
|
||||
|
||||
|
|
After Width: | Height: | Size: 474 B |
After Width: | Height: | Size: 24 KiB |
After Width: | Height: | Size: 361 B |
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 430 B |
After Width: | Height: | Size: 452 B |
After Width: | Height: | Size: 559 B |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 901 B |
After Width: | Height: | Size: 422 B |
After Width: | Height: | Size: 553 B |
After Width: | Height: | Size: 366 B |
After Width: | Height: | Size: 528 B |
After Width: | Height: | Size: 423 B |
After Width: | Height: | Size: 382 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 588 B |
After Width: | Height: | Size: 1.4 MiB |
After Width: | Height: | Size: 592 B |
After Width: | Height: | Size: 581 B |
After Width: | Height: | Size: 624 B |
After Width: | Height: | Size: 156 B |
BIN
art/gen/wood.png
Before Width: | Height: | Size: 254 B After Width: | Height: | Size: 278 B |
|
@ -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);
|
||||
|
|
@ -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);
|
|
@ -0,0 +1 @@
|
|||
Only modify these for eco2d game specifically!
|
|
@ -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);
|
|
@ -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);
|
||||
|
|
@ -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)
|
||||
);
|
After Width: | Height: | Size: 24 KiB |
|
@ -0,0 +1,3 @@
|
|||
@echo off
|
||||
call win\setup_cl_generic.bat amd64
|
||||
cmake --build build && build\eco2d
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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[];
|
|
@ -3,31 +3,39 @@
|
|||
#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);
|
||||
|
@ -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,10 +134,13 @@ 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
|
||||
|
@ -142,20 +153,15 @@ void game_init(const char *ip, uint16_t port, game_kind play_mode, uint32_t num_
|
|||
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) {
|
||||
|
@ -177,6 +183,8 @@ void game_init(const char *ip, uint16_t port, game_kind play_mode, uint32_t num_
|
|||
}
|
||||
}
|
||||
|
||||
game_init_ecs();
|
||||
|
||||
if (game_mode == GAMEKIND_SINGLE) {
|
||||
for (uint32_t i = 0; i < num_viewers; i++) {
|
||||
pkt_00_init_send(i);
|
||||
|
@ -189,6 +197,7 @@ int8_t game_is_networked() {
|
|||
}
|
||||
|
||||
void game_shutdown() {
|
||||
db_shutdown();
|
||||
|
||||
if (game_mode == GAMEKIND_CLIENT) {
|
||||
network_client_disconnect();
|
||||
|
@ -209,15 +218,8 @@ void game_shutdown() {
|
|||
|
||||
// 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,13 +234,14 @@ 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();
|
||||
|
@ -260,12 +263,16 @@ 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]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
|
@ -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,
|
||||
};
|
|
@ -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;
|
|
@ -1,6 +1,6 @@
|
|||
#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"
|
||||
|
||||
|
@ -12,9 +12,6 @@ typedef enum {
|
|||
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 {
|
||||
|
@ -175,7 +172,7 @@ 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);
|
||||
|
||||
|
@ -208,7 +205,7 @@ 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);
|
||||
|
@ -225,15 +222,6 @@ 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;
|
|
@ -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,7 +20,9 @@ typedef enum {
|
|||
DITEM_BUTTON,
|
||||
DITEM_SLIDER,
|
||||
DITEM_LIST,
|
||||
DITEM_TOOL,
|
||||
DITEM_COND,
|
||||
|
||||
DITEM_END,
|
||||
|
||||
DITEM_FORCE_UINT8 = UINT8_MAX
|
||||
|
@ -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,
|
||||
|
@ -71,6 +79,11 @@ typedef struct debug_item {
|
|||
void (*on_change)(float);
|
||||
} slider;
|
||||
|
||||
struct {
|
||||
uint8_t is_open;
|
||||
void (*on_draw)(void);
|
||||
} tool;
|
||||
|
||||
void (*on_click)(void);
|
||||
|
||||
uint8_t (*on_success)(void);
|
||||
|
@ -82,10 +95,13 @@ typedef struct 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[] = {
|
||||
{
|
||||
|
@ -95,7 +111,9 @@ static debug_item items[] = {
|
|||
.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 },
|
||||
}
|
||||
|
@ -131,13 +149,24 @@ 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",
|
||||
|
@ -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,
|
||||
|
@ -334,6 +378,25 @@ debug_draw_result debug_draw_list(debug_item *list, float xpos, float ypos, bool
|
|||
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;
|
||||
|
@ -347,6 +410,19 @@ 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;
|
||||
|
||||
|
@ -391,6 +467,8 @@ void debug_draw(void) {
|
|||
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) {
|
|
@ -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,7 +12,7 @@ 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);
|
||||
|
@ -22,48 +24,40 @@ ActSpawnCar(void) {
|
|||
}
|
||||
|
||||
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);
|
||||
|
@ -238,8 +232,7 @@ ActSpawnDemoNPCs(void) {
|
|||
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());
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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"
|
||||
|
@ -43,6 +43,23 @@ DrawCameraPos(debug_item *it, float xpos, float ypos) {
|
|||
return DrawFormattedText(xpos, ypos, TextFormat("%d %d", (int)(cam.x/WORLD_BLOCK_SIZE), (int)(cam.y/WORLD_BLOCK_SIZE)));
|
||||
}
|
||||
|
||||
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;
|
||||
|
@ -102,6 +119,11 @@ DrawDemoNPCCount(debug_item *it, float xpos, float ypos) {
|
|||
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
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
|
@ -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]);
|
||||
}
|
||||
}
|
|
@ -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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
||||
}
|
|
@ -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);
|
|
@ -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 });
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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));
|
||||
}
|
|
@ -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)
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "platform/system.h"
|
||||
|
||||
uint64_t storage_spawn(void);
|
||||
void storage_despawn(uint64_t id);
|
||||
|
|
@ -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);
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
#pragma once
|
||||
#include "platform/system.h"
|
||||
|
||||
uint64_t vehicle_spawn(void);
|
||||
void vehicle_despawn(uint64_t id);
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
|
@ -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})
|
|
@ -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));
|
||||
};
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
// NOTE(zaklaus): contains collection of packed images used by texgen
|
||||
// TODO(zaklaus): we will use files for now
|
|
@ -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);
|
||||
}
|
|
@ -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) {
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
#pragma once
|
||||
|
||||
void notification_push(const char* title, const char* text);
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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"
|
||||
|
|
@ -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
|
||||
};
|
|
@ -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})
|
|
@ -0,0 +1,15 @@
|
|||
#include "models/components.h"
|
||||
|
||||
|
||||
|
||||
#define X(comp) ECS_COMPONENT_DECLARE(comp);
|
||||
_COMPS
|
||||
#undef X
|
||||
|
||||
void ComponentsImport(ecs_world_t *ecs) {
|
||||
ECS_MODULE(ecs, Components);
|
||||
|
||||
#define X(comp) ECS_COMPONENT_DEFINE(ecs, comp);
|
||||
_COMPS
|
||||
#undef X
|
||||
}
|