From dda8f6b33ee05acdf23883c91a0897a464b84061 Mon Sep 17 00:00:00 2001 From: Magnus Auvinen Date: Sun, 18 Nov 2007 12:03:59 +0000 Subject: [PATCH] fixed skin selector and some other mindor stuff --- data/browse_icons.png | Bin 0 -> 473 bytes datasrc/teewars.ds | 6 + src/engine/client/client.c | 17 ++ src/engine/config.c | 2 +- src/engine/snapshot.c | 21 +++ src/game/client/cl_render.h | 23 +++ src/game/client/cl_skin.cpp | 82 ++++++++++ src/game/client/cl_skin.h | 14 ++ src/game/client/game_client.cpp | 157 ++++++------------ src/game/client/menu2.cpp | 274 ++++++++++++++++++++++++++++++-- src/game/game_variables.h | 4 +- src/game/vmath.h | 6 +- 12 files changed, 473 insertions(+), 133 deletions(-) create mode 100644 data/browse_icons.png create mode 100644 src/game/client/cl_render.h create mode 100644 src/game/client/cl_skin.cpp create mode 100644 src/game/client/cl_skin.h diff --git a/data/browse_icons.png b/data/browse_icons.png new file mode 100644 index 0000000000000000000000000000000000000000..f9ba33f8f9610260ee2676a8dba478e9311ebdb8 GIT binary patch literal 473 zcmV;~0Ve*5P)JTsHzI;a$_hb{bS3HT zsdTmE7d!@%%KU2j!3>kkgoq}osmdZ32zy~Y0Du4>a{<3j$PpNC5$)F62}FqnuOJF2FUlZ=j|Cq1S3; zj55DZfStxgmmO~o0sdjWR4aVq{7+-^%Ux(~#SYhUEae7h&oorN?@Ugg)KqQQ3+dHk z&rlE`GXZu}?sK#D?sivTm_pjROS0%VdeZNvuE_xH8xPRM`&ndG-^#u2&q_hagb>W4*# z`b+~$(slBfIb%*EIbpV~7YO1703*PB000311ON~K*a%?pS8d_hLtw-YA}A;R5#_lm P00000NkvXXu0mjf(!Irh literal 0 HcmV?d00001 diff --git a/datasrc/teewars.ds b/datasrc/teewars.ds index c0a085fde..f3534d002 100644 --- a/datasrc/teewars.ds +++ b/datasrc/teewars.ds @@ -683,6 +683,12 @@ animations { walk { body { + 0.0 0 0 0 + 0.2 0 -1 0 + 0.4 0 0 0 + 0.6 0 0 0 + 0.8 0 -1 0 + 1.0 0 0 0 } front_foot { diff --git a/src/engine/client/client.c b/src/engine/client/client.c index 19ddf9e49..ecb485825 100644 --- a/src/engine/client/client.c +++ b/src/engine/client/client.c @@ -446,6 +446,9 @@ static int client_load_data() return 1; } +extern int snapshot_data_rate[0xffff]; +extern int snapshot_data_updates[0xffff]; + static void client_debug_render() { static NETSTATS prev, current; @@ -478,6 +481,20 @@ static void client_debug_render() (int)(1.0f/frametime_avg)); gfx_quads_text(2, 2, 16, buffer); + /* render rates */ + { + int i; + for(i = 0; i < 256; i++) + { + if(snapshot_data_rate[i]) + { + sprintf(buffer, "%4d : %8d %8d %8d", i, snapshot_data_rate[i]/8, snapshot_data_updates[i], + (snapshot_data_rate[i]/snapshot_data_updates[i])/8); + gfx_quads_text(2, 100+i*8, 16, buffer); + } + } + } + /* render graphs */ gfx_mapscreen(0,0,400.0f,300.0f); graph_render(&predict_graph, 300, 10, 90, 50); diff --git a/src/engine/config.c b/src/engine/config.c index 97241e489..a4e802bfd 100644 --- a/src/engine/config.c +++ b/src/engine/config.c @@ -188,7 +188,7 @@ void config_save(const char *filename) #undef MACRO_CONFIG_INT #undef MACRO_CONFIG_STR -#define MACRO_CONFIG_INT(name,def,min,max) void config_set_ ## name (CONFIGURATION *c, int val) { if (val < min) val = min; if (max != 0 && val > max) val = max; c->name = val; } +#define MACRO_CONFIG_INT(name,def,min,max) void config_set_ ## name (CONFIGURATION *c, int val) { if(min != max) { if (val < min) val = min; if (max != 0 && val > max) val = max; } c->name = val; } #define MACRO_CONFIG_STR(name,len,def) void config_set_ ## name (CONFIGURATION *c, const char *str) { strncpy(c->name, str, len-1); c->name[sizeof(c->name)-1] = 0; } #include "config_variables.h" #undef MACRO_CONFIG_INT diff --git a/src/engine/snapshot.c b/src/engine/snapshot.c index 40bad21e5..3bd2f6dee 100644 --- a/src/engine/snapshot.c +++ b/src/engine/snapshot.c @@ -1,4 +1,5 @@ #include "snapshot.h" +#include "compression.h" int *snapitem_data(SNAPSHOT_ITEM *item) { return (int *)(item+1); } @@ -108,11 +109,25 @@ static int diff_item(int *past, int *current, int *out, int size) return needed; } +int snapshot_data_rate[0xffff] = {0}; +int snapshot_data_updates[0xffff] = {0}; +static int snapshot_current = 0; + static void undiff_item(int *past, int *diff, int *out, int size) { while(size) { *out = *past+*diff; + + if(*diff == 0) + snapshot_data_rate[snapshot_current] += 1; + else + { + unsigned char buf[16]; + unsigned char *end = vint_pack(buf, *diff); + snapshot_data_rate[snapshot_current] += (int)(end - (unsigned char*)buf) * 8; + } + out++; past++; diff++; @@ -260,6 +275,7 @@ int snapshot_unpack_delta(SNAPSHOT *from, SNAPSHOT *to, void *srcdata, int data_ itemsize = *data++; type = *data++; id = *data++; + snapshot_current = type; key = (type<<16)|id; @@ -273,9 +289,14 @@ int snapshot_unpack_delta(SNAPSHOT *from, SNAPSHOT *to, void *srcdata, int data_ { /* we got an update so we need to apply the diff */ undiff_item((int *)snapitem_data(snapshot_get_item(from, fromindex)), data, newdata, itemsize/4); + snapshot_data_updates[snapshot_current]++; } else /* no previous, just copy the data */ + { mem_copy(newdata, data, itemsize); + snapshot_data_rate[snapshot_current] += itemsize*8; + snapshot_data_updates[snapshot_current]++; + } data += itemsize/4; } diff --git a/src/game/client/cl_render.h b/src/game/client/cl_render.h new file mode 100644 index 000000000..44ae7ad4a --- /dev/null +++ b/src/game/client/cl_render.h @@ -0,0 +1,23 @@ +struct animstate +{ + keyframe body; + keyframe back_foot; + keyframe front_foot; + keyframe attach; +}; + +void anim_seq_eval(sequence *seq, float time, keyframe *frame); +void anim_eval(animation *anim, float time, animstate *state); +void anim_add_keyframe(keyframe *seq, keyframe *added, float amount); +void anim_add(animstate *state, animstate *added, float amount); +void anim_eval_add(animstate *state, animation *anim, float time, float amount); + +struct tee_render_info +{ + int texture; + vec4 color_body; + vec4 color_feet; + float size; +}; + +void render_tee(animstate *anim, tee_render_info *info, int emote, vec2 dir, vec2 pos); diff --git a/src/game/client/cl_skin.cpp b/src/game/client/cl_skin.cpp new file mode 100644 index 000000000..6e450b4fe --- /dev/null +++ b/src/game/client/cl_skin.cpp @@ -0,0 +1,82 @@ +#include +#include +#include +#include +#include "cl_skin.h" +#include "../math.h" + +enum +{ + MAX_SKINS=256, +}; + +static skin skins[MAX_SKINS] = {{-1, -1, {0}, {0}}}; +static int num_skins = 0; + +static void skinscan(const char *name, int is_dir, void *user) +{ + int l = strlen(name); + if(l < 4 || is_dir || num_skins == MAX_SKINS) + return; + if(strcmp(name+l-4, ".png") != 0) + return; + + char buf[512]; + sprintf(buf, "data/skins/%s", name); + IMAGE_INFO info; + if(!gfx_load_png(&info, buf)) + { + dbg_msg("game", "failed to load skin from %s", name); + return; + } + + skins[num_skins].org_texture = gfx_load_texture_raw(info.width, info.height, info.format, info.data); + + // create colorless version + unsigned char *d = (unsigned char *)info.data; + int step = info.format == IMG_RGBA ? 4 : 3; + + for(int i = 0; i < info.width*info.height; i++) + { + int v = (d[i*step]+d[i*step+1]+d[i*step+2])/3; + d[i*step] = v; + d[i*step+1] = v; + d[i*step+2] = v; + } + + skins[num_skins].color_texture = gfx_load_texture_raw(info.width, info.height, info.format, info.data); + mem_free(info.data); + + // set skin data + strncpy(skins[num_skins].name, name, min((int)sizeof(skins[num_skins].name),l-4)); + dbg_msg("game", "load skin %s", skins[num_skins].name); + num_skins++; +} + + +void skin_init() +{ + // load skins + fs_listdir("data/skins", skinscan, 0); +} + +int skin_num() +{ + return num_skins; +} + +const skin *skin_get(int index) +{ + return &skins[index%num_skins]; +} + +int skin_find(const char *name) +{ + for(int i = 0; i < num_skins; i++) + { + if(strcmp(skins[i].name, name) == 0) + return i; + } + return -1; +} + diff --git a/src/game/client/cl_skin.h b/src/game/client/cl_skin.h new file mode 100644 index 000000000..84dbc5f24 --- /dev/null +++ b/src/game/client/cl_skin.h @@ -0,0 +1,14 @@ + +// do this better and nicer +typedef struct +{ + int org_texture; + int color_texture; + char name[31]; + const char term[1]; +} skin; + +void skin_init(); +int skin_num(); +const skin *skin_get(int index); +int skin_find(const char *name); diff --git a/src/game/client/game_client.cpp b/src/game/client/game_client.cpp index 7d01311ef..5698fc05a 100644 --- a/src/game/client/game_client.cpp +++ b/src/game/client/game_client.cpp @@ -15,6 +15,8 @@ extern "C" { #include "mapres_tilemap.h" #include "data.h" #include "menu.h" +#include "cl_skin.h" +#include "cl_render.h" // sound channels enum @@ -24,10 +26,13 @@ enum CHN_WORLD, }; +// red team color = 54090 +// blue team color = 10998628 + + data_container *data = 0x0; int gametype = GAMETYPE_DM; -//static int skinseed = 0; static int music_menu = -1; static int music_menu_id = -1; @@ -51,29 +56,6 @@ static const obj_player_character *local_prev_character = 0; static const obj_player_info *local_info = 0; static const obj_game *gameobj = 0; -// do this better and nicer -struct skin -{ - int org_texture; - int color_texture; - char name[31]; - const char term[1]; -}; - -enum -{ - MAX_SKINS=256, -}; - -struct tee_render_info -{ - int texture; - vec4 color; -}; - -static skin skins[MAX_SKINS] = {{-1, -1, {0}, {0}}}; -static int num_skins = 0; - static struct client_data { char name[64]; @@ -541,46 +523,6 @@ static void render_loading(float percent) gfx_swap(); } -static void skinscan(const char *name, int is_dir, void *user) -{ - int l = strlen(name); - if(l < 4 || is_dir || num_skins == MAX_SKINS) - return; - if(strcmp(name+l-4, ".png") != 0) - return; - - char buf[512]; - sprintf(buf, "data/skins/%s", name); - IMAGE_INFO info; - if(!gfx_load_png(&info, buf)) - { - dbg_msg("game", "failed to load skin from %s", name); - return; - } - - skins[num_skins].org_texture = gfx_load_texture_raw(info.width, info.height, info.format, info.data); - - // create colorless version - unsigned char *d = (unsigned char *)info.data; - int step = info.format == IMG_RGBA ? 4 : 3; - - for(int i = 0; i < info.width*info.height; i++) - { - int v = (d[i*step]+d[i*step+1]+d[i*step+2])/3; - d[i*step] = v; - d[i*step+1] = v; - d[i*step+2] = v; - } - - skins[num_skins].color_texture = gfx_load_texture_raw(info.width, info.height, info.format, info.data); - mem_free(info.data); - - // set skin data - strncpy(skins[num_skins].name, name, min((int)sizeof(skins[num_skins].name),l-4)); - dbg_msg("game", "load skin %s", skins[num_skins].name); - num_skins++; -} - extern "C" void modc_init() { // init menu @@ -627,8 +569,7 @@ extern "C" void modc_init() current++; } - // load skins - fs_listdir("data/skins", skinscan, 0); + skin_init(); } extern "C" void modc_entergame() @@ -914,7 +855,7 @@ void send_info(bool start) msg_pack_start(MSG_CHANGEINFO, MSGFLAG_VITAL); msg_pack_string(config.player_name, 64); msg_pack_string(config.player_skin, 64); - msg_pack_int(config.player_color); + msg_pack_int(config.player_color_body); msg_pack_end(); client_send_msg(); } @@ -1030,7 +971,7 @@ static void render_flag(const obj_flag *prev, const obj_flag *current) gfx_quads_end(); } -static void anim_seq_eval(sequence *seq, float time, keyframe *frame) +void anim_seq_eval(sequence *seq, float time, keyframe *frame) { if(seq->num_frames == 0) { @@ -1072,17 +1013,7 @@ static void anim_seq_eval(sequence *seq, float time, keyframe *frame) } } -struct animstate -{ - keyframe body; - keyframe back_foot; - keyframe front_foot; - keyframe attach; -}; - - - -static void anim_eval(animation *anim, float time, animstate *state) +void anim_eval(animation *anim, float time, animstate *state) { anim_seq_eval(&anim->body, time, &state->body); anim_seq_eval(&anim->back_foot, time, &state->back_foot); @@ -1090,14 +1021,14 @@ static void anim_eval(animation *anim, float time, animstate *state) anim_seq_eval(&anim->attach, time, &state->attach); } -static void anim_add_keyframe(keyframe *seq, keyframe *added, float amount) +void anim_add_keyframe(keyframe *seq, keyframe *added, float amount) { seq->x += added->x*amount; seq->y += added->y*amount; seq->angle += added->angle*amount; } -static void anim_add(animstate *state, animstate *added, float amount) +void anim_add(animstate *state, animstate *added, float amount) { anim_add_keyframe(&state->body, &added->body, amount); anim_add_keyframe(&state->back_foot, &added->back_foot, amount); @@ -1105,7 +1036,7 @@ static void anim_add(animstate *state, animstate *added, float amount) anim_add_keyframe(&state->attach, &added->attach, amount); } -static void anim_eval_add(animstate *state, animation *anim, float time, float amount) +void anim_eval_add(animstate *state, animation *anim, float time, float amount) { animstate add; anim_eval(anim, time, &add); @@ -1115,7 +1046,7 @@ static void anim_eval_add(animstate *state, animation *anim, float time, float a static void render_hand(int skin_id, vec2 center_pos, vec2 dir, float angle_offset, vec2 post_rot_offset) { // for drawing hand - skin_id = skin_id%num_skins; + const skin *s = skin_get(skin_id); float basesize = 10.0f; //dir = normalize(hook_pos-pos); @@ -1137,7 +1068,7 @@ static void render_hand(int skin_id, vec2 center_pos, vec2 dir, float angle_offs hand_pos += diry * post_rot_offset.y; //gfx_texture_set(data->images[IMAGE_CHAR_DEFAULT].id); - gfx_texture_set(skins[skin_id].color_texture); + gfx_texture_set(s->color_texture); gfx_quads_begin(); // two passes @@ -1154,7 +1085,7 @@ static void render_hand(int skin_id, vec2 center_pos, vec2 dir, float angle_offs gfx_quads_end(); } -static void render_tee(animstate *anim, tee_render_info *info, int emote, vec2 dir, vec2 pos) +void render_tee(animstate *anim, tee_render_info *info, int emote, vec2 dir, vec2 pos) { vec2 direction = dir; vec2 position = pos; @@ -1162,7 +1093,6 @@ static void render_tee(animstate *anim, tee_render_info *info, int emote, vec2 d //gfx_texture_set(data->images[IMAGE_CHAR_DEFAULT].id); gfx_texture_set(info->texture); gfx_quads_begin(); - gfx_setcolor(info->color.r, info->color.g, info->color.b, info->color.a); //gfx_quads_draw(pos.x, pos.y-128, 128, 128); // first pass we draw the outline @@ -1170,18 +1100,20 @@ static void render_tee(animstate *anim, tee_render_info *info, int emote, vec2 d for(int p = 0; p < 2; p++) { int outline = p==0 ? 1 : 0; - //int shift = skin; for(int f = 0; f < 2; f++) { - float basesize = 16.0f; + float animscale = info->size * 1.0f/64.0f; + float basesize = info->size; if(f == 1) { gfx_quads_setrotation(anim->body.angle*pi*2); // draw body + gfx_setcolor(info->color_body.r, info->color_body.g, info->color_body.b, info->color_body.a); + vec2 body_pos = position + vec2(anim->body.x, anim->body.y)*animscale; select_sprite(outline?SPRITE_TEE_BODY_OUTLINE:SPRITE_TEE_BODY, 0, 0, 0); - gfx_quads_draw(position.x+anim->body.x, position.y+anim->body.y, 4*basesize, 4*basesize); + gfx_quads_draw(body_pos.x, body_pos.y, basesize, basesize); // draw eyes if(p == 1) @@ -1204,22 +1136,27 @@ static void render_tee(animstate *anim, tee_render_info *info, int emote, vec2 d select_sprite(SPRITE_TEE_EYE_NORMAL, 0, 0, 0); break; } - int h = emote == EMOTE_BLINK ? (int)(basesize/3) : (int)(basesize); - gfx_quads_draw(position.x-4+direction.x*4, position.y-8+direction.y*3, basesize*1.5f, h*1.5f); - gfx_quads_draw(position.x+4+direction.x*4, position.y-8+direction.y*3, -basesize*1.5f, h*1.5f); + + float eyescale = basesize*0.40f; + float h = emote == EMOTE_BLINK ? basesize*0.15f : eyescale; + float eyeseparation = (0.075f - 0.010f*fabs(direction.x))*basesize; + vec2 offset = vec2(direction.x*0.125f, -0.05f+direction.y*0.10f)*basesize; + gfx_quads_draw(body_pos.x-eyeseparation+offset.x, body_pos.y+offset.y, eyescale, h); + gfx_quads_draw(body_pos.x+eyeseparation+offset.x, body_pos.y+offset.y, -eyescale, h); } } // draw feet + gfx_setcolor(info->color_feet.r, info->color_feet.g, info->color_feet.b, info->color_feet.a); select_sprite(outline?SPRITE_TEE_FOOT_OUTLINE:SPRITE_TEE_FOOT, 0, 0, 0); keyframe *foot = f ? &anim->front_foot : &anim->back_foot; - float w = basesize*2.5f*1.5f; - float h = basesize*1.425f*1.5f; + float w = basesize; + float h = basesize/2; gfx_quads_setrotation(foot->angle*pi*2); - gfx_quads_draw(position.x+foot->x, position.y+foot->y, w, h); + gfx_quads_draw(position.x+foot->x*animscale, position.y+foot->y*animscale, w, h); } } @@ -1538,7 +1475,8 @@ static void render_player( { vec2 ghost_position = mix(vec2(prev_char->x, prev_char->y), vec2(player_char->x, player_char->y), client_intratick()); tee_render_info ghost = client_datas[info.clientid].skin_info; - ghost.color.a = 0.5f; + ghost.color_body.a = 0.5f; + ghost.color_feet.a = 0.5f; render_tee(&state, &ghost, player.emote, direction, ghost_position); // render ghost } @@ -1999,16 +1937,16 @@ void render_world(float center_x, float center_y, float zoom) static void next_skin() { int skin_id = 0; - for(int i = 0; i < num_skins; i++) + for(int i = 0; i < skin_num(); i++) { - if(strcmp(config.player_skin, skins[i].name) == 0) + if(strcmp(config.player_skin, skin_get(i)->name) == 0) { - skin_id = (i+1)%num_skins; + skin_id = (i+1)%skin_num(); break; } } - config_set_player_skin(&config, skins[skin_id].name); + config_set_player_skin(&config, skin_get(skin_id)->name); send_info(false); } @@ -2706,20 +2644,15 @@ extern "C" void modc_message(int msg) (void)color; strncpy(client_datas[cid].name, name, 64); strncpy(client_datas[cid].skin_name, skinname, 64); - client_datas[cid].skin_info.color = vec4(1,1,1,1); //color; + client_datas[cid].skin_info.color_body = vec4(1,1,1,1); //color; + client_datas[cid].skin_info.color_feet = vec4(1,1,1,1); //color; + client_datas[cid].skin_info.size = 64; // find new skin - client_datas[cid].skin_id = 0; - for(int i = 0; i < num_skins; i++) - { - if(strcmp(skins[i].name, client_datas[cid].skin_name) == 0) - { - client_datas[cid].skin_id = i; - break; - } - } - - client_datas[cid].skin_info.texture = skins[client_datas[cid].skin_id].org_texture; + client_datas[cid].skin_id = skin_find(client_datas[cid].skin_name); + if(client_datas[cid].skin_id < 0) + client_datas[cid].skin_id = 0; + client_datas[cid].skin_info.texture = skin_get(client_datas[cid].skin_id)->org_texture; } else if(msg == MSG_READY_TO_ENTER) { diff --git a/src/game/client/menu2.cpp b/src/game/client/menu2.cpp index 10e66f4f7..f1c0ac726 100644 --- a/src/game/client/menu2.cpp +++ b/src/game/client/menu2.cpp @@ -21,6 +21,8 @@ extern "C" { #include "mapres_tilemap.h" #include "data.h" +#include "cl_render.h" +#include "cl_skin.h" #include extern data_container *data; @@ -497,8 +499,6 @@ float ui2_do_scrollbar_v(const void *id, const RECT *rect, float current) handle.y += (rect->h-handle.h)*current; - //dbg_msg("scroll", "%f %f %f %f", handle.x,handle.y,handle.w,handle.h); - /* logic */ float ret = current; int inside = ui_mouse_inside(handle.x,handle.y,handle.w,handle.h); @@ -506,11 +506,7 @@ float ui2_do_scrollbar_v(const void *id, const RECT *rect, float current) if(ui_active_item() == id) { if(!ui_mouse_button(0)) - { - //if(inside) - // ret = 1; ui_set_active_item(0); - } float min = rect->y; float max = rect->h-handle.h; @@ -549,6 +545,62 @@ float ui2_do_scrollbar_v(const void *id, const RECT *rect, float current) return ret; } + + +float ui2_do_scrollbar_h(const void *id, const RECT *rect, float current) +{ + RECT handle; + static float offset_x; + ui2_vsplit_l(rect, 33, &handle, 0); + + handle.x += (rect->w-handle.w)*current; + + /* logic */ + float ret = current; + int inside = ui_mouse_inside(handle.x,handle.y,handle.w,handle.h); + + if(ui_active_item() == id) + { + if(!ui_mouse_button(0)) + ui_set_active_item(0); + + float min = rect->x; + float max = rect->w-handle.w; + float cur = ui_mouse_x()-offset_x; + ret = (cur-min)/max; + if(ret < 0.0f) ret = 0.0f; + if(ret > 1.0f) ret = 1.0f; + } + else if(ui_hot_item() == id) + { + if(ui_mouse_button(0)) + { + ui_set_active_item(id); + offset_x = ui_mouse_x()-handle.x; + } + } + + if(inside) + ui_set_hot_item(id); + + // render + RECT rail; + ui2_hmargin(rect, 5.0f, &rail); + ui2_draw_rect(&rail, vec4(1,1,1,0.25f), 0, 0.0f); + + RECT slider = handle; + slider.h = rail.y-slider.y; + ui2_draw_rect(&slider, vec4(1,1,1,0.25f), CORNER_T, 2.5f); + slider.y = rail.y+rail.h; + ui2_draw_rect(&slider, vec4(1,1,1,0.25f), CORNER_B, 2.5f); + + slider = handle; + ui2_margin(&slider, 5.0f, &slider); + ui2_draw_rect(&slider, vec4(1,1,1,0.25f), CORNER_ALL, 2.5f); + + return ret; +} + int ui2_do_key_reader(void *id, const RECT *rect, int key) { // process @@ -756,7 +808,7 @@ static void menu2_render_serverbrowser(RECT main_view) ui2_vsplit_r(&headers, 2, &headers, &cols[i].spacer); } } - + for(int i = 0; i < num_cols; i++) { if(cols[i].direction == 0) @@ -960,20 +1012,192 @@ static void menu2_render_serverbrowser(RECT main_view) } } + +// these converter functions were nicked from some random internet pages +static float hue_to_rgb(float v1, float v2, float h) +{ + if(h < 0) h += 1; + if(h > 1) h -= 1; + if((6 * h) < 1) return v1 + ( v2 - v1 ) * 6 * h; + if((2 * h) < 1) return v2; + if((3 * h) < 2) return v1 + ( v2 - v1 ) * ((2.0f/3.0f) - h) * 6; + return v1; +} + +vec3 hsl_to_rgb(vec3 in) +{ + float v1, v2; + vec3 out; + + if(in.s == 0) + { + out.r = in.l; + out.g = in.l; + out.b = in.l; + } + else + { + if(in.l < 0.5f) + v2 = in.l * (1 + in.s); + else + v2 = (in.l+in.s) - (in.s*in.l); + + v1 = 2 * in.l - v2; + + out.r = hue_to_rgb(v1, v2, in.h + (1.0f/3.0f)); + out.g = hue_to_rgb(v1, v2, in.h); + out.b = hue_to_rgb(v1, v2, in.h - (1.0f/3.0f)); + } + + return out; +} + +static vec4 get_color(int v) +{ + vec3 r = hsl_to_rgb(vec3((v>>16)/255.0f, ((v>>8)&0xff)/255.0f, 0.5f+(v&0xff)/255.0f*0.5f)); + return vec4(r.r, r.g, r.b, 1.0f); +} + static void menu2_render_settings_player(RECT main_view) { RECT button; + RECT skinselection; + ui2_vsplit_l(&main_view, 300.0f, &main_view, &skinselection); + + + ui2_hsplit_t(&main_view, 20.0f, &button, &main_view); + + // render settings + { + ui2_hsplit_t(&main_view, 20.0f, &button, &main_view); + ui2_do_label(&button, "Name:", 18.0, -1); + ui2_vsplit_l(&button, 80.0f, 0, &button); + ui2_vsplit_l(&button, 180.0f, &button, 0); + ui2_do_edit_box(config.player_name, &button, config.player_name, sizeof(config.player_name)); + + ui2_hsplit_t(&main_view, 20.0f, &button, &main_view); + if (ui2_do_button(&config.dynamic_camera, "Dynamic camera", config.dynamic_camera, &button, ui2_draw_checkbox, 0)) + config.dynamic_camera ^= 1; + + ui2_hsplit_t(&main_view, 20.0f, &button, &main_view); + if (ui2_do_button(&config.player_color_body, "Custom colors", config.player_use_custom_color, &button, ui2_draw_checkbox, 0)) + config.player_use_custom_color = config.player_use_custom_color?0:1; + + if(config.player_use_custom_color) + { + int *colors[2]; + colors[0] = &config.player_color_body; + colors[1] = &config.player_color_feet; + + const char *parts[] = {"Body", "Feet"}; + const char *labels[] = {"Hue", "Sat.", "Lht."}; + static int color_slider[2][3] = {{0}}; + //static float v[2][3] = {{0, 0.5f, 0.25f}, {0, 0.5f, 0.25f}}; + + for(int i = 0; i < 2; i++) + { + RECT text; + ui2_hsplit_t(&main_view, 20.0f, &text, &main_view); + ui2_vsplit_l(&text, 15.0f, 0, &text); + ui2_do_label(&text, parts[i], 18, -1); + + int prevcolor = *colors[i]; + int color = 0; + for(int s = 0; s < 3; s++) + { + RECT text; + ui2_hsplit_t(&main_view, 19.0f, &button, &main_view); + ui2_vsplit_l(&button, 30.0f, 0, &button); + ui2_vsplit_l(&button, 30.0f, &text, &button); + ui2_vsplit_r(&button, 5.0f, &button, 0); + ui2_hsplit_t(&button, 4.0f, 0, &button); + + float k = ((prevcolor>>((2-s)*8))&0xff) / 255.0f; + k = ui2_do_scrollbar_h(&color_slider[i][s], &button, k); + color <<= 8; + color += clamp((int)(k*255), 0, 255); + ui2_do_label(&text, labels[s], 20, -1); + + } + + *colors[i] = color; + ui2_hsplit_t(&main_view, 5.0f, 0, &main_view); + } + } + } + + // draw header + RECT header, footer; + ui2_hsplit_t(&skinselection, 20, &header, &skinselection); + ui2_draw_rect(&header, vec4(1,1,1,0.25f), CORNER_T, 5.0f); + ui2_do_label(&header, "Skins", 18.0f, 0); + + // draw footers + ui2_hsplit_b(&skinselection, 20, &skinselection, &footer); + ui2_draw_rect(&footer, vec4(1,1,1,0.25f), CORNER_B, 5.0f); + ui2_vsplit_l(&footer, 10.0f, 0, &footer); + + // modes + ui2_draw_rect(&skinselection, vec4(0,0,0,0.15f), 0, 0); + + RECT scroll; + ui2_vsplit_r(&skinselection, 15, &skinselection, &scroll); + + RECT list = skinselection; + ui2_hsplit_t(&list, 50, &button, &list); - ui2_hsplit_t(&main_view, 20.0f, &button, &main_view); - ui2_do_label(&button, "Name:", 18.0, -1); - ui2_vsplit_l(&button, 80.0f, 0, &button); - ui2_vsplit_l(&button, 180.0f, &button, 0); - ui2_do_edit_box(config.player_name, &button, config.player_name, sizeof(config.player_name)); - - ui2_hsplit_t(&main_view, 20.0f, &button, &main_view); - if (ui2_do_button(&config.dynamic_camera, "Dynamic camera", config.dynamic_camera, &button, ui2_draw_checkbox, 0)) - config.dynamic_camera ^= 1; + int num = (int)(skinselection.h/button.h); + static float scrollvalue = 0; + static int scrollbar = 0; + ui2_hmargin(&scroll, 5.0f, &scroll); + scrollvalue = ui2_do_scrollbar_v(&scrollbar, &scroll, scrollvalue); + int start = (int)((skin_num()-num)*scrollvalue); + if(start < 0) + start = 0; + + animstate state; + anim_eval(&data->animations[ANIM_BASE], 0, &state); + anim_eval_add(&state, &data->animations[ANIM_IDLE], 0, 1.0f); + //anim_eval_add(&state, &data->animations[ANIM_WALK], fmod(client_localtime(), 1.0f), 1.0f); + + for(int i = start; i < start+num && i < skin_num(); i++) + { + const skin *s = skin_get(i); + char buf[128]; + sprintf(buf, "%s", s->name); + int selected = 0; + if(strcmp(s->name, config.player_skin) == 0) + selected = 1; + + tee_render_info info; + info.texture = s->org_texture; + info.color_body = vec4(1,1,1,1); + info.color_feet = vec4(1,1,1,1); + if(config.player_use_custom_color) + { + info.color_body = get_color(config.player_color_body); + info.color_feet = get_color(config.player_color_feet); + info.texture = s->color_texture; + } + + info.size = ui2_scale()*50.0f; + + RECT icon; + RECT text; + ui2_vsplit_l(&button, 50.0f, &icon, &text); + + if(ui2_do_button(s, "", selected, &button, ui2_draw_list_row, 0)) + config_set_player_skin(&config, s->name); + + ui2_hsplit_t(&text, 12.0f, 0, &text); // some margin from the top + ui2_do_label(&text, buf, 24, 0); + + ui2_hsplit_t(&icon, 5.0f, 0, &icon); // some margin from the top + render_tee(&state, &info, 0, vec2(1, 0), vec2(icon.x+icon.w/2, icon.y+icon.h/2)); + + ui2_hsplit_t(&list, 50, &button, &list); + } } typedef void (*assign_func_callback)(CONFIGURATION *config, int value); @@ -1212,6 +1436,24 @@ static void menu2_render_game(RECT main_view) int menu2_render() { + /* + gfx_mapscreen(0,0,2*4/3.0f,2); + gfx_clear(gui_color.r, gui_color.g, gui_color.b); + + animstate state; + anim_eval(&data->animations[ANIM_BASE], 0, &state); + //anim_eval_add(&idlestate, &data->animations[ANIM_IDLE], 0, 1.0f); + anim_eval_add(&state, &data->animations[ANIM_WALK], fmod(client_localtime(), 1.0f), 1.0f); + + tee_render_info info; + info.texture = skin_get(1)->org_texture; + info.color = vec4(1,1,1,1); + info.size = 1.0f; //ui2_scale()*16.0f; + render_tee(&state, &info, 0, vec2(sinf(client_localtime()*3), cosf(client_localtime()*3)), vec2(1,1)); + + return 0; + */ + gfx_mapscreen(0,0,800,600); static bool first = true; diff --git a/src/game/game_variables.h b/src/game/game_variables.h index 3f779730f..e183658ea 100644 --- a/src/game/game_variables.h +++ b/src/game/game_variables.h @@ -39,7 +39,9 @@ MACRO_CONFIG_INT(dynamic_camera, 1, 0, 1) MACRO_CONFIG_INT(warmup, 0, 0, 0) MACRO_CONFIG_INT(team, -10, -1, 0) -MACRO_CONFIG_INT(player_color, -1, -1, 256) +MACRO_CONFIG_INT(player_use_custom_color, 0, 0, 1) +MACRO_CONFIG_INT(player_color_body, 65408, 0, 0) +MACRO_CONFIG_INT(player_color_feet, 65408, 0, 0) MACRO_CONFIG_STR(player_skin, 64, "default") MACRO_CONFIG_INT(dbg_new_gui, 0, 0, 1) diff --git a/src/game/vmath.h b/src/game/vmath.h index d7b502b1a..7eaed12f9 100644 --- a/src/game/vmath.h +++ b/src/game/vmath.h @@ -70,9 +70,9 @@ template class vector3_base { public: - union { T x,r; }; - union { T y,g; }; - union { T z,b; }; + union { T x,r,h; }; + union { T y,g,s; }; + union { T z,b,v,l; }; vector3_base() {} vector3_base(float nx, float ny, float nz)