editor update and other stuff

This commit is contained in:
Magnus Auvinen 2008-01-17 23:09:49 +00:00
parent 253a5639ae
commit 57c4765993
19 changed files with 2324 additions and 1112 deletions

File diff suppressed because it is too large Load diff

View file

@ -70,15 +70,6 @@ enum
PAGE_SYSTEM,
};
static void ui_draw_rect(const RECT *r, vec4 color, int corners, float rounding)
{
gfx_texture_set(-1);
gfx_quads_begin();
gfx_setcolor(color.r, color.g, color.b, color.a);
draw_round_rect_ext(r->x,r->y,r->w,r->h,rounding*ui_scale(), corners);
gfx_quads_end();
}
static void ui_draw_browse_icon(int what, const RECT *r)
{
gfx_texture_set(data->images[IMAGE_BROWSEICONS].id);

View file

@ -1,16 +1,5 @@
/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
#ifndef __MENU_H
#define __MENU_H
/*
void draw_image_button(void *id, const char *text, int checked, float x, float y, float w, float h, void *extra);
void draw_single_part_button(void *id, const char *text, int checked, float x, float y, float w, float h, void *extra);
void draw_menu_button(void *id, const char *text, int checked, float x, float y, float w, float h, void *extra);
void draw_teewars_button(void *id, const char *text, int checked, float x, float y, float w, float h, void *extra);
int ui_do_key_reader(void *id, float x, float y, float w, float h, int key);
int ui_do_combo_box(void *id, float x, float y, float w, char *lines, int line_count, int selected_index);
int ui_do_edit_box(void *id, float x, float y, float w, float h, char *str, int str_size);
int ui_do_check_box(void *id, float x, float y, float w, float h, int value);
int do_scroll_bar_horiz(void *id, float x, float y, float width, int steps, int last_index);
int do_scroll_bar_vert(void *id, float x, float y, float height, int steps, int last_index);
*/
#endif

View file

@ -125,6 +125,15 @@ void draw_round_rect(float x, float y, float w, float h, float r)
draw_round_rect_ext(x,y,w,h,r,0xf);
}
void ui_draw_rect(const RECT *r, vec4 color, int corners, float rounding)
{
gfx_texture_set(-1);
gfx_quads_begin();
gfx_setcolor(color.r, color.g, color.b, color.a);
draw_round_rect_ext(r->x,r->y,r->w,r->h,rounding*ui_scale(), corners);
gfx_quads_end();
}
void render_tee(animstate *anim, tee_render_info *info, int emote, vec2 dir, vec2 pos)
{
vec2 direction = dir;
@ -246,6 +255,14 @@ static void mapscreen_to_group(float center_x, float center_y, MAPITEM_GROUP *gr
gfx_mapscreen(points[0], points[1], points[2], points[3]);
}
static void envelope_eval(float time_offset, int env, float *channels)
{
channels[0] = 0;
channels[1] = 0;
channels[2] = 0;
channels[3] = 0;
}
void render_layers(float center_x, float center_y, int pass)
{
bool passed_gamelayer = false;
@ -299,7 +316,7 @@ void render_layers(float center_x, float center_y, int pass)
else
gfx_texture_set(img_get(qlayer->image));
QUAD *quads = (QUAD *)map_get_data_swapped(qlayer->data);
render_quads(quads, qlayer->num_quads);
render_quads(quads, qlayer->num_quads, envelope_eval);
}
}
}

View file

@ -4,6 +4,7 @@
#include "../g_vmath.h"
#include "../g_mapitems.h"
#include "gc_ui.h"
struct tee_render_info
{
@ -30,6 +31,7 @@ void draw_sprite(float x, float y, float size);
// rects
void draw_round_rect(float x, float y, float w, float h, float r);
void draw_round_rect_ext(float x, float y, float w, float h, float r, int corners);
void ui_draw_rect(const RECT *r, vec4 color, int corners, float rounding);
// larger rendering methods
void menu_render();
@ -49,7 +51,8 @@ void render_player(
const struct obj_player_info *prev_info, const struct obj_player_info *player_info);
// map render methods (gc_render_map.cpp)
void render_quads(QUAD *quads, int num_quads);
void render_eval_envelope(ENVPOINT *points, int num_points, int channels, float time, float *result);
void render_quads(QUAD *quads, int num_quads, void (*eval)(float time_offset, int env, float *channels));
void render_tilemap(TILE *tiles, int w, int h, float scale, int flags);
// helpers

View file

@ -3,6 +3,70 @@
#include "../g_math.h"
#include "gc_client.h"
void render_eval_envelope(ENVPOINT *points, int num_points, int channels, float time, float *result)
{
if(num_points == 0)
{
result[0] = 0;
result[1] = 0;
result[2] = 0;
result[3] = 0;
return;
}
if(num_points == 1)
{
result[0] = fx2f(points[0].values[0]);
result[1] = fx2f(points[0].values[1]);
result[2] = fx2f(points[0].values[2]);
result[3] = fx2f(points[0].values[3]);
return;
}
time = fmod(time, points[num_points-1].time/1000.0f)*1000.0f;
for(int i = 0; i < num_points-1; i++)
{
if(time >= points[i].time && time <= points[i+1].time)
{
float delta = points[i+1].time-points[i].time;
float a = (time-points[i].time)/delta;
if(points[i].curvetype == CURVETYPE_SMOOTH)
a = -2*a*a*a + 3*a*a; // second hermite basis
else if(points[i].curvetype == CURVETYPE_SLOW)
a = a*a*a;
else if(points[i].curvetype == CURVETYPE_FAST)
{
a = 1-a;
a = 1-a*a*a;
}
else if (points[i].curvetype == CURVETYPE_STEP)
a = 0;
else
{
// linear
}
for(int c = 0; c < channels; c++)
{
float v0 = fx2f(points[i].values[c]);
float v1 = fx2f(points[i+1].values[c]);
result[c] = v0 + (v1-v0) * a;
}
return;
}
}
result[0] = fx2f(points[num_points-1].values[0]);
result[1] = fx2f(points[num_points-1].values[1]);
result[2] = fx2f(points[num_points-1].values[2]);
result[3] = fx2f(points[num_points-1].values[3]);
return;
}
static void rotate(POINT *center, POINT *point, float rotation)
{
int x = point->x - center->x;
@ -11,7 +75,7 @@ static void rotate(POINT *center, POINT *point, float rotation)
point->y = (int)(x * sinf(rotation) + y * cosf(rotation) + center->y);
}
void render_quads(QUAD *quads, int num_quads)
void render_quads(QUAD *quads, int num_quads, void (*eval)(float time_offset, int env, float *channels))
{
gfx_quads_begin();
float conv = 1/255.0f;
@ -31,29 +95,25 @@ void render_quads(QUAD *quads, int num_quads)
float offset_y = 0;
float rot = 0;
/*
// TODO: fix this
if(editor.animate)
if(q->pos_env >= 0)
{
if(q->pos_env >= 0 && q->pos_env < editor.map.envelopes.len())
{
ENVELOPE *e = editor.map.envelopes[q->pos_env];
float t = editor.animate_time+q->pos_env_offset/1000.0f;
offset_x = e->eval(t, 0);
offset_y = e->eval(t, 1);
rot = e->eval(t, 2);
}
if(q->color_env >= 0 && q->color_env < editor.map.envelopes.len())
{
ENVELOPE *e = editor.map.envelopes[q->color_env];
float t = editor.animate_time+q->color_env_offset/1000.0f;
r = e->eval(t, 0);
g = e->eval(t, 1);
b = e->eval(t, 2);
a = e->eval(t, 3);
}
}*/
float channels[4];
eval(q->pos_env_offset/1000.0f, q->pos_env, channels);
offset_x = channels[0];
offset_y = channels[1];
rot = channels[2];
}
if(q->color_env >= 0)
{
float channels[4];
eval(q->color_env_offset/1000.0f, q->color_env, channels);
r = channels[0];
g = channels[1];
b = channels[2];
a = channels[3];
}
gfx_setcolorvertex(0, q->colors[0].r*conv*r, q->colors[0].g*conv*g, q->colors[0].b*conv*b, q->colors[0].a*conv*a);
gfx_setcolorvertex(1, q->colors[1].r*conv*r, q->colors[1].g*conv*g, q->colors[1].b*conv*b, q->colors[1].a*conv*a);

File diff suppressed because it is too large Load diff

View file

@ -4,6 +4,7 @@
#include <math.h>
#include "array.h"
#include "../g_mapitems.h"
#include "../client/gc_render.h"
extern "C" {
#include <engine/e_system.h>
@ -32,30 +33,12 @@ enum
DIALOG_FILE,
};
typedef struct // as in file
typedef struct
{
POINT position;
int type;
} ENTITY;
enum
{
CURVETYPE_STEP=0,
CURVETYPE_LINEAR,
CURVETYPE_SLOW,
CURVETYPE_FAST,
CURVETYPE_SMOOTH,
NUM_CURVETYPES,
};
typedef struct // as in file
{
int time; // in ms
int curvetype;
int values[4]; // 1-4 depending on envelope (22.10 fixed point)
} ENVPOINT;
class ENVELOPE
{
public:
@ -86,10 +69,10 @@ public:
void resort()
{
qsort(points.getptr(), points.len(), sizeof(ENVPOINT), sort_comp);
find_top_bottom();
find_top_bottom(0xf);
}
void find_top_bottom()
void find_top_bottom(int channelmask)
{
top = -1000000000.0f;
bottom = 1000000000.0f;
@ -97,54 +80,20 @@ public:
{
for(int c = 0; c < channels; c++)
{
float v = fx2f(points[i].values[c]);
if(v > top) top = v;
if(v < bottom) bottom = v;
if(channelmask&(1<<c))
{
float v = fx2f(points[i].values[c]);
if(v > top) top = v;
if(v < bottom) bottom = v;
}
}
}
}
float eval(float time, int channel)
int eval(float time, float *result)
{
if(channel >= channels)
return 0;
if(points.len() == 0)
return 0;
if(points.len() == 1)
return points[0].values[channel];
time = fmod(time, end_time())*1000.0f;
for(int i = 0; i < points.len() - 1; i++)
{
if(time >= points[i].time && time <= points[i+1].time)
{
float delta = points[i+1].time-points[i].time;
float a = (time-points[i].time)/delta;
float v0 = fx2f(points[i].values[channel]);
float v1 = fx2f(points[i+1].values[channel]);
if(points[i].curvetype == CURVETYPE_SMOOTH)
a = -2*a*a*a + 3*a*a; // second hermite basis
else if(points[i].curvetype == CURVETYPE_SLOW)
a = a*a*a;
else if(points[i].curvetype == CURVETYPE_FAST)
{
a = 1-a;
a = 1-a*a*a;
}
else if (points[i].curvetype == CURVETYPE_STEP)
a = 0;
else
{
// linear
}
return v0 + (v1-v0) * a;
}
}
return points[points.len()-1].values[channel];
render_eval_envelope(points.getptr(), points.len(), channels, time, result);
return channels;
}
void add_point(int time, int v0, int v1=0, int v2=0, int v3=0)
@ -310,12 +259,6 @@ enum
PROPTYPE_COLOR,
PROPTYPE_IMAGE,
PROPTYPE_ENVELOPE,
PROPS_NONE=0,
PROPS_GROUP,
PROPS_LAYER,
PROPS_QUAD,
PROPS_QUAD_POINT,
};
class EDITOR
@ -347,8 +290,6 @@ public:
animate_start = 0;
animate_time = 0;
props = PROPS_NONE;
show_envelope_editor = 0;
}
@ -362,6 +303,7 @@ public:
void reset(bool create_default=true);
int save(const char *filename);
int load(const char *filename);
void render();
QUAD *get_selected_quad();
LAYER *get_selected_layer_type(int index, int type);
@ -395,10 +337,14 @@ public:
int64 animate_start;
float animate_time;
int props;
int show_envelope_editor;
int selected_layer;
int selected_group;
int selected_quad;
int selected_points;
int selected_envelope;
MAP map;
};
@ -468,7 +414,6 @@ public:
array<QUAD> quads;
};
class LAYER_GAME : public LAYER_TILES
{
public:
@ -481,3 +426,14 @@ public:
int do_editor_button(const void *id, const char *text, int checked, const RECT *r, ui_draw_button_func draw_func, int flags, const char *tooltip);
void draw_editor_button(const void *id, const char *text, int checked, const RECT *r, const void *extra);
void draw_editor_button_menuitem(const void *id, const char *text, int checked, const RECT *r, const void *extra);
void ui_invoke_popup_menu(void *id, int flags, float x, float y, float w, float h, int (*func)(RECT rect), void *extra=0);
void ui_do_popup_menu();
int popup_group(RECT view);
int popup_layer(RECT view);
int popup_quad(RECT view);
int popup_point(RECT view);
void popup_select_image_invoke(int current, float x, float y);
int popup_select_image_result();

471
src/game/editor/ed_io.cpp Normal file
View file

@ -0,0 +1,471 @@
#include "ed_editor.hpp"
template<typename T>
static int make_version(int i, const T &v)
{ return (i<<16)+sizeof(T); }
// backwards compatiblity
void editor_load_old(DATAFILE *df)
{
class mapres_image
{
public:
int width;
int height;
int image_data;
};
struct mapres_tilemap
{
int image;
int width;
int height;
int x, y;
int scale;
int data;
int main;
};
struct mapres_entity
{
int x, y;
int data[1];
};
struct mapres_spawnpoint
{
int x, y;
};
struct mapres_item
{
int x, y;
int type;
};
struct mapres_flagstand
{
int x, y;
};
enum
{
MAPRES_ENTS_START=1,
MAPRES_SPAWNPOINT=1,
MAPRES_ITEM=2,
MAPRES_SPAWNPOINT_RED=3,
MAPRES_SPAWNPOINT_BLUE=4,
MAPRES_FLAGSTAND_RED=5,
MAPRES_FLAGSTAND_BLUE=6,
MAPRES_ENTS_END,
ITEM_NULL=0,
ITEM_WEAPON_GUN=0x00010001,
ITEM_WEAPON_SHOTGUN=0x00010002,
ITEM_WEAPON_ROCKET=0x00010003,
ITEM_WEAPON_SNIPER=0x00010004,
ITEM_WEAPON_HAMMER=0x00010005,
ITEM_HEALTH =0x00020001,
ITEM_ARMOR=0x00030001,
ITEM_NINJA=0x00040001,
};
enum
{
MAPRES_REGISTERED=0x8000,
MAPRES_IMAGE=0x8001,
MAPRES_TILEMAP=0x8002,
MAPRES_COLLISIONMAP=0x8003,
MAPRES_TEMP_THEME=0x8fff,
};
// load tilemaps
int game_width = 0;
int game_height = 0;
{
int start, num;
datafile_get_type(df, MAPRES_TILEMAP, &start, &num);
for(int t = 0; t < num; t++)
{
mapres_tilemap *tmap = (mapres_tilemap *)datafile_get_item(df, start+t,0,0);
LAYER_TILES *l = new LAYER_TILES(tmap->width, tmap->height);
if(tmap->main)
{
// move game layer to correct position
for(int i = 0; i < editor.map.groups[0]->layers.len()-1; i++)
{
if(editor.map.groups[0]->layers[i] == editor.game_layer)
editor.map.groups[0]->swap_layers(i, i+1);
}
game_width = tmap->width;
game_height = tmap->height;
}
// add new layer
editor.map.groups[0]->add_layer(l);
// process the data
unsigned char *src_data = (unsigned char *)datafile_get_data(df, tmap->data);
TILE *dst_data = l->tiles;
for(int y = 0; y < tmap->height; y++)
for(int x = 0; x < tmap->width; x++, dst_data++, src_data+=2)
{
dst_data->index = src_data[0];
dst_data->flags = src_data[1];
}
l->image = tmap->image;
}
}
// load images
{
int start, count;
datafile_get_type(df, MAPRES_IMAGE, &start, &count);
for(int i = 0; i < count; i++)
{
mapres_image *imgres = (mapres_image *)datafile_get_item(df, start+i, 0, 0);
void *data = datafile_get_data(df, imgres->image_data);
IMAGE *img = new IMAGE;
img->width = imgres->width;
img->height = imgres->height;
img->format = IMG_RGBA;
// copy image data
img->data = mem_alloc(img->width*img->height*4, 1);
mem_copy(img->data, data, img->width*img->height*4);
img->tex_id = gfx_load_texture_raw(img->width, img->height, img->format, img->data, IMG_AUTO);
editor.map.images.add(img);
// unload image
datafile_unload_data(df, imgres->image_data);
}
}
// load entities
{
LAYER_GAME *g = editor.game_layer;
g->resize(game_width, game_height);
for(int t = MAPRES_ENTS_START; t < MAPRES_ENTS_END; t++)
{
// fetch entities of this class
int start, num;
datafile_get_type(df, t, &start, &num);
for(int i = 0; i < num; i++)
{
mapres_entity *e = (mapres_entity *)datafile_get_item(df, start+i,0,0);
int x = e->x/32;
int y = e->y/32;
int id = -1;
if(t == MAPRES_SPAWNPOINT) id = ENTITY_SPAWN;
else if(t == MAPRES_SPAWNPOINT_RED) id = ENTITY_SPAWN_RED;
else if(t == MAPRES_SPAWNPOINT_BLUE) id = ENTITY_SPAWN_BLUE;
else if(t == MAPRES_FLAGSTAND_RED) id = ENTITY_FLAGSTAND_RED;
else if(t == MAPRES_FLAGSTAND_BLUE) id = ENTITY_FLAGSTAND_BLUE;
else if(t == MAPRES_ITEM)
{
if(e->data[0] == ITEM_WEAPON_SHOTGUN) id = ENTITY_WEAPON_SHOTGUN;
else if(e->data[0] == ITEM_WEAPON_ROCKET) id = ENTITY_WEAPON_ROCKET;
else if(e->data[0] == ITEM_NINJA) id = ENTITY_POWERUP_NINJA;
else if(e->data[0] == ITEM_ARMOR) id = ENTITY_ARMOR_1;
else if(e->data[0] == ITEM_HEALTH) id = ENTITY_HEALTH_1;
}
if(id > 0 && x >= 0 && x < g->width && y >= 0 && y < g->height)
g->tiles[y*g->width+x].index = id+ENTITY_OFFSET;
}
}
}
}
int EDITOR::save(const char *filename)
{
dbg_msg("editor", "saving to '%s'...", filename);
DATAFILE_OUT *df = datafile_create(filename);
if(!df)
{
dbg_msg("editor", "failed to open file '%s'...", filename);
return 0;
}
// save version
{
MAPITEM_VERSION item;
item.version = 1;
datafile_add_item(df, MAPITEMTYPE_VERSION, 0, sizeof(item), &item);
}
// save images
for(int i = 0; i < map.images.len(); i++)
{
IMAGE *img = map.images[i];
MAPITEM_IMAGE item;
item.version = 1;
item.width = img->width;
item.height = img->height;
item.external = 0;
item.image_name = -1;
item.image_data = datafile_add_data(df, item.width*item.height*4, img->data);
datafile_add_item(df, MAPITEMTYPE_IMAGE, i, sizeof(item), &item);
}
// save layers
int layer_count = 0;
for(int g = 0; g < map.groups.len(); g++)
{
LAYERGROUP *group = map.groups[g];
MAPITEM_GROUP gitem;
gitem.version = 1;
gitem.parallax_x = group->parallax_x;
gitem.parallax_y = group->parallax_y;
gitem.offset_x = group->offset_x;
gitem.offset_y = group->offset_y;
gitem.start_layer = layer_count;
gitem.num_layers = 0;
for(int l = 0; l < group->layers.len(); l++)
{
if(group->layers[l]->type == LAYERTYPE_TILES)
{
dbg_msg("editor", "saving tiles layer");
LAYER_TILES *layer = (LAYER_TILES *)group->layers[l];
MAPITEM_LAYER_TILEMAP item;
item.version = 2;
item.layer.flags = 0;
item.layer.type = layer->type;
item.color.r = 255; // not in use right now
item.color.g = 255;
item.color.b = 255;
item.color.a = 255;
item.color_env = -1;
item.color_env_offset = 0;
item.width = layer->width;
item.height = layer->height;
item.flags = layer->game;
item.image = layer->image;
item.data = datafile_add_data(df, layer->width*layer->height*sizeof(TILE), layer->tiles);
datafile_add_item(df, MAPITEMTYPE_LAYER, layer_count, sizeof(item), &item);
gitem.num_layers++;
layer_count++;
}
else if(group->layers[l]->type == LAYERTYPE_QUADS)
{
dbg_msg("editor", "saving quads layer");
LAYER_QUADS *layer = (LAYER_QUADS *)group->layers[l];
if(layer->quads.len())
{
MAPITEM_LAYER_QUADS item;
item.version = 1;
item.layer.flags = 0;
item.layer.type = layer->type;
item.image = layer->image;
// add the data
item.num_quads = layer->quads.len();
item.data = datafile_add_data_swapped(df, layer->quads.len()*sizeof(QUAD), layer->quads.getptr());
datafile_add_item(df, MAPITEMTYPE_LAYER, layer_count, sizeof(item), &item);
// clean up
//mem_free(quads);
gitem.num_layers++;
layer_count++;
}
}
}
datafile_add_item(df, MAPITEMTYPE_GROUP, g, sizeof(gitem), &gitem);
}
// save envelopes
int point_count = 0;
for(int e = 0; e < map.envelopes.len(); e++)
{
MAPITEM_ENVELOPE item;
item.version = 1;
item.channels = map.envelopes[e]->channels;
item.start_point = point_count;
item.num_points = map.envelopes[e]->points.len();
item.name = -1;
datafile_add_item(df, MAPITEMTYPE_ENVELOPE, e, sizeof(item), &item);
point_count += item.num_points;
}
// save points
int totalsize = sizeof(ENVPOINT) * point_count;
ENVPOINT *points = (ENVPOINT *)mem_alloc(totalsize, 1);
point_count = 0;
for(int e = 0; e < map.envelopes.len(); e++)
{
int count = map.envelopes[e]->points.len();
mem_copy(&points[point_count], map.envelopes[e]->points.getptr(), sizeof(ENVPOINT)*count);
point_count += count;
}
datafile_add_item(df, MAPITEMTYPE_ENVPOINTS, 0, totalsize, points);
// finish the data file
datafile_finish(df);
dbg_msg("editor", "done");
return 1;
}
int EDITOR::load(const char *filename)
{
DATAFILE *df = datafile_load(filename);
if(!df)
return 0;
// check version
MAPITEM_VERSION *item = (MAPITEM_VERSION *)datafile_find_item(df, MAPITEMTYPE_VERSION, 0);
if(!item)
{
// import old map
editor.reset();
editor_load_old(df);
}
else if(item->version == 1)
{
editor.reset(false);
// load images
{
int start, num;
datafile_get_type(df, MAPITEMTYPE_IMAGE, &start, &num);
for(int i = 0; i < num; i++)
{
MAPITEM_IMAGE *item = (MAPITEM_IMAGE *)datafile_get_item(df, start+i, 0, 0);
void *data = datafile_get_data(df, item->image_data);
IMAGE *img = new IMAGE;
img->width = item->width;
img->height = item->height;
img->format = IMG_RGBA;
// copy image data
img->data = mem_alloc(img->width*img->height*4, 1);
mem_copy(img->data, data, img->width*img->height*4);
img->tex_id = gfx_load_texture_raw(img->width, img->height, img->format, img->data, IMG_AUTO);
editor.map.images.add(img);
// unload image
datafile_unload_data(df, item->image_data);
}
}
// load groups
{
int layers_start, layers_num;
datafile_get_type(df, MAPITEMTYPE_LAYER, &layers_start, &layers_num);
int start, num;
datafile_get_type(df, MAPITEMTYPE_GROUP, &start, &num);
for(int g = 0; g < num; g++)
{
MAPITEM_GROUP *gitem = (MAPITEM_GROUP *)datafile_get_item(df, start+g, 0, 0);
LAYERGROUP *group = map.new_group();
group->parallax_x = gitem->parallax_x;
group->parallax_y = gitem->parallax_y;
group->offset_x = gitem->offset_x;
group->offset_y = gitem->offset_y;
for(int l = 0; l < gitem->num_layers; l++)
{
MAPITEM_LAYER *layer_item = (MAPITEM_LAYER *)datafile_get_item(df, layers_start+gitem->start_layer+l, 0, 0);
if(!layer_item)
continue;
if(layer_item->type == LAYERTYPE_TILES)
{
MAPITEM_LAYER_TILEMAP *tilemap_item = (MAPITEM_LAYER_TILEMAP *)layer_item;
LAYER_TILES *tiles = 0;
if(tilemap_item->flags&1)
{
tiles = new LAYER_GAME(tilemap_item->width, tilemap_item->height);
editor.make_game_layer(tiles);
make_game_group(group);
}
else
tiles = new LAYER_TILES(tilemap_item->width, tilemap_item->height);
group->add_layer(tiles);
void *data = datafile_get_data(df, tilemap_item->data);
tiles->image = tilemap_item->image;
tiles->game = tilemap_item->flags&1;
mem_copy(tiles->tiles, data, tiles->width*tiles->height*sizeof(TILE));
if(tiles->game && tilemap_item->version == make_version(1, *tilemap_item))
{
for(int i = 0; i < tiles->width*tiles->height; i++)
{
if(tiles->tiles[i].index)
tiles->tiles[i].index += ENTITY_OFFSET;
}
}
datafile_unload_data(df, tilemap_item->data);
}
else if(layer_item->type == LAYERTYPE_QUADS)
{
MAPITEM_LAYER_QUADS *quads_item = (MAPITEM_LAYER_QUADS *)layer_item;
LAYER_QUADS *layer = new LAYER_QUADS;
layer->image = quads_item->image;
if(layer->image < -1 || layer->image >= map.images.len())
layer->image = -1;
void *data = datafile_get_data_swapped(df, quads_item->data);
group->add_layer(layer);
layer->quads.setsize(quads_item->num_quads);
mem_copy(layer->quads.getptr(), data, sizeof(QUAD)*quads_item->num_quads);
datafile_unload_data(df, quads_item->data);
}
}
}
}
// load envelopes
{
ENVPOINT *points = 0;
{
int start, num;
datafile_get_type(df, MAPITEMTYPE_ENVPOINTS, &start, &num);
if(num)
points = (ENVPOINT *)datafile_get_item(df, start, 0, 0);
}
int start, num;
datafile_get_type(df, MAPITEMTYPE_ENVELOPE, &start, &num);
for(int e = 0; e < num; e++)
{
MAPITEM_ENVELOPE *item = (MAPITEM_ENVELOPE *)datafile_get_item(df, start+e, 0, 0);
ENVELOPE *env = new ENVELOPE(item->channels);
env->points.setsize(item->num_points);
mem_copy(env->points.getptr(), &points[item->start_point], sizeof(ENVPOINT)*item->num_points);
map.envelopes.add(env);
}
}
}
datafile_unload(df);
return 0;
}

View file

@ -14,13 +14,20 @@ LAYER_QUADS::~LAYER_QUADS()
{
}
static void envelope_eval(float time_offset, int env, float *channels)
{
ENVELOPE *e = editor.map.envelopes[env];
float t = editor.animate_time+time_offset;
e->eval(t, channels);
}
void LAYER_QUADS::render()
{
gfx_texture_set(-1);
if(image >= 0 && image < editor.map.images.len())
gfx_texture_set(editor.map.images[image]->tex_id);
render_quads(quads.getptr(), quads.len());
render_quads(quads.getptr(), quads.len(), envelope_eval);
}
QUAD *LAYER_QUADS::new_quad()
@ -160,123 +167,29 @@ extern int selected_points;
int LAYER_QUADS::render_properties(RECT *toolbox)
{
// layer props
if(editor.props == PROPS_LAYER)
enum
{
enum
{
PROP_IMAGE=0,
NUM_PROPS,
};
PROPERTY props[] = {
{"Image", image, PROPTYPE_IMAGE, -1, 0},
{0},
};
static int ids[NUM_PROPS] = {0};
int new_val = 0;
int prop = editor.do_properties(toolbox, props, ids, &new_val);
if(prop == PROP_IMAGE)
{
if(new_val >= 0)
image = new_val%editor.map.images.len();
else
image = -1;
}
PROP_IMAGE=0,
NUM_PROPS,
};
PROPERTY props[] = {
{"Image", image, PROPTYPE_IMAGE, -1, 0},
{0},
};
static int ids[NUM_PROPS] = {0};
int new_val = 0;
int prop = editor.do_properties(toolbox, props, ids, &new_val);
if(prop == PROP_IMAGE)
{
if(new_val >= 0)
image = new_val%editor.map.images.len();
else
image = -1;
}
// quad props
QUAD *quad = editor.get_selected_quad();
if(editor.props == PROPS_QUAD)
{
if(quad)
{
RECT slot;
ui_hsplit_t(toolbox, 15.0f, &slot, toolbox);
ui_do_label(&slot, "Quad Props", 12.0f, -1, -1);
enum
{
PROP_POS_ENV=0,
PROP_POS_ENV_OFFSET,
PROP_COLOR_ENV,
PROP_COLOR_ENV_OFFSET,
NUM_PROPS,
};
PROPERTY props[] = {
{"Pos. Env", quad->pos_env, PROPTYPE_INT_STEP, -1, editor.map.envelopes.len()},
{"Pos. TO", quad->pos_env_offset, PROPTYPE_INT_SCROLL, -1000000, 1000000},
{"Color Env", quad->color_env, PROPTYPE_INT_STEP, -1, editor.map.envelopes.len()},
{"Color TO", quad->color_env_offset, PROPTYPE_INT_SCROLL, -1000000, 1000000},
{0},
};
static int ids[NUM_PROPS] = {0};
int new_val = 0;
int prop = editor.do_properties(toolbox, props, ids, &new_val);
if(prop == PROP_POS_ENV) quad->pos_env = new_val;
if(prop == PROP_POS_ENV_OFFSET) quad->pos_env_offset = new_val;
if(prop == PROP_COLOR_ENV) quad->color_env = new_val;
if(prop == PROP_COLOR_ENV_OFFSET) quad->color_env_offset = new_val;
}
}
// point props
if(editor.props == PROPS_QUAD_POINT && quad && selected_points)
{
RECT slot;
ui_hsplit_t(toolbox, 15.0f, &slot, toolbox);
ui_do_label(&slot, "Point Props", 14.0f, -1, -1);
enum
{
PROP_COLOR=0,
NUM_PROPS,
};
int color = 0;
for(int v = 0; v < 4; v++)
{
if(selected_points&(1<<v))
{
color = 0;
color |= quad->colors[v].r<<24;
color |= quad->colors[v].g<<16;
color |= quad->colors[v].b<<8;
color |= quad->colors[v].a;
}
}
PROPERTY props[] = {
{"Color", color, PROPTYPE_COLOR, -1, editor.map.envelopes.len()},
{0},
};
static int ids[NUM_PROPS] = {0};
int new_val = 0;
int prop = editor.do_properties(toolbox, props, ids, &new_val);
if(prop == PROP_COLOR)
{
for(int v = 0; v < 4; v++)
{
if(selected_points&(1<<v))
{
color = 0;
quad->colors[v].r = (new_val>>24)&0xff;
quad->colors[v].g = (new_val>>16)&0xff;
quad->colors[v].b = (new_val>>8)&0xff;
quad->colors[v].a = new_val&0xff;
}
}
}
}
return 0;
}

View file

@ -214,7 +214,7 @@ int LAYER_TILES::render_properties(RECT *toolbox)
};
PROPERTY props[] = {
{"Image", image, PROPTYPE_INT_STEP, 0, 0},
{"Image", image, PROPTYPE_IMAGE, 0, 0},
{"Width", width, PROPTYPE_INT_STEP, 1, 1000000000},
{"Height", height, PROPTYPE_INT_STEP, 1, 1000000000},
{0},

View file

@ -0,0 +1,385 @@
#include <stdio.h>
#include "ed_editor.hpp"
// popup menu handling
static struct
{
RECT rect;
void *id;
int (*func)(RECT rect);
int is_menu;
void *extra;
} ui_popups[8];
static int ui_num_popups = 0;
void ui_invoke_popup_menu(void *id, int flags, float x, float y, float w, float h, int (*func)(RECT rect), void *extra)
{
dbg_msg("", "invoked");
ui_popups[ui_num_popups].id = id;
ui_popups[ui_num_popups].is_menu = flags;
ui_popups[ui_num_popups].rect.x = x;
ui_popups[ui_num_popups].rect.y = y;
ui_popups[ui_num_popups].rect.w = w;
ui_popups[ui_num_popups].rect.h = h;
ui_popups[ui_num_popups].func = func;
ui_popups[ui_num_popups].extra = extra;
ui_num_popups++;
}
void ui_do_popup_menu()
{
for(int i = 0; i < ui_num_popups; i++)
{
bool inside = ui_mouse_inside(&ui_popups[i].rect);
ui_set_hot_item(&ui_popups[i].id);
if(ui_active_item() == &ui_popups[i].id)
{
if(!ui_mouse_button(0))
{
if(!inside)
ui_num_popups--;
ui_set_active_item(0);
}
}
else if(ui_hot_item() == &ui_popups[i].id)
{
if(ui_mouse_button(0))
ui_set_active_item(&ui_popups[i].id);
}
int corners = CORNER_ALL;
if(ui_popups[i].is_menu)
corners = CORNER_R|CORNER_B;
RECT r = ui_popups[i].rect;
ui_draw_rect(&r, vec4(0.5f,0.5f,0.5f,0.75f), corners, 3.0f);
ui_margin(&r, 1.0f, &r);
ui_draw_rect(&r, vec4(0,0,0,0.75f), corners, 3.0f);
ui_margin(&r, 4.0f, &r);
if(ui_popups[i].func(r))
ui_num_popups--;
if(inp_key_down(KEY_ESC))
ui_num_popups--;
}
}
int popup_group(RECT view)
{
// remove group button
RECT button;
ui_hsplit_b(&view, 12.0f, &view, &button);
static int delete_button = 0;
if(do_editor_button(&delete_button, "Delete Group", 0, &button, draw_editor_button, 0, "Delete group"))
{
editor.map.delete_group(editor.selected_group);
return 1;
}
// new tile layer
ui_hsplit_b(&view, 10.0f, &view, &button);
ui_hsplit_b(&view, 12.0f, &view, &button);
static int new_quad_layer_button = 0;
if(do_editor_button(&new_quad_layer_button, "Add Quads Layer", 0, &button, draw_editor_button, 0, "Creates a new quad layer"))
{
LAYER *l = new LAYER_QUADS;
editor.map.groups[editor.selected_group]->add_layer(l);
editor.selected_layer = editor.map.groups[editor.selected_group]->layers.len()-1;
return 1;
}
// new quad layer
ui_hsplit_b(&view, 5.0f, &view, &button);
ui_hsplit_b(&view, 12.0f, &view, &button);
static int new_tile_layer_button = 0;
if(do_editor_button(&new_tile_layer_button, "Add Tile Layer", 0, &button, draw_editor_button, 0, "Creates a new tile layer"))
{
LAYER *l = new LAYER_TILES(50, 50);
editor.map.groups[editor.selected_group]->add_layer(l);
editor.selected_layer = editor.map.groups[editor.selected_group]->layers.len()-1;
return 1;
}
enum
{
PROP_ORDER=0,
PROP_POS_X,
PROP_POS_Y,
PROP_PARA_X,
PROP_PARA_Y,
NUM_PROPS,
};
PROPERTY props[] = {
{"Order", editor.selected_group, PROPTYPE_INT_STEP, 0, editor.map.groups.len()-1},
{"Pos X", -editor.map.groups[editor.selected_group]->offset_x, PROPTYPE_INT_SCROLL, -1000000, 1000000},
{"Pos Y", -editor.map.groups[editor.selected_group]->offset_y, PROPTYPE_INT_SCROLL, -1000000, 1000000},
{"Para X", editor.map.groups[editor.selected_group]->parallax_x, PROPTYPE_INT_SCROLL, -1000000, 1000000},
{"Para Y", editor.map.groups[editor.selected_group]->parallax_y, PROPTYPE_INT_SCROLL, -1000000, 1000000},
{0},
};
static int ids[NUM_PROPS] = {0};
int new_val = 0;
// cut the properties that isn't needed
if(editor.get_selected_group()->game_group)
props[PROP_POS_X].name = 0;
int prop = editor.do_properties(&view, props, ids, &new_val);
if(prop == PROP_ORDER)
editor.selected_group = editor.map.swap_groups(editor.selected_group, new_val);
// these can not be changed on the game group
if(!editor.get_selected_group()->game_group)
{
if(prop == PROP_PARA_X)
editor.map.groups[editor.selected_group]->parallax_x = new_val;
else if(prop == PROP_PARA_Y)
editor.map.groups[editor.selected_group]->parallax_y = new_val;
else if(prop == PROP_POS_X)
editor.map.groups[editor.selected_group]->offset_x = -new_val;
else if(prop == PROP_POS_Y)
editor.map.groups[editor.selected_group]->offset_y = -new_val;
}
return 0;
}
int popup_layer(RECT view)
{
// remove layer button
RECT button;
ui_hsplit_b(&view, 12.0f, &view, &button);
static int delete_button = 0;
if(do_editor_button(&delete_button, "Delete Layer", 0, &button, draw_editor_button, 0, "Deletes the layer"))
{
editor.map.groups[editor.selected_group]->delete_layer(editor.selected_layer);
return 1;
}
ui_hsplit_b(&view, 10.0f, &view, 0);
LAYERGROUP *current_group = editor.map.groups[editor.selected_group];
LAYER *current_layer = editor.get_selected_layer(0);
enum
{
PROP_GROUP=0,
PROP_ORDER,
NUM_PROPS,
};
PROPERTY props[] = {
{"Group", editor.selected_group, PROPTYPE_INT_STEP, 0, editor.map.groups.len()-1},
{"Order", editor.selected_layer, PROPTYPE_INT_STEP, 0, current_group->layers.len()},
{0},
};
static int ids[NUM_PROPS] = {0};
int new_val = 0;
int prop = editor.do_properties(&view, props, ids, &new_val);
if(prop == PROP_ORDER)
editor.selected_layer = current_group->swap_layers(editor.selected_layer, new_val);
else if(prop == PROP_GROUP && current_layer->type != LAYERTYPE_GAME)
{
if(new_val >= 0 && new_val < editor.map.groups.len())
{
current_group->layers.remove(current_layer);
editor.map.groups[new_val]->layers.add(current_layer);
editor.selected_group = new_val;
editor.selected_layer = editor.map.groups[new_val]->layers.len()-1;
}
}
return current_layer->render_properties(&view);
}
int popup_quad(RECT view)
{
QUAD *quad = editor.get_selected_quad();
RECT button;
ui_hsplit_b(&view, 12.0f, &view, &button);
static int sq_button = 0;
if(do_editor_button(&sq_button, "Square", 0, &button, draw_editor_button, 0, "Squares the current quad"))
{
int top = quad->points[0].y;
int left = quad->points[0].x;
int bottom = quad->points[0].y;
int right = quad->points[0].x;
for(int k = 1; k < 4; k++)
{
if(quad->points[k].y < top) top = quad->points[k].y;
if(quad->points[k].x < left) left = quad->points[k].x;
if(quad->points[k].y > bottom) bottom = quad->points[k].y;
if(quad->points[k].x > right) right = quad->points[k].x;
}
quad->points[0].x = left; quad->points[0].y = top;
quad->points[1].x = right; quad->points[1].y = top;
quad->points[2].x = left; quad->points[2].y = bottom;
quad->points[3].x = right; quad->points[3].y = bottom;
return 1;
}
//ui_vsplit_b(&toolbar, 2.0f, &button, &toolbar);
enum
{
PROP_POS_ENV=0,
PROP_POS_ENV_OFFSET,
PROP_COLOR_ENV,
PROP_COLOR_ENV_OFFSET,
NUM_PROPS,
};
PROPERTY props[] = {
{"Pos. Env", quad->pos_env, PROPTYPE_INT_STEP, -1, editor.map.envelopes.len()},
{"Pos. TO", quad->pos_env_offset, PROPTYPE_INT_SCROLL, -1000000, 1000000},
{"Color Env", quad->color_env, PROPTYPE_INT_STEP, -1, editor.map.envelopes.len()},
{"Color TO", quad->color_env_offset, PROPTYPE_INT_SCROLL, -1000000, 1000000},
{0},
};
static int ids[NUM_PROPS] = {0};
int new_val = 0;
int prop = editor.do_properties(&view, props, ids, &new_val);
if(prop == PROP_POS_ENV) quad->pos_env = new_val;
if(prop == PROP_POS_ENV_OFFSET) quad->pos_env_offset = new_val;
if(prop == PROP_COLOR_ENV) quad->color_env = new_val;
if(prop == PROP_COLOR_ENV_OFFSET) quad->color_env_offset = new_val;
return 0;
}
int popup_point(RECT view)
{
QUAD *quad = editor.get_selected_quad();
enum
{
PROP_COLOR=0,
NUM_PROPS,
};
int color = 0;
for(int v = 0; v < 4; v++)
{
if(editor.selected_points&(1<<v))
{
color = 0;
color |= quad->colors[v].r<<24;
color |= quad->colors[v].g<<16;
color |= quad->colors[v].b<<8;
color |= quad->colors[v].a;
}
}
PROPERTY props[] = {
{"Color", color, PROPTYPE_COLOR, -1, editor.map.envelopes.len()},
{0},
};
static int ids[NUM_PROPS] = {0};
int new_val = 0;
int prop = editor.do_properties(&view, props, ids, &new_val);
if(prop == PROP_COLOR)
{
for(int v = 0; v < 4; v++)
{
if(editor.selected_points&(1<<v))
{
color = 0;
quad->colors[v].r = (new_val>>24)&0xff;
quad->colors[v].g = (new_val>>16)&0xff;
quad->colors[v].b = (new_val>>8)&0xff;
quad->colors[v].a = new_val&0xff;
}
}
}
return 0;
}
static int select_image_selected = -100;
static int select_image_current = -100;
int popup_select_image(RECT view)
{
RECT buttonbar, imageview;
ui_vsplit_l(&view, 80.0f, &buttonbar, &view);
ui_margin(&view, 10.0f, &imageview);
int show_image = select_image_current;
for(int i = -1; i < editor.map.images.len(); i++)
{
RECT button;
ui_hsplit_t(&buttonbar, 12.0f, &button, &buttonbar);
ui_hsplit_t(&buttonbar, 2.0f, 0, &buttonbar);
if(ui_mouse_inside(&button))
show_image = i;
if(i == -1)
{
if(do_editor_button(&editor.map.images[i], "None", i==select_image_current, &button, draw_editor_button_menuitem, 0, 0))
select_image_selected = -1;
}
else
{
char buf[64];
sprintf(buf, "%d", i);
if(do_editor_button(&editor.map.images[i], buf, i==select_image_current, &button, draw_editor_button_menuitem, 0, 0))
select_image_selected = i;
}
}
if(show_image >= 0 && show_image < editor.map.images.len())
gfx_texture_set(editor.map.images[show_image]->tex_id);
else
gfx_texture_set(-1);
gfx_quads_begin();
gfx_quads_drawTL(imageview.x, imageview.y, imageview.w, imageview.h);
gfx_quads_end();
return 0;
}
void popup_select_image_invoke(int current, float x, float y)
{
static int select_image_popup_id = 0;
select_image_selected = -100;
select_image_current = current;
ui_invoke_popup_menu(&select_image_popup_id, 0, x, y, 400, 300, popup_select_image);
}
int popup_select_image_result()
{
if(select_image_selected == -100)
return -100;
select_image_current = select_image_selected;
select_image_selected = -100;
return select_image_current;
}

View file

@ -129,48 +129,4 @@ public:
inline bool col_check_point(float x, float y) { return col_is_solid((int)x, (int)y) != 0; }
inline bool col_check_point(vec2 p) { return col_check_point(p.x, p.y); }
struct mapres_entity
{
int x, y;
int data[1];
};
struct mapres_spawnpoint
{
int x, y;
};
struct mapres_item
{
int x, y;
int type;
};
struct mapres_flagstand
{
int x, y;
};
enum
{
MAPRES_ENTS_START=1,
MAPRES_SPAWNPOINT=1,
MAPRES_ITEM=2,
MAPRES_SPAWNPOINT_RED=3,
MAPRES_SPAWNPOINT_BLUE=4,
MAPRES_FLAGSTAND_RED=5,
MAPRES_FLAGSTAND_BLUE=6,
MAPRES_ENTS_END,
ITEM_NULL=0,
ITEM_WEAPON_GUN=0x00010001,
ITEM_WEAPON_SHOTGUN=0x00010002,
ITEM_WEAPON_ROCKET=0x00010003,
ITEM_WEAPON_SNIPER=0x00010004,
ITEM_WEAPON_HAMMER=0x00010005,
ITEM_HEALTH =0x00020001,
ITEM_ARMOR=0x00030001,
ITEM_NINJA=0x00040001,
};
#endif

View file

@ -16,6 +16,15 @@ enum
MAPITEMTYPE_ENVELOPE,
MAPITEMTYPE_GROUP,
MAPITEMTYPE_LAYER,
MAPITEMTYPE_ENVPOINTS,
CURVETYPE_STEP=0,
CURVETYPE_LINEAR,
CURVETYPE_SLOW,
CURVETYPE_FAST,
CURVETYPE_SMOOTH,
NUM_CURVETYPES,
// game layer tiles
ENTITY_NULL=0,
@ -133,6 +142,22 @@ typedef struct
int version;
} MAPITEM_VERSION;
typedef struct
{
int time; // in ms
int curvetype;
int values[4]; // 1-4 depending on envelope (22.10 fixed point)
} ENVPOINT;
typedef struct
{
int version;
int channels;
int start_point;
int num_points;
int name;
} MAPITEM_ENVELOPE;
// float to fixed
inline int f2fx(float v) { return (int)(v*(float)(1<<10)); }
inline float fx2f(int v) { return v*(1.0f/(1<<10)); }

View file

@ -133,7 +133,9 @@ public:
int gametype;
gameobject();
void do_team_wincheck();
void do_team_score_wincheck();
void do_player_score_wincheck();
void do_warmup(int seconds);
void startround();

View file

@ -289,7 +289,40 @@ int gameobject::getteam(int notthisid)
return numplayers[0] > numplayers[1] ? 1 : 0;
}
void gameobject::do_team_wincheck()
void gameobject::do_player_score_wincheck()
{
if(game_over_tick == -1 && !warmup)
{
// gather some stats
int topscore = 0;
int topscore_count = 0;
for(int i = 0; i < MAX_CLIENTS; i++)
{
if(players[i].client_id != -1)
{
if(players[i].score > topscore)
{
topscore = players[i].score;
topscore_count = 1;
}
else if(players[i].score == topscore)
topscore_count++;
}
}
// check score win condition
if((config.sv_scorelimit > 0 && topscore >= config.sv_scorelimit) ||
(config.sv_timelimit > 0 && (server_tick()-round_start_tick) >= config.sv_timelimit*server_tickspeed()*60))
{
if(topscore_count == 1)
endround();
else
sudden_death = 1;
}
}
}
void gameobject::do_team_score_wincheck()
{
if(game_over_tick == -1 && !warmup)
{

View file

@ -62,7 +62,7 @@ void gameobject_ctf::tick()
{
gameobject::tick();
do_team_wincheck();
do_team_score_wincheck();
// do flags
for(int fi = 0; fi < 2; fi++)

View file

@ -5,38 +5,6 @@
void gameobject_dm::tick()
{
if(game_over_tick == -1)
{
// game is running
// gather some stats
int topscore = 0;
int topscore_count = 0;
for(int i = 0; i < MAX_CLIENTS; i++)
{
if(players[i].client_id != -1)
{
if(players[i].score > topscore)
{
topscore = players[i].score;
topscore_count = 1;
}
else if(players[i].score == topscore)
topscore_count++;
}
}
// check score win condition
if((config.sv_scorelimit > 0 && topscore >= config.sv_scorelimit) ||
(config.sv_timelimit > 0 && (server_tick()-round_start_tick) >= config.sv_timelimit*server_tickspeed()*60))
{
if(topscore_count == 1)
endround();
else
sudden_death = 1;
}
}
do_player_score_wincheck();
gameobject::tick();
}

View file

@ -8,7 +8,6 @@ gameobject_tdm::gameobject_tdm()
is_teamplay = true;
}
int gameobject_tdm::on_player_death(class player *victim, class player *killer, int weapon)
{
gameobject::on_player_death(victim, killer, weapon);
@ -26,7 +25,6 @@ int gameobject_tdm::on_player_death(class player *victim, class player *killer,
void gameobject_tdm::tick()
{
do_team_wincheck();
do_team_score_wincheck();
gameobject::tick();
}