wip crafting ui

efd/v1
Dominik Madarász 2022-10-18 19:37:56 +02:00
parent 7ecc5cd0d7
commit 5e8e760098
12 changed files with 202 additions and 59 deletions

View File

@ -1,3 +1,5 @@
#include "models/crafting.h"
typedef struct {
uint8_t selected_item;
bool drop_item;
@ -11,6 +13,7 @@ typedef struct {
bool swap;
uint8_t swap_from;
uint8_t swap_to;
uint16_t craft_item;
} inv_keystate;
static inv_keystate player_inv = {0};
@ -21,6 +24,100 @@ 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;
}
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(float xpos, float ypos) {
// NOTE(zaklaus): collect the list of supported recipes
// TODO(zaklaus): too lazy, draw all recipes everywhere for now
float start_xpos = xpos;
float start_ypos = ypos;
for (uint16_t i = 0; i < craft_get_num_recipes(); ++i) {
asset_id id = craft_get_recipe_asset(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;
@ -37,8 +134,10 @@ void inventory_draw_panel(entity_view *e, bool is_player, float sx, float sy){
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(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;
inv_is_inside |= inv->is_inside || inside_craft;
for (int32_t i = 0; i < inv_size; i += 1) {
{
@ -138,6 +237,7 @@ void inventory_render_held_item(bool is_player){
void inventory_reset_states(inv_keystate *ik) {
ik->drop_item = false;
ik->swap = false;
ik->craft_item = 0;
}
void inventory_draw() {
@ -164,4 +264,9 @@ void inventory_draw() {
inventory_render_held_item(true);
inventory_render_held_item(false);
// TODO(zaklaus): draw craft list
if (IsKeyPressed(KEY_O)) {
player_inv.craft_item = ASSET_SCREWS;
}
}

View File

@ -63,6 +63,7 @@ typedef struct {
uint8_t swap_storage;
uint8_t swap_from;
uint8_t swap_to;
asset_id craft_item;
// NOTE(zaklaus): build mode
uint8_t num_placements;

View File

@ -51,6 +51,15 @@ bool craft_is_reagent_used_in_producer(asset_id reagent, asset_id producer) {
return craft__find_num_recipes_by_reagent(producer, reagent) > 0;
}
uint16_t craft_get_num_recipes(void) {
return MAX_RECIPES;
}
asset_id craft_get_recipe_asset(uint16_t id) {
ZPL_ASSERT(id < MAX_RECIPES);
return recipes[id].product;
}
asset_id craft_perform_recipe(ecs_entity_t *items, asset_id producer, asset_id target, uint32_t *quantity) {
ZPL_ASSERT_NOT_NULL(items);
@ -143,12 +152,12 @@ asset_id craft_perform_recipe(ecs_entity_t *items, asset_id producer, asset_id t
return 0;
}
// TODO(zaklaus):
// TODO(zaklaus): might be removed
asset_id craft_has_byproducts(asset_id product) {
return 0xFF;
}
// TODO(zaklaus):
// TODO(zaklaus): might be removed
uint32_t craft_resolve_graph(asset_id product, uint16_t *hops, uint8_t direct_cost) {
return 0;
}

View File

@ -9,12 +9,18 @@
// TODO(zaklaus): "items" is assumed to come from ItemContainer component.
asset_id craft_perform_recipe(ecs_entity_t *items, asset_id producer, asset_id target, uint32_t *quantity);
// NOTE(zaklaus): informs us on whether this product has any byproducts desired.
asset_id craft_has_byproducts(asset_id product);
// NOTE(zaklaus): mostly used by item router so we don't push reagents out
bool craft_is_reagent_used_in_producer(asset_id reagent, asset_id producer);
// NOTE(zaklaus): utilities
uint16_t craft_get_num_recipes(void);
asset_id craft_get_recipe_asset(uint16_t id);
//~TODO(zaklaus): not implemented and might get removed
// NOTE(zaklaus): informs us on whether this product has any byproducts desired.
asset_id craft_has_byproducts(asset_id product);
// NOTE(zaklaus): resolves the production chain and analyses the amount of items required
// and a number of hops (production layers) needed to produce the item.
// optionally, it allows to calculate "direct_cost" of the product.

View File

@ -16,8 +16,6 @@ uint64_t craftbench_spawn(void) {
producer->energy_level = 69.0f;
producer->pending_task = PRODUCER_CRAFT_WAITING;
producer->push_filter = PRODUCER_PUSH_NONE;
ecs_set(world_ecs(), e, ItemRouter, {1});
return (uint64_t)e;
}

View File

@ -25,6 +25,7 @@ pkt_desc pkt_send_keystate_desc[] = {
{ PKT_UINT(pkt_send_keystate, swap_storage) },
{ PKT_UINT(pkt_send_keystate, swap_from) },
{ PKT_UINT(pkt_send_keystate, swap_to) },
{ PKT_UINT(pkt_send_keystate, craft_item) },
{ PKT_UINT(pkt_send_keystate, placement_num) },
{ PKT_UINT(pkt_send_keystate, deletion_mode) },
{ PKT_ARRAY(pkt_send_keystate, placements) },
@ -73,9 +74,9 @@ int32_t pkt_send_keystate_handler(pkt_header *header) {
i->swap_storage |= table.swap_storage;
i->swap_from = zpl_clamp(table.swap_from, 0, ITEMS_CONTAINER_SIZE-1);
i->swap_to = zpl_clamp(table.swap_to, 0, ITEMS_CONTAINER_SIZE-1);
i->craft_item = table.craft_item;
i->storage_action = table.storage_action;
i->deletion_mode = table.deletion_mode;
if (table.placement_num > 0) {
i->num_placements = zpl_clamp(table.placement_num, 0, BUILD_MAX_PLACEMENTS);
for (uint8_t j = 0; j < i->num_placements; j++) {

View File

@ -22,6 +22,7 @@ typedef struct {
uint8_t swap_storage;
uint8_t swap_from;
uint8_t swap_to;
uint16_t craft_item;
// TODO(zaklaus): build mode
uint8_t placement_num;

View File

@ -141,6 +141,7 @@ void platform_input_update_input_frame(game_keystate_data data) {
if (data.swap != last_input_data.swap) goto send_data;
if (data.swap_from != last_input_data.swap_from) goto send_data;
if (data.swap_to != last_input_data.swap_to) goto send_data;
if (data.craft_item != last_input_data.craft_item) goto send_data;
if (data.placement_num != last_input_data.placement_num) goto send_data;
if (data.deletion_mode != last_input_data.deletion_mode) goto send_data;
if (zpl_memcompare(data.placements, last_input_data.placements, zpl_size_of(data.placements))) goto send_data;

View File

@ -56,6 +56,25 @@ void PickItem(ecs_iter_t *it) {
}
}
void CraftItem(ecs_iter_t *it) {
Input *in = ecs_field(it, Input, 1);
for (int i = 0; i < it->count; i++) {
if (in[i].craft_item == 0) continue;
zpl_printf("id: %d\n", in[i].craft_item);
if (world_entity_valid(in[i].storage_ent)){
Producer *ic = 0;
if ((ic = ecs_get_mut_if_ex(it->world, in[i].storage_ent, Producer))){
ic->target_item = in[i].craft_item;
if (ic->pending_task == PRODUCER_CRAFT_WAITING) {
ic->pending_task = PRODUCER_CRAFT_ENQUEUED;
}
in[i].craft_item = 0;
}
}
}
}
void DropItem(ecs_iter_t *it) {
Input *in = ecs_field(it, Input, 1);
Position *p = ecs_field(it, Position, 2);

View File

@ -263,6 +263,7 @@ void SystemsImport(ecs_world_t *ecs) {
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, CraftItem, EcsPostUpdate, components.Input, !components.IsInVehicle);
ECS_SYSTEM(ecs, InspectContainers, EcsPostUpdate, components.Input, !components.IsInVehicle);
ECS_SYSTEM_TICKED(ecs, HarvestIntoContainers, EcsPostUpdate, components.ItemContainer, components.Position, !components.BlockHarvest);

View File

@ -108,6 +108,7 @@ void platform_input() {
.swap_storage = inv_swap_storage,
.swap_from = inv->swap_from,
.swap_to = inv->swap_to,
.craft_item = inv->craft_item,
.deletion_mode = build_is_deletion_mode,
};