diff options
| author | Magnus Auvinen <magnus.auvinen@gmail.com> | 2008-01-12 15:07:57 +0000 |
|---|---|---|
| committer | Magnus Auvinen <magnus.auvinen@gmail.com> | 2008-01-12 15:07:57 +0000 |
| commit | 99f0a47d6b03b005d0a7dae064cb6eb7cb4f60b5 (patch) | |
| tree | 6c453bff72668da6cc6f6e28621356004a06d441 /src/game/editor/editor.hpp | |
| parent | 2aba180f8c1bfa2680b1f660148de1dc82b03298 (diff) | |
| download | zcatch-99f0a47d6b03b005d0a7dae064cb6eb7cb4f60b5.tar.gz zcatch-99f0a47d6b03b005d0a7dae064cb6eb7cb4f60b5.zip | |
first round of code cleanup
Diffstat (limited to 'src/game/editor/editor.hpp')
| -rw-r--r-- | src/game/editor/editor.hpp | 569 |
1 files changed, 569 insertions, 0 deletions
diff --git a/src/game/editor/editor.hpp b/src/game/editor/editor.hpp new file mode 100644 index 00000000..0d2af5e1 --- /dev/null +++ b/src/game/editor/editor.hpp @@ -0,0 +1,569 @@ +#include <stdlib.h> +#include <math.h> +#include "array.h" + +extern "C" { + #include <engine/e_system.h> + #include <engine/e_interface.h> + #include <engine/e_datafile.h> + #include <engine/e_config.h> +} + +#include <game/client/gc_ui.h> + +// EDITOR SPECIFIC +template<typename T> +void swap(T &a, T &b) +{ + T tmp = a; + a = b; + b = tmp; +} + +enum +{ + MODE_MAP=0, + MODE_LAYERS, + MODE_IMAGES, + + DIALOG_NONE=0, + DIALOG_LOAD_IMAGE, + + LAYERTYPE_INVALID=0, + LAYERTYPE_GAME, + LAYERTYPE_TILES, + LAYERTYPE_QUADS, +}; + +typedef struct +{ + int x, y; // 22.10 fixed point +} POINT; + +// 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)); } + +typedef struct // as in file +{ + int r, g, b, a; +} COLOR; + +typedef struct // as in file +{ + POINT points[5]; + COLOR colors[4]; + POINT texcoords[4]; + + int pos_env; + int pos_env_offset; + + int color_env; + int color_env_offset; +} QUAD; + +typedef struct // as in file +{ + POINT position; + int type; +} ENTITY; + +enum +{ + ENTITY_NULL=0, + ENTITY_SPAWN, + ENTITY_SPAWN_RED, + ENTITY_SPAWN_BLUE, + ENTITY_FLAGSTAND_RED, + ENTITY_FLAGSTAND_BLUE, + ENTITY_ARMOR_1, + ENTITY_HEATH_1, + ENTITY_WEAPON_SHOTGUN, + ENTITY_WEAPON_ROCKET, + ENTITY_POWERUP_NINJA, + NUM_ENTITIES, + + TILE_AIR=0, + TILE_SOLID, + TILE_NOHOOK, + + ENTITY_OFFSET=255-16*4, +}; + +typedef struct // as in file +{ + unsigned char index; + unsigned char flags; + unsigned char reserved1; + unsigned char reserved2; +} TILE; + +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: + int channels; + array<ENVPOINT> points; + char name[32]; + float bottom, top; + + ENVELOPE(int chan) + { + channels = chan; + name[0] = 0; + bottom = 0; + top = 0; + } + + static int sort_comp(const void *v0, const void *v1) + { + const ENVPOINT *p0 = (const ENVPOINT *)v0; + const ENVPOINT *p1 = (const ENVPOINT *)v1; + if(p0->time < p1->time) + return -1; + if(p0->time > p1->time) + return 1; + return 0; + } + + void resort() + { + qsort(points.getptr(), points.len(), sizeof(ENVPOINT), sort_comp); + find_top_bottom(); + } + + void find_top_bottom() + { + top = -1000000000.0f; + bottom = 1000000000.0f; + for(int i = 0; i < points.len(); i++) + { + for(int c = 0; c < channels; c++) + { + float v = fx2f(points[i].values[c]); + if(v > top) top = v; + if(v < bottom) bottom = v; + } + } + } + + float eval(float time, int channel) + { + 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]; + } + + void add_point(int time, int v0, int v1=0, int v2=0, int v3=0) + { + ENVPOINT p; + p.time = time; + p.values[0] = v0; + p.values[1] = v1; + p.values[2] = v2; + p.values[3] = v3; + p.curvetype = CURVETYPE_LINEAR; + points.add(p); + resort(); + } + + float end_time() + { + if(points.len()) + return points[points.len()-1].time*(1.0f/1000.0f); + return 0; + } +}; + + +class LAYER; +class LAYERGROUP; +class MAP; + +class LAYER +{ +public: + LAYER() + { + type = LAYERTYPE_INVALID; + type_name = "(invalid)"; + visible = true; + readonly = false; + } + + virtual ~LAYER() + { + } + + + virtual void brush_selecting(RECT rect) {} + virtual int brush_grab(LAYERGROUP *brush, RECT rect) { return 0; } + virtual void brush_draw(LAYER *brush, float x, float y) {} + virtual void brush_place(LAYER *brush, float x, float y) {} + virtual void brush_flip_x() {} + virtual void brush_flip_y() {} + + virtual void render() {} + virtual void render_properties(RECT *toolbox) {} + + virtual void get_size(float *w, float *h) { *w = 0; *h = 0;} + + const char *type_name; + int type; + + bool readonly; + bool visible; +}; + +class LAYERGROUP +{ +public: + array<LAYER*> layers; + + int offset_x; + int offset_y; + + int parallax_x; + int parallax_y; + + const char *name; + bool game_group; + bool visible; + + LAYERGROUP(); + ~LAYERGROUP(); + + void convert(RECT *rect); + void render(); + void mapscreen(); + void mapping(float *points); + + bool is_empty() const; + void clear(); + void add_layer(LAYER *l); + + void get_size(float *w, float *h); + + void delete_layer(int index); + int swap_layers(int index0, int index1); +}; + +class IMAGE : public IMAGE_INFO +{ +public: + IMAGE() + { + tex_id = -1; + name[0] = 0; + } + + int tex_id; + char name[128]; +}; + +class MAP +{ +public: + array<LAYERGROUP*> groups; + array<IMAGE*> images; + array<ENVELOPE*> envelopes; + + ENVELOPE *new_envelope(int channels) + { + ENVELOPE *e = new ENVELOPE(channels); + envelopes.add(e); + return e; + } + + LAYERGROUP *new_group() + { + LAYERGROUP *g = new LAYERGROUP; + groups.add(g); + return g; + } + + int swap_groups(int index0, int index1) + { + if(index0 < 0 || index0 >= groups.len()) return index0; + if(index1 < 0 || index1 >= groups.len()) return index0; + if(index0 == index1) return index0; + swap(groups[index0], groups[index1]); + return index1; + } + + void delete_group(int index) + { + if(index < 0 || index >= groups.len()) return; + delete groups[index]; + groups.removebyindex(index); + } +}; + + +struct PROPERTY +{ + const char *name; + int value; + int type; + int min; + int max; +}; + +enum +{ + PROPTYPE_NULL=0, + PROPTYPE_INT_STEP, + PROPTYPE_INT_SCROLL, + PROPTYPE_COLOR, + + PROPS_NONE=0, + PROPS_GROUP, + PROPS_LAYER, + PROPS_QUAD, + PROPS_QUAD_POINT, +}; + +class EDITOR +{ +public: + EDITOR() + { + mode = MODE_LAYERS; + dialog = 0; + tooltip = 0; + + world_offset_x = 0; + world_offset_y = 0; + editor_offset_x = 0.0f; + editor_offset_y = 0.0f; + + world_zoom = 1.0f; + zoom_level = 100; + lock_mouse = false; + mouse_delta_x = 0; + mouse_delta_y = 0; + mouse_delta_wx = 0; + mouse_delta_wy = 0; + + gui_active = true; + proof_borders = false; + + + animate = false; + animate_start = 0; + animate_time = 0; + + props = PROPS_NONE; + + show_envelope_editor = 0; + } + + void make_game_group(LAYERGROUP *group); + void make_game_layer(LAYER *layer); + + int save(const char *filename); + int load(const char *filename); + + QUAD *get_selected_quad(); + LAYER *get_selected_layer_type(int index, int type); + LAYER *get_selected_layer(int index); + LAYERGROUP *get_selected_group(); + + class LAYER_GAME *game_layer; + LAYERGROUP *game_group; + + int do_properties(RECT *toolbox, PROPERTY *props, int *ids, int *new_val); + + int mode; + int dialog; + const char *tooltip; + + float world_offset_x; + float world_offset_y; + float editor_offset_x; + float editor_offset_y; + float world_zoom; + int zoom_level; + bool lock_mouse; + bool gui_active; + bool proof_borders; + float mouse_delta_x; + float mouse_delta_y; + float mouse_delta_wx; + float mouse_delta_wy; + + bool animate; + int64 animate_start; + float animate_time; + + int props; + + int show_envelope_editor; + + MAP map; +}; + +extern EDITOR editor; + +typedef struct +{ + int x, y; + int w, h; +} RECTi; + +class LAYER_TILES : public LAYER +{ +public: + LAYER_TILES(int w, int h); + ~LAYER_TILES(); + + void resize(int new_w, int new_h); + + void make_palette(); + virtual void render(); + + int convert_x(float x) const; + int convert_y(float y) const; + void convert(RECT rect, RECTi *out); + void snap(RECT *rect); + void clamp(RECTi *rect); + + virtual void brush_selecting(RECT rect); + virtual int brush_grab(LAYERGROUP *brush, RECT rect); + virtual void brush_draw(LAYER *brush, float wx, float wy); + virtual void brush_flip_x(); + virtual void brush_flip_y(); + + virtual void render_properties(RECT *toolbox); + + void get_size(float *w, float *h) { *w = width*32.0f; *h = height*32.0f; } + + int tex_id; + int game; + int image; + int width; + int height; + TILE *tiles; +}; + +class LAYER_QUADS : public LAYER +{ +public: + LAYER_QUADS(); + ~LAYER_QUADS(); + + virtual void render(); + QUAD *new_quad(); + + virtual void brush_selecting(RECT rect); + virtual int brush_grab(LAYERGROUP *brush, RECT rect); + virtual void brush_place(LAYER *brush, float wx, float wy); + virtual void brush_flip_x(); + virtual void brush_flip_y(); + + virtual void render_properties(RECT *toolbox); + + void get_size(float *w, float *h); + + int image; + array<QUAD> quads; +}; + + +class LAYER_GAME : public LAYER_TILES +{ +public: + LAYER_GAME(int w, int h); + ~LAYER_GAME(); + + virtual void render_properties(RECT *toolbox); +}; + + +inline void calc_screen_params(float amount, float wmax, float hmax, float aspect, float *w, float *h) +{ + float f = sqrt(amount) / sqrt(aspect); + *w = f*aspect; + *h = f; + + // limit the view + if(*w > wmax) + { + *w = wmax; + *h = *w/aspect; + } + + if(*h > hmax) + { + *h = hmax; + *w = *h*aspect; + } +} + +inline void mapscreen_to_world(float center_x, float center_y, float parallax_x, float parallax_y, + float offset_x, float offset_y, float aspect, float zoom, float *points) +{ + float width, height; + calc_screen_params(1300*1000, 1500, 1050, aspect, &width, &height); + center_x *= parallax_x; + center_y *= parallax_y; + width *= zoom; + height *= zoom; + points[0] = offset_x+center_x-width/2; + points[1] = offset_y+center_y-height/2; + points[2] = offset_x+center_x+width/2; + points[3] = offset_y+center_y+height/2; +} |