365 lines
12 KiB
C
365 lines
12 KiB
C
#include "v4k.h"
|
|
#include "split/3rd_icon_mdi.h"
|
|
|
|
#if 0 // v4k_pack proposal
|
|
static __thread char* mpin;
|
|
static __thread unsigned mpinlen;
|
|
static __thread char mpinbuf[256];
|
|
static __thread char* mpout;
|
|
static __thread unsigned mpoutlen;
|
|
static __thread char mpoutbuf[256];
|
|
#define PACKMSG(...) (msgpack_new(mpin = mpinbuf, mpinlen = sizeof(mpinbuf)), mpinlen = msgpack(__VA_ARGS__), cobs_encode(mpin, mpinlen, mpout = mpoutbuf, mpoutlen = cobs_bounds(mpinlen)), mpout)
|
|
#define UNPACKMSG(ptr,fmt,...) (mpin = (char*)ptr, mpinlen = strlen(ptr), mpout = mpoutbuf, mpoutlen = sizeof(mpoutbuf), mpoutlen = cobs_decode(mpin, mpinlen, mpout, mpoutlen), msgunpack_new(mpout, mpoutlen) && msgunpack(fmt, __VA_ARGS__))
|
|
#endif
|
|
|
|
TODO("COOK_ON_DEMAND 1: this directive should be on client, not within v4k.dll");
|
|
TODO("ENABLE_AUTOTESTS 1: this directive should be on client, not within v4k.dll");
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
TODO("editor_load_on_boot()");
|
|
TODO("editor_save_on_quit()");
|
|
|
|
TODO("file_id: glow.hdr vs glow.png");
|
|
TODO("reflect: iterate components+metas on REFLECT too, so they're properly saved/loaded");
|
|
|
|
TODO("edit: tree nav");
|
|
TODO("edit: keys up,down,left,right -> move selection");
|
|
TODO("edit: reordering/dragging items on a list. ctrl+cursors");
|
|
TODO("edit: tab -> cycle next node of matching highlighted type");
|
|
TODO("edit: ^C^V^X thru clipboard. ^C to serialize to clipboard.");
|
|
TODO("edit: ^Z^Y cursor too. also fix undo ordering");
|
|
TODO("edit: ^S^L^N. load/save as filesystems");
|
|
TODO("edit: ^B(toolbar)");
|
|
TODO("edit: ^E prop single-view for multiple selections: should inspect common fields only");
|
|
TODO("edit: two-column way (or Nth) for multiple selections");
|
|
TODO("edit: tab/caps view, world + entity only, obj printf");
|
|
TODO("edit: obj bounds, obj picking, obj collisions");
|
|
TODO("edit: LMB object picking, RMB object serialization + log, floating ICONS bulb light");
|
|
TODO("edit: worldtraveller component");
|
|
TODO("edit: levelstreamer component");
|
|
TODO("edit: OSC server/client port 2023");
|
|
TODO("edit: add/rem entities, add/rem components, add/rem/pause/resume systems");
|
|
TODO("edit: event loop: tick,draw*,spawn,delete,un/load from bvh stream,");
|
|
|
|
TODO("edit: overlay scene editor");
|
|
TODO("edit: overlay0 artwork");
|
|
TODO("edit: overlay1 world editor: gizmo, grid, snap, splats (@todo: fixed screen size gizmos)");
|
|
TODO("edit: overlay2 script editor");
|
|
TODO("edit: overlay3 track, spline, keys editor");
|
|
TODO("edit: overlay4 node editor (shader/anim/bt/hfsm/material/audio/blueprints)");
|
|
TODO("edit: overlay5 csv editor");
|
|
TODO("edit: overlay6 bug/task editor");
|
|
|
|
TODO("gfx: tree traversal from game");
|
|
TODO("gfx: bvh and collision queries");
|
|
TODO("gfx: visibility and pvs queries");
|
|
|
|
TODO("obj: finish SYSTEMS and join queries");
|
|
TODO("obj: make it work with /GL flag (VC)");
|
|
TODO("obj: impl obj_mutate() ... deprecate?");
|
|
TODO("obj: make() from mpack(m) + native(n)");
|
|
TODO("obj: make() should save schema `[{mn`+version. and (m)pack and (n)ative should start with objtype");
|
|
TODO("obj: super()");
|
|
TODO("obj: lock()/trylock()/unlock()/barrier(N)");
|
|
TODO("obj: diff()/patch()");
|
|
TODO("obj: free obj_children()/payload");
|
|
TODO("obj: free obj_components()/payload2");
|
|
|
|
TODO("pack: mp2json, json2mp");
|
|
TODO("pack: simplify msgpack API, make it growth similar to va()")
|
|
|
|
TODO("serialize array(types)")
|
|
TODO("serialize map(char*,types)")
|
|
TODO("serialize map(int,types)")
|
|
TODO("sprite: solid platforms, one-way platforms")
|
|
TODO("sprite: shake left-right, up-down")
|
|
TODO("sprite: coyote time")
|
|
TODO("sprite: jump buffering before grounded")
|
|
TODO("sprite: double jump, wall sliding, wall climbing")
|
|
TODO("sprite: hitbox for enemies -> wall detection")
|
|
|
|
TODO("new: integrate with Art/ browser")
|
|
TODO("bug: lite key bindings are being sent to editor")
|
|
TODO("bug: not sending quit signal to lite neither at window close nor editor close (see: temporary files)")
|
|
TODO("bug: missing search results window")
|
|
TODO("bug: missing code completions popup")
|
|
|
|
// TODO("eval: https://github.com/drmargarido/linters")
|
|
// TODO("eval: https://github.com/monolifed/theme16")
|
|
// TODO("eval: https://github.com/vincens2005/lite-formatters")
|
|
// https://github.com/takase1121/lite-xl-img
|
|
// https://github.com/takase1121/lite-xl-finder
|
|
// https://github.com/rxi/lite/commit/236a585756cb9fa70130eee6c9a604780aced424 > suru.png
|
|
// https://github.com/rxi/lite/commit/f90b00748e1fe1cd2340aaa06d2526a1b2ea54ec
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// demo
|
|
|
|
typedef struct lit { OBJ
|
|
vec3 pos;
|
|
vec3 dir;
|
|
int type;
|
|
} lit;
|
|
|
|
int lit_aabb(lit *obj, aabb *box) {
|
|
*box = aabb( vec3(obj->pos.x-16,obj->pos.y-16,0), vec3(obj->pos.x+16,obj->pos.y+16,1) );
|
|
return 1;
|
|
}
|
|
const char *lit_icon(lit *obj) {
|
|
const char *icon =
|
|
obj->type == 0 ? ICON_MD_WB_IRIDESCENT :
|
|
obj->type == 1 ? ICON_MD_WB_INCANDESCENT :
|
|
obj->type == 2 ? ICON_MD_FLARE :
|
|
obj->type == 3 ? ICON_MD_WB_SUNNY : "";
|
|
return icon;
|
|
}
|
|
int lit_edit(lit *obj) {
|
|
const char *all_icons =
|
|
ICON_MD_WB_IRIDESCENT
|
|
ICON_MD_WB_INCANDESCENT
|
|
ICON_MD_FLARE
|
|
ICON_MD_WB_SUNNY
|
|
|
|
ICON_MD_LIGHT_MODE
|
|
ICON_MD_LIGHT
|
|
|
|
ICON_MD_FLASHLIGHT_OFF
|
|
ICON_MD_FLASHLIGHT_ON
|
|
ICON_MD_HIGHLIGHT
|
|
ICON_MD_HIGHLIGHT_ALT
|
|
ICON_MD_LIGHTBULB
|
|
ICON_MD_LIGHTBULB_OUTLINE
|
|
ICON_MD_NIGHTLIGHT
|
|
ICON_MD_NIGHTLIGHT_ROUND
|
|
|
|
// MDI
|
|
ICON_MDI_LIGHTBULB_ON_OUTLINE // generic
|
|
ICON_MDI_WALL_SCONCE_ROUND //
|
|
ICON_MDI_WALL_SCONCE_FLAT // emissive
|
|
ICON_MDI_CEILING_LIGHT // spotlight
|
|
ICON_MDI_TRACK_LIGHT // spotlight
|
|
ICON_MDI_WEATHER_SUNNY // directional
|
|
ICON_MDI_LIGHTBULB_FLUORESCENT_TUBE_OUTLINE
|
|
;
|
|
// editor_symbol(obj->pos.x+16,obj->pos.y-32,all_icons);
|
|
if( editor_selected(obj) ) {
|
|
obj->pos.x += input(KEY_RIGHT) - input(KEY_LEFT);
|
|
obj->pos.y += input(KEY_DOWN) - input(KEY_UP);
|
|
obj->type = (obj->type + !!input_down(KEY_SPACE)) % 4;
|
|
}
|
|
editor_symbol(obj->pos.x,obj->pos.y,lit_icon(obj));
|
|
|
|
|
|
|
|
return 1;
|
|
}
|
|
|
|
OBJTYPEDEF(lit,200);
|
|
|
|
AUTORUN {
|
|
STRUCT(lit, vec3, pos);
|
|
STRUCT(lit, vec3, dir);
|
|
STRUCT(lit, int, type);
|
|
EXTEND(lit, edit,icon,aabb);
|
|
}
|
|
|
|
typedef struct kid { OBJ
|
|
int kid;
|
|
vec2 pos;
|
|
vec2 vel;
|
|
float angle;
|
|
unsigned color;
|
|
int controllerid;
|
|
|
|
// --- private
|
|
char *filename;
|
|
texture_t texture_;
|
|
} kid;
|
|
|
|
void kid_ctor(kid *obj) {
|
|
obj->kid = randi(0,3);
|
|
obj->pos = vec2(randi(0, window_width()), randi(0, window_height()));
|
|
obj->vel.x = obj->vel.y = 100 + 200 * randf();
|
|
obj->controllerid = randi(0,3);
|
|
|
|
obj->texture_ = texture(obj->filename, TEXTURE_RGBA|TEXTURE_LINEAR);
|
|
}
|
|
void kid_tick(kid *obj, float dt) {
|
|
// add velocity to position
|
|
vec2 off = vec2( input(KEY_RIGHT)-input(KEY_LEFT), input(KEY_DOWN)-input(KEY_UP) );
|
|
obj->pos = add2(obj->pos, scale2(mul2(obj->vel, off), dt * (obj->controllerid == 0)));
|
|
|
|
// wrap at screen boundaries
|
|
const int appw = window_width(), apph = window_height();
|
|
if( obj->pos.x < 0 ) obj->pos.x += appw; else if( obj->pos.x > appw ) obj->pos.x -= appw;
|
|
if( obj->pos.y < 0 ) obj->pos.y += apph; else if( obj->pos.y > apph ) obj->pos.y -= apph;
|
|
}
|
|
void kid_draw(kid *obj) {
|
|
// 4x4 tilesheet
|
|
int col = (((int)obj->kid) % 4);
|
|
int row = (((int)obj->pos.x / 10 ^ (int)obj->pos.y / 10) % 4);
|
|
float position[3] = {obj->pos.x,obj->pos.y,obj->pos.y}; // position(x,y,depth: sort by Y)
|
|
float offset[2]={0,0}, scale[2]={1,1};
|
|
float coords[3]={col * 4 + row,4,4}; // num_frame(x) in a 4x4(y,z) spritesheet
|
|
unsigned flags = 0;
|
|
sprite_sheet(obj->texture_, coords, position, obj->angle*TO_DEG, offset, scale, obj->color, flags);
|
|
}
|
|
int kid_aabb(kid *obj, aabb *box) {
|
|
*box = aabb( vec3(obj->pos.x-16,obj->pos.y-16,0), vec3(obj->pos.x+16,obj->pos.y+16,1) );
|
|
return 1;
|
|
}
|
|
int kid_edit(kid *obj) {
|
|
aabb box;
|
|
if( kid_aabb(obj, &box) ) {
|
|
ddraw_color_push(YELLOW);
|
|
ddraw_push_2d();
|
|
ddraw_aabb(box.min, box.max);
|
|
ddraw_pop_2d();
|
|
ddraw_color_pop();
|
|
}
|
|
if( editor_selected(obj) ) {
|
|
obj->pos.x += input(KEY_RIGHT) - input(KEY_LEFT);
|
|
obj->pos.y += input(KEY_DOWN) - input(KEY_UP);
|
|
|
|
editor_symbol(obj->pos.x+16,obj->pos.y-16,ICON_MD_VIDEOGAME_ASSET);
|
|
}
|
|
return 1;
|
|
}
|
|
void kid_menu(kid *obj, const char *argv) {
|
|
ui_label("Private section");
|
|
ui_color4("Color_", &obj->color);
|
|
ui_texture("Texture_", obj->texture_);
|
|
ui_separator();
|
|
}
|
|
|
|
OBJTYPEDEF(kid,201);
|
|
|
|
AUTORUN {
|
|
// reflect
|
|
STRUCT(kid, int, kid);
|
|
STRUCT(kid, vec2, pos);
|
|
STRUCT(kid, vec2, vel);
|
|
STRUCT(kid, float, angle, "Tilt degrees");
|
|
STRUCT(kid, rgba, color, "Tint color");
|
|
STRUCT(kid, char*, filename, "Filename" );
|
|
EXTEND(kid, ctor,tick,draw,aabb,edit,menu);
|
|
}
|
|
|
|
void game(unsigned frame, float dt, double t) {
|
|
static kid *root;
|
|
static kid *o1;
|
|
static kid *o2;
|
|
static camera_t cam;
|
|
if( !frame ) {
|
|
// init camera (x,y) (z = zoom)
|
|
cam = camera();
|
|
cam.position = vec3(window_width()/2,window_height()/2,1);
|
|
camera_enable(&cam);
|
|
|
|
root = obj_make(
|
|
"[kid]\n"
|
|
"filename=spriteSheetExample.png\n"
|
|
"pos=5,2\n"
|
|
"angle=pi/12\n"
|
|
"color=#ffcf\n"
|
|
);
|
|
o1 = obj_make(
|
|
"[kid]\n"
|
|
"filename=spriteSheetExample.png\n"
|
|
"pos=1,100\n"
|
|
"angle=pi/12\n"
|
|
"color=#fcc\n"
|
|
);
|
|
o2 = obj_make(
|
|
"[kid]\n"
|
|
"filename=spriteSheetExample.png\n"
|
|
"pos=50,200\n"
|
|
"angle=pi/12\n"
|
|
"color=#ccccffff\n"
|
|
);
|
|
|
|
//obj_setname(root, "root");
|
|
obj_setname(o1, "o1");
|
|
obj_setname(o2, "o2");
|
|
|
|
obj*o3 = obj_make(
|
|
"[lit]\n"
|
|
"pos=300,300,0\n"
|
|
"type=1"
|
|
);
|
|
obj*o4 = obj_new_ext(obj, "o4");
|
|
obj*o5 = obj_new_ext(obj, "o5");
|
|
|
|
obj_attach(root, o1);
|
|
obj_attach(o1, o2);
|
|
obj_attach(o2, o3);
|
|
obj_attach(o1, o4);
|
|
obj_attach(root, o5);
|
|
|
|
editor_watch(root);
|
|
}
|
|
|
|
// camera panning (x,y) & zooming (z)
|
|
if(0)
|
|
if( !ui_hover() && !ui_active() ) {
|
|
if( input(MOUSE_L) ) cam.position.x -= input_diff(MOUSE_X);
|
|
if( input(MOUSE_L) ) cam.position.y -= input_diff(MOUSE_Y);
|
|
cam.position.z += input_diff(MOUSE_W) * 0.1; // cam.p.z += 0.001f; for tests
|
|
}
|
|
|
|
// tick game
|
|
if( dt ) {
|
|
kid_tick(root, dt);
|
|
kid_tick(o1, dt);
|
|
kid_tick(o2, dt);
|
|
|
|
root->angle = 5 * sin(t+dt);
|
|
}
|
|
|
|
// fps camera
|
|
bool active = 0;
|
|
if( input_down(MOUSE_M) || input_down(MOUSE_R) ) {
|
|
active = ui_hover() || ui_active() || gizmo_active() || editor_first_selected() ? false : true;
|
|
} else {
|
|
active = !window_has_cursor() && (input(MOUSE_M) || input(MOUSE_R));
|
|
}
|
|
window_cursor( !active );
|
|
if( active ) cam.speed = clampf(cam.speed + input_diff(MOUSE_W) / 10, 0.05f, 5.0f);
|
|
vec2 mouse = scale2(vec2(input_diff(MOUSE_X), -input_diff(MOUSE_Y)), 0.2f * active);
|
|
vec3 wasdecq = scale3(vec3(input(KEY_D)-input(KEY_A),input(KEY_E)-(input(KEY_C)||input(KEY_Q)),input(KEY_W)-input(KEY_S)), cam.speed);
|
|
camera_moveby(&cam, wasdecq);
|
|
camera_fps(&cam, mouse.x,mouse.y);
|
|
|
|
// draw world
|
|
ddraw_ontop_push(0);
|
|
ddraw_grid(0);
|
|
ddraw_ontop_pop();
|
|
ddraw_flush();
|
|
|
|
// draw game
|
|
kid_draw(root);
|
|
kid_draw(o1);
|
|
kid_draw(o2);
|
|
}
|
|
|
|
int main(){
|
|
// borderless, see:
|
|
// https://github.com/glfw/glfw/pull/1420
|
|
// https://github.com/glfw/glfw/pull/987
|
|
// https://github.com/glfw/glfw/pull/991
|
|
// https://github.com/glfw/glfw/pull/990
|
|
|
|
window_title("Editor " EDITOR_VERSION);
|
|
if( flag("--transparent") )
|
|
window_create(101, 0);
|
|
else
|
|
window_create(80, flag("--windowed") ? 0 : WINDOW_BORDERLESS);
|
|
window_icon("scale-ruler-icon.png");
|
|
|
|
while( window_swap() ) {
|
|
editor_frame(game);
|
|
editor_gizmos(2);
|
|
}
|
|
}
|