498 lines
18 KiB
C
498 lines
18 KiB
C
#include "v4k.h"
|
|
#include "split/3rd_icon_mdi.h"
|
|
|
|
#define SWAP(T,a,b) do { T c = (a); (a) = (b); (b) = c; } while(0)
|
|
|
|
#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
|
|
|
|
#if 0 // good UI/UX blender ideas
|
|
ui density is perfect: font face, font size and icon sizes are perfect even in a low res 1366x768 scenario
|
|
viewport: not cluttered at all. vertical floating toolbar on the left, floating icons on the right
|
|
left icons are tools related to current edition mode, right icons are camera only.
|
|
left icons can be long pressed for a hovered submenu, right icons can be clicked or dragged.
|
|
non-matching text filtering works by disabling widgets, not by hiding them
|
|
window contents can be promoted to any display any other window content by clicking their [icon V]
|
|
there are no windows or minimize/maximize buttons
|
|
windows are grouped with a vertical toolbar inside the right bar docked section
|
|
you can only display 1 window at time.
|
|
panels can be dragged within a window and make much more sense than our approach
|
|
scene tree: can make collections/groups
|
|
widget tree drawing is much simpler than us, just a vertical parent line per collection and indented arrows per child
|
|
context menus are always like: optional icon (white), text (white), either optional input binding (gray) or submenu arrow
|
|
input boxes are super reactive
|
|
< > are hidden unless hovered
|
|
< > can be clicked to de/increment (release)
|
|
< > can be horizontally dragged to de/increment larger quantities (hold)
|
|
< > can be vertically dragged to include other Y,Z properties in the selection (hold)
|
|
0.53m can be clicked (release) or dragged (<-> hovered icon) (hold).
|
|
0.53m whole text is automatically selected when clicked.
|
|
you can enter units when entering values 350m, 350km, 12mi
|
|
you can enter math values: 30+20+sin(1)
|
|
numeric: units always specified: 0 m, 90o, 1.25x
|
|
numeric: epsilons (non-zero) displayed as -0.00000 even if digits cannot fit widget rect
|
|
|
|
operation context is split into different sections in menu bar: modeling, sculpting, uv editing, shading, anim, etc
|
|
cam 3d orientation gizmo top right: can be dragged (orbit cam) or clicked (reposition)
|
|
rotation gizmo: anchor can be positioned within world
|
|
gizmo: will display always initial position while dragging, and tape distance so far
|
|
right floating icons can be dragged: cam orientation, cam panning, cam zooming, cam iso/dimetric
|
|
ctrl-z undo, ctrl-shift-z redo
|
|
#endif
|
|
|
|
bool is_hovering(vec4 rect, vec2 mouse) { // rect(x,y,x2,y2)
|
|
if( mouse.x < rect.x ) return 0;
|
|
if( mouse.x > rect.z ) return 0;
|
|
if( mouse.y < rect.y ) return 0;
|
|
if( mouse.y > rect.w ) return 0;
|
|
return 1;
|
|
}
|
|
vec4 editor_toolbar_drag; // xy mouse, z time
|
|
vec4 editor_toolbar_rect;
|
|
int editor_toolbar_hovered() {
|
|
return is_hovering(editor_toolbar_rect, vec2(input(MOUSE_X),input(MOUSE_Y)));
|
|
}
|
|
vec2 editor_toolbar_dragged() {
|
|
return vec2( editor_toolbar_drag.x, editor_toolbar_drag.y );
|
|
}
|
|
int editor_toolbar(int x, int y, int incw, int inch, const char *sym) {
|
|
array(uint32_t) codepoints = string32(sym);
|
|
if( incw < 0 ) return editor_toolbar(x + incw * (array_count(codepoints)-1), y, -incw, inch, sym);
|
|
if( inch < 0 ) return editor_toolbar(x, y + inch * (array_count(codepoints)-1), incw, -inch, sym);
|
|
|
|
int mx = input(MOUSE_X);
|
|
int my = input(MOUSE_Y);
|
|
int inc = maxi(incw, inch);
|
|
|
|
static int ox = 0, oy = 0, dragging = 0; // drag origin
|
|
|
|
editor_toolbar_rect = vec4(x,y,x + (incw ? incw * array_count(codepoints) : inch), y + (inch ? inch * array_count(codepoints) : incw) );
|
|
int oo = is_hovering(editor_toolbar_rect, vec2(ox,oy));
|
|
|
|
int ix = x, iy = y;
|
|
for each_array(codepoints, uint32_t, g) {
|
|
int selected = oo ? is_hovering(vec4(ix,iy,ix+inc,iy+inc),vec2(ox,oy)) : 0;
|
|
int hovering = dragging ? 0 : is_hovering(vec4(ix,iy,ix+inc,iy+inc), vec2(mx,my));
|
|
const char *str8 = codepoint_to_utf8(g);
|
|
editor_glyphs(ix + inc/8, iy + inc/3 + 2, selected || hovering ? FONT_COLOR1 FONT_H1 : FONT_COLOR2 FONT_H1, str8);
|
|
ix += incw;
|
|
iy += inch;
|
|
}
|
|
// debug:
|
|
// ddraw_push_2d();
|
|
// ddraw_aabb(vec3(editor_toolbar_rect.x,editor_toolbar_rect.y,0),vec3(editor_toolbar_rect.z,editor_toolbar_rect.w,0));
|
|
// ddraw_pop_2d();
|
|
if( 1 ) // is_hovering(editor_toolbar_rect, vec2(mx,my)) )
|
|
{
|
|
if( input_down(MOUSE_L) && editor_toolbar_hovered() ) {
|
|
window_cursor_shape(0);
|
|
editor_toolbar_drag = vec4(0,0, mx,my);
|
|
ox = mx, oy = my, dragging = 1;
|
|
int mcx = ((ox - x) / inc) + 1, mcy = ((oy - y) / inc) + 1; // mouse cells
|
|
return incw ? -mcx : -mcy;
|
|
}
|
|
if( input(MOUSE_L) && dragging ) {
|
|
int mcx = ((ox - x) / inc) + 1, mcy = ((oy - y) / inc) + 1; // mouse cells
|
|
editor_toolbar_drag.x = mx - editor_toolbar_drag.z;
|
|
editor_toolbar_drag.y = my - editor_toolbar_drag.w;
|
|
API void editor_setmouse(int x, int y);
|
|
editor_setmouse(ox, oy);
|
|
editor_toolbar_drag.z = ox;
|
|
editor_toolbar_drag.w = oy;
|
|
return incw ? -mcx : -mcy;
|
|
}
|
|
if( input_up(MOUSE_L) && dragging ) {
|
|
int mcx = ((ox - x) / inc) + 1, mcy = ((oy - y) / inc) + 1; // mouse cells
|
|
window_cursor_shape(CURSOR_SW_AUTO);
|
|
ox = oy = 0, dragging = 0;
|
|
return incw ? mcx : mcy;
|
|
}
|
|
}
|
|
editor_toolbar_drag = vec4(0,0,0,0);
|
|
return 0;
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// 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_glyphs(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_glyphs(obj->pos.x,obj->pos.y,0,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_glyphs(obj->pos.x+16,obj->pos.y-16,0,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 * active);
|
|
camera_moveby(&cam, wasdecq);
|
|
camera_fps(&cam, mouse.x,mouse.y);
|
|
|
|
// draw world
|
|
ddraw_ontop_push(0);
|
|
ddraw_grid(0); // 1+10+100
|
|
ddraw_grid(1000);
|
|
ddraw_ontop_pop();
|
|
ddraw_flush();
|
|
|
|
// draw game
|
|
kid_draw(root);
|
|
kid_draw(o1);
|
|
kid_draw(o2);
|
|
}
|
|
|
|
int main(){
|
|
argvadd("--cook-on-demand");
|
|
|
|
// 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);
|
|
window_create( flag("--transparent") ? 101 : 80, WINDOW_MSAA4 | (flag("--windowed") ? 0 : WINDOW_BORDERLESS));
|
|
window_icon("scale-ruler-icon.png");
|
|
|
|
while( window_swap() ) {
|
|
editor_frame(game);
|
|
editor_gizmos(2);
|
|
|
|
camera_t *cam = camera_get_active();
|
|
|
|
int choice1 = editor_toolbar(window_width()-32, ui_has_menubar() ? 34 : 0, 0, 32,
|
|
ICON_MD_VISIBILITY
|
|
ICON_MD_360 // ICON_MDI_ORBIT
|
|
ICON_MD_LOUPE // ZOOM_OUT_MAP // ICON_MD_ZOOM_IN
|
|
ICON_MD_GRID_ON ); // ICON_MDI_GRID );
|
|
int choice2 = editor_toolbar(window_width()-32*2, ui_has_menubar() ? 34 : 0, -32, 0, ICON_MD_SQUARE_FOOT );
|
|
|
|
if( choice1 > 0 ) { // clicked[>0]
|
|
camera_t *cam = camera_get_active();
|
|
if( choice1 == 4 ) cam->orthographic ^= 1, camera_fps(cam, 0, 0);
|
|
}
|
|
if( choice1 < 0 ) { // dragged[<0]
|
|
vec2 mouse_sensitivity = vec2(0.1, -0.1); // sensitivity + polarity
|
|
vec2 drag = mul2( editor_toolbar_dragged(), mouse_sensitivity );
|
|
if( choice1 == -1 ) camera_fps(cam, drag.x, drag.y );
|
|
if( choice1 == -2 ) camera_orbit(cam, drag.x, drag.y, 0); //len3(cam->position) );
|
|
if( choice1 == -3 ) camera_fov(cam, cam->fov += drag.y - drag.x);
|
|
}
|
|
|
|
// font demo
|
|
font_print(va(FONT_BOTTOM FONT_RIGHT FONT_H6 "(CAM: %5.2f,%5.2f,%5.2f)", cam->position.x, cam->position.y, cam->position.z));
|
|
}
|
|
}
|