sync fwk
parent
ceae5e2fe0
commit
e807e4bef8
10
MAKE.bat
10
MAKE.bat
|
@ -75,6 +75,13 @@ if "%1"=="cook" (
|
|||
|
||||
exit /b
|
||||
)
|
||||
if "%1"=="build_cook" (
|
||||
pushd tools
|
||||
cl cook.c -I..\engine /openmp /Os /Ox /O2 /Oy /MT /DNDEBUG /GL /GF /Gw /arch:AVX2 /link /OPT:ICF /LTCG
|
||||
popd
|
||||
|
||||
exit /b
|
||||
)
|
||||
rem generate bindings
|
||||
if "%1"=="bind" (
|
||||
rem luajit
|
||||
|
@ -324,7 +331,7 @@ if "%1"=="fwk_prep" (
|
|||
xcopy /y "engine\split\3rd_*" "_fwk\engine\split"
|
||||
xcopy /y "engine\art\shaders\*" "_fwk\engine\art\shaders"
|
||||
xcopy /y "demos" "_fwk\demos"
|
||||
xcopy /y "engine\editor.c" "_fwk\engine\editor.c"
|
||||
copy /y "engine\editor.c" "_fwk\engine\editor.c"
|
||||
rem xcopy /y/E "tools "_fwk\tools"
|
||||
for %%f in ("engine\split\v4k*") do (
|
||||
set "filename=%%~nf"
|
||||
|
@ -371,6 +378,7 @@ if "%1"=="back" (
|
|||
xcopy /y "_fwk" "."
|
||||
xcopy /y "_fwk\engine\split\3rd_*" "engine\split"
|
||||
xcopy /y "_fwk\engine\art\shaders\*" "engine\art\shaders"
|
||||
del "demos\*.c"
|
||||
xcopy /y "_fwk\demos" "demos"
|
||||
xcopy /y "_fwk\engine\editor.c" "engine\editor.c"
|
||||
tools\fwkren.exe "engine\editor.c" to
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#include "v4k.h" // Minimal C sample
|
||||
|
||||
int main() {
|
||||
window_create(75.0, 0); // 75% size, no extra flags
|
||||
|
||||
while( window_swap() && !input(KEY_ESC) ) { // game loop
|
||||
puts("hello V4K from C!");
|
||||
}
|
|
@ -1,86 +0,0 @@
|
|||
// hello ui: config, window, system, ui, video
|
||||
// - rlyeh, public domain.
|
||||
//
|
||||
// Compile with:
|
||||
// `make demos\01-ui.c` (windows)
|
||||
// `sh MAKE.bat demos/01-ui.c` (linux, osx)
|
||||
|
||||
#include "v4k.h"
|
||||
|
||||
int main() {
|
||||
float app_volume = 1.00f;
|
||||
unsigned app_size = flag("--fullscreen") ? 100 : 75;
|
||||
unsigned app_flags = flag("--msaa") ? WINDOW_MSAA4 : 0;
|
||||
unsigned app_target_fps = optioni("--fps", 60); // --fps=30, --fps=45, etc. defaults to 60.
|
||||
|
||||
// window api (fullscreen or 75% sized, optional MSAA flags)
|
||||
window_create(app_size, app_flags);
|
||||
window_title(__FILE__);
|
||||
window_fps_lock(app_target_fps);
|
||||
|
||||
// load video
|
||||
video_t *v = video( "pexels-pachon-in-motion-17486489.mp4", VIDEO_RGB | VIDEO_LOOP );
|
||||
|
||||
// app loop
|
||||
while( window_swap() ) {
|
||||
// input controls
|
||||
if( input(KEY_ESC) ) break;
|
||||
|
||||
// profile api
|
||||
texture_t *textures;
|
||||
profile( "Video decoder" ) {
|
||||
// video api: decode frame and get associated textures (audio is sent to audiomixer automatically)
|
||||
textures = video_decode( v );
|
||||
// fullscreen video
|
||||
// if(video_is_rgb(v)) fullscreen_quad_rgb( textures[0], 1.3f );
|
||||
// else fullscreen_quad_ycbcr( textures, 1.3f );
|
||||
}
|
||||
|
||||
// create menubar on top
|
||||
int choice1 = ui_menu("File;Shell;Exit");
|
||||
int choice2 = ui_menu("Help;About");
|
||||
if( choice1 == 1 ) system(ifdef(win32, "start \"\" cmd", ifdef(osx, "open sh", "xdg-open sh")));
|
||||
if( choice1 == 2 ) exit(0);
|
||||
|
||||
// showcase a few ui widgets
|
||||
ui_demo(0);
|
||||
|
||||
// create ui panel
|
||||
if( ui_panel("myPanel", PANEL_OPEN) ) {
|
||||
// Print some numbers
|
||||
ui_section("Stats");
|
||||
ui_label2("FPS", va("%5.2f", window_fps()));
|
||||
ui_separator();
|
||||
|
||||
// add some buttons
|
||||
ui_section("Buttons");
|
||||
if( ui_button("Screenshot") ) window_screenshot(__FILE__ ".png"), ui_notify(0,ICON_MD_WARNING "Screenshot");
|
||||
if( ui_button("Record Video") ) window_record(__FILE__ ".mp4"), ui_notify(0,ICON_MD_WARNING "Recoding video");
|
||||
if( ui_button("Toggle fullscreen") ) window_fullscreen( !window_has_fullscreen() );
|
||||
ui_separator();
|
||||
|
||||
// some more video controls
|
||||
ui_section("Video");
|
||||
if( ui_button("Rewind") ) video_seek(v, video_position(v) - 3);
|
||||
if( ui_button("Pause") ) video_pause(v, video_is_paused(v) ^ 1);
|
||||
if( ui_button("Forward") ) video_seek(v, video_position(v) + 3);
|
||||
if( ui_slider2("Volume", &app_volume, va("%.2f", app_volume))) audio_volume_master(app_volume);
|
||||
|
||||
// end of panel. must be enclosed within same if() branch.
|
||||
ui_panel_end();
|
||||
}
|
||||
|
||||
// create window
|
||||
static int open = 1;
|
||||
if( ui_window("myWindow", &open) ) {
|
||||
// present decoded texture in a widget, without any label (NULL)
|
||||
ui_texture( NULL, textures[0] );
|
||||
// end of window. must be enclosed within same if() branch.
|
||||
ui_window_end();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// this demo supersedes following old sources:
|
||||
// https://github.com/r-lyeh/V4K/blob/45e34d7890b2b8fe1f4994f4b76e496280d83cb6/demos/00-hello.c
|
||||
// https://github.com/r-lyeh/V4K/blob/45e34d7890b2b8fe1f4994f4b76e496280d83cb6/demos/00-video.c
|
|
@ -1,218 +0,0 @@
|
|||
// sprite routines
|
||||
// - rlyeh,
|
||||
//
|
||||
// credits: original lovely demo by rxi (MIT License).
|
||||
// see https://github.com/rxi/autobatch/tree/master/demo/cats
|
||||
|
||||
#include "v4k.h"
|
||||
|
||||
texture_t kids, catImage, shadowImage, inputs;
|
||||
int NUM_SPRITES = 100, NUM_SPRITES_CHANGED = 1;
|
||||
|
||||
typedef struct Cat {
|
||||
int cat, flip;
|
||||
double x, y;
|
||||
double vx, vy;
|
||||
double animSpeed;
|
||||
double moveTimer;
|
||||
double elapsed;
|
||||
} Cat;
|
||||
|
||||
void demo_cats() {
|
||||
static array(Cat) cats = 0;
|
||||
|
||||
// init
|
||||
if( NUM_SPRITES_CHANGED ) {
|
||||
NUM_SPRITES_CHANGED = 0;
|
||||
|
||||
array_resize(cats, NUM_SPRITES); int i = 0;
|
||||
for each_array_ptr(cats, Cat, c) {
|
||||
randset(i++);
|
||||
c->x = randf() * window_width();
|
||||
c->y = randf() * window_height();
|
||||
c->vx = c->vy = 0;
|
||||
c->cat = randi(0, 4);
|
||||
c->flip = randf() < 0.5;
|
||||
c->animSpeed = 0.8 + randf() * 0.3;
|
||||
c->moveTimer = 0;
|
||||
c->elapsed = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// move
|
||||
const float dt = 1/120.f;
|
||||
const int appw = window_width(), apph = window_height();
|
||||
|
||||
enum { yscale = 1 };
|
||||
for( int i = 0; i < NUM_SPRITES; ++i ) {
|
||||
Cat *c = &cats[i];
|
||||
// Add velocity to position //and wrap to screen
|
||||
c->x += yscale * c->vx * dt; // % ;
|
||||
c->y += yscale * c->vy * dt; // % (int)window_height();
|
||||
if( c->x < 0 ) c->x += appw; else if( c->x > appw ) c->x -= appw;
|
||||
if( c->y < 0 ) c->y += apph; else if( c->y > apph ) c->y -= apph;
|
||||
// Faster animation if walking
|
||||
int boost = c->vx == 0 && c->vy == 0 ? 1 : 3;
|
||||
// Update elapsed time
|
||||
c->elapsed += dt * boost;
|
||||
// Update move timer -- if we hit zero then change or zero velocity
|
||||
c->moveTimer -= dt * boost;
|
||||
if (c->moveTimer < 0) {
|
||||
if (randf() < .2) {
|
||||
c->vx = (randf() * 2 - 1) * 30 * 2;
|
||||
c->vy = (randf() * 2 - 1) * 15 * 2;
|
||||
c->flip = c->vx < 0;
|
||||
} else {
|
||||
c->vx = c->vy = 0;
|
||||
}
|
||||
c->moveTimer = 1 + randf() * 5;
|
||||
}
|
||||
}
|
||||
|
||||
// render
|
||||
uint32_t white = rgba(255,255,255,255);
|
||||
uint32_t alpha = rgba(255,255,255,255*0.6);
|
||||
for( int i = 0; i < NUM_SPRITES; ++i ) {
|
||||
Cat *c = &cats[i];
|
||||
// Get current animation frame (8x4 tilesheet)
|
||||
double e = c->elapsed * c->animSpeed;
|
||||
double frame_num = c->cat * 8 + floor( ((int)(e * 8)) % 4 );
|
||||
frame_num = c->vx != 0 || c->vy != 0 ? frame_num + 4 : frame_num;
|
||||
// Get x scale based on flip flag
|
||||
int xscale = yscale * (c->flip ? -1 : 1);
|
||||
// Draw
|
||||
float angle = 0; //fmod(window_time()*360/5, 360);
|
||||
float scale[2] = { 2*xscale, 2*yscale };
|
||||
float position[3] = { c->x,c->y,c->y }, no_offset[2] = {0,0}, spritesheet[3] = { frame_num,8,4 };
|
||||
sprite_sheet(catImage,
|
||||
spritesheet, // frame_number in a 8x4 spritesheet
|
||||
position, angle, // position(x,y,depth: sort by Y), angle
|
||||
no_offset, scale, // offset(x,y), scale(x,y)
|
||||
0,white,0 // is_additive, tint color, resolution independant
|
||||
);
|
||||
float position_neg_sort[3] = { c->x,c->y,-c->y }, offset[2] = {-1,5}, no_spritesheet[3] = {0,0,0};
|
||||
sprite_sheet(shadowImage,
|
||||
no_spritesheet, // no frame_number (0x0 spritesheet)
|
||||
position_neg_sort, angle, // position(x,y,depth: sort by Y), angle
|
||||
offset, scale, // offset(x,y), scale(x,y)
|
||||
0,alpha,0 // is_additive, tint color, resolution independant
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void demo_kids() {
|
||||
static int angle; //++angle;
|
||||
static int *x, *y, *v;
|
||||
|
||||
// init
|
||||
if( NUM_SPRITES_CHANGED ) {
|
||||
NUM_SPRITES_CHANGED = 0;
|
||||
|
||||
y = (int*)REALLOC(y, 0 );
|
||||
x = (int*)REALLOC(x, NUM_SPRITES * sizeof(int) );
|
||||
y = (int*)REALLOC(y, NUM_SPRITES * sizeof(int) );
|
||||
v = (int*)REALLOC(v, NUM_SPRITES * sizeof(int) );
|
||||
for( int i = 0; i < NUM_SPRITES; ++i ) {
|
||||
randset(i);
|
||||
x[i] = randi(0, window_width());
|
||||
y[i] = randi(0, window_height());
|
||||
v[i] = randi(1, 3);
|
||||
}
|
||||
}
|
||||
|
||||
// config
|
||||
const int appw = window_width(), apph = window_height();
|
||||
|
||||
// move & render
|
||||
for( int i = 0; i < NUM_SPRITES; ++i ) {
|
||||
y[i] = (y[i] + v[i]) % (apph + 128);
|
||||
int col = ((x[i] / 10) % 4); // 4x4 tilesheet
|
||||
int row = ((y[i] / 10) % 4);
|
||||
int num_frame = col * 4 + row;
|
||||
float position[3] = {x[i],y[i],y[i]}, offset[2]={0,0}, scale[2]={1,1}, spritesheet[3]={num_frame,4,4};
|
||||
sprite_sheet(kids,
|
||||
spritesheet, // num_frame in a 4x4 spritesheet
|
||||
position, angle, // position(x,y,depth: sort by Y), angle
|
||||
offset, scale, // offset(x,y), scale(x,y)
|
||||
0, ~0u, 0 // is_additive, tint color, resolution independant
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
window_create(75.f, 0);
|
||||
window_title("V4K - Sprite");
|
||||
window_color( SILVER );
|
||||
|
||||
// options
|
||||
int do_cats = 1;
|
||||
NUM_SPRITES = optioni("--num_sprites,-N", NUM_SPRITES);
|
||||
if(do_cats) NUM_SPRITES/=2; // cat-sprite+cat-shadow == 2 sprites
|
||||
|
||||
// load sprites and sheets
|
||||
kids = texture( "spriteSheetExample.png", TEXTURE_LINEAR );
|
||||
catImage = texture( "cat.png", TEXTURE_LINEAR ); //
|
||||
shadowImage = texture( "cat-shadow.png", TEXTURE_LINEAR );
|
||||
inputs = texture( "prompts_tilemap_34x24_16x16x1.png", TEXTURE_LINEAR );
|
||||
|
||||
// load all fx files, including subdirs
|
||||
fx_load("fx**.fs");
|
||||
|
||||
// init camera (x,y) (z = zoom)
|
||||
camera_t cam = camera();
|
||||
cam.position = vec3(window_width()/2,window_height()/2,1);
|
||||
camera_enable(&cam);
|
||||
|
||||
while(window_swap()) {
|
||||
if( input(KEY_F5)) window_reload();
|
||||
if( input(KEY_F11)) window_fullscreen( window_has_fullscreen() ^ 1);
|
||||
if( input(KEY_ESC) ) break;
|
||||
|
||||
// camera panning (x,y) & zooming (z)
|
||||
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
|
||||
}
|
||||
|
||||
// apply post-fxs from here
|
||||
fx_begin();
|
||||
|
||||
profile("Sprite batching") {
|
||||
if(do_cats) demo_cats(); else demo_kids();
|
||||
}
|
||||
|
||||
// flush retained renderer, so we ensure the fbos are up to date before fx_end()
|
||||
profile("Sprite flushing") {
|
||||
sprite_flush();
|
||||
}
|
||||
|
||||
// post-fxs end here
|
||||
fx_end();
|
||||
|
||||
// draw pixel-art hud, 16x16 ui element, scaled and positioned in resolution-independant way
|
||||
{
|
||||
vec3 old_pos = camera_get_active()->position;
|
||||
|
||||
sprite_flush();
|
||||
camera_get_active()->position = vec3(window_width()/2,window_height()/2,1);
|
||||
|
||||
float zindex = window_height(); // large number, on top
|
||||
float spritesheet[3] = {17,34,24}, offset[2] = {0, - 2*absf(sin(window_time()*5))}; // sprite cell and animation
|
||||
float scale[2] = {3, 3}, tile_w = 16 * scale[0], tile_h = 16 * scale[1]; // scaling
|
||||
float position[3] = {window_width() - tile_w, window_height() - tile_h, zindex }; // position in screen-coordinates
|
||||
sprite_sheet(inputs, spritesheet, position, 0/*rotation*/, offset, scale, false/*is_additive*/, WHITE/*color*/, false/*resolution_independant*/);
|
||||
|
||||
sprite_flush();
|
||||
camera_get_active()->position = old_pos;
|
||||
}
|
||||
|
||||
if( ui_panel("Sprite", 0) ) {
|
||||
const char *labels[] = {"Kids","Cats"};
|
||||
if( ui_list("Sprite type", labels, countof(labels), &do_cats) ) NUM_SPRITES_CHANGED = 1;
|
||||
if( ui_int("Number of Sprites", &NUM_SPRITES) ) NUM_SPRITES_CHANGED = 1;
|
||||
if( ui_clampf("Zoom", &cam.position.z, 0.1, 10));
|
||||
ui_panel_end();
|
||||
}
|
||||
}
|
||||
}
|
234
demos/04-lod.c
234
demos/04-lod.c
File diff suppressed because one or more lines are too long
216
demos/05-scene.c
216
demos/05-scene.c
|
@ -1,216 +0,0 @@
|
|||
// scene demo
|
||||
// - rlyeh, public domain
|
||||
|
||||
#include "v4k.h"
|
||||
|
||||
int main() {
|
||||
// options
|
||||
bool do_twosided = 1;
|
||||
bool do_wireframe = 0;
|
||||
bool do_billboard_x = 1, do_billboard_y = 1, do_billboard_z = 1;
|
||||
|
||||
// window (80% sized, MSAA x4 flag)
|
||||
window_create(80, WINDOW_MSAA4);
|
||||
window_title(__FILE__);
|
||||
|
||||
// load all postfx files in all subdirs
|
||||
fx_load("fx**.fs");
|
||||
|
||||
// scene loading
|
||||
#define SCENE(...) #__VA_ARGS__
|
||||
const char *my_scene = SCENE([
|
||||
{
|
||||
skybox: 'cubemaps/stardust/',
|
||||
},
|
||||
{
|
||||
position:[-5.0,-2.0,2.0],
|
||||
rotation: [90.0,0.0,180.0],
|
||||
scale:0.20,
|
||||
//anchor/pivot:[],
|
||||
// vertex:'p3 t2',
|
||||
mesh:'models/witch/witch.obj',
|
||||
texture:'models/witch/witch_diffuse.tga.png',
|
||||
// swapzy:true,
|
||||
flipuv:false,
|
||||
},
|
||||
{
|
||||
position:[-5.0,-2.0,2.0],
|
||||
rotation: [90.0,0.0,180.0],
|
||||
scale:2.20,
|
||||
//anchor/pivot:[],
|
||||
// vertex:'p3 t2',
|
||||
mesh:'models/witch/witch_object.obj',
|
||||
texture:'models/witch/witch_object_diffuse.tga.png',
|
||||
// swapzy:true,
|
||||
flipuv:false,
|
||||
},
|
||||
]);
|
||||
int num_spawned = scene_merge(my_scene);
|
||||
object_t *obj1 = scene_index(0);
|
||||
object_t *obj2 = scene_index(1);
|
||||
|
||||
// manual spawn & loading
|
||||
model_t m1 = model("kgirl/kgirls01.fbx", 0); //MODEL_NO_ANIMS);
|
||||
texture_t t1 = texture("kgirl/g01_texture.png", TEXTURE_RGB);
|
||||
object_t* obj3 = scene_spawn();
|
||||
object_model(obj3, m1);
|
||||
object_diffuse(obj3, t1);
|
||||
object_scale(obj3, vec3(3,3,3));
|
||||
object_move(obj3, vec3(-10,0,-10));
|
||||
object_pivot(obj3, vec3(-90+180,180,0));
|
||||
|
||||
// camera
|
||||
camera_t cam = camera();
|
||||
|
||||
// demo loop
|
||||
while (window_swap())
|
||||
{
|
||||
// input
|
||||
if( input_down(KEY_ESC) ) break;
|
||||
|
||||
// fps camera
|
||||
bool active = ui_active() || ui_hover() || gizmo_active() ? false : input(MOUSE_L) || 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);
|
||||
|
||||
// queue model scale bounces
|
||||
float t = fmod(window_time(), 0.3) / 0.3;
|
||||
float s = 0.01f * ease_ping_pong(t, EASE_IN|EASE_CUBIC,EASE_OUT|EASE_CUBIC);
|
||||
object_scale(obj1, vec3(0.20f - s,0.20f + s,0.20f - s));
|
||||
object_scale(obj2, vec3(0.20f - s,0.20f + s,0.20f - s));
|
||||
|
||||
// queue model billboard
|
||||
object_billboard(obj1, (do_billboard_x << 2)|(do_billboard_y << 1)|(do_billboard_z << 0));
|
||||
object_billboard(obj2, (do_billboard_x << 2)|(do_billboard_y << 1)|(do_billboard_z << 0));
|
||||
|
||||
// queue model rotation
|
||||
//object_rotate(obj3, vec3(0,1*window_time() * 20,0));
|
||||
|
||||
// flush render scene (background objects: skybox)
|
||||
profile("Scene background") {
|
||||
scene_render(SCENE_BACKGROUND);
|
||||
}
|
||||
|
||||
// queue debug drawcalls
|
||||
profile("Debugdraw") {
|
||||
ddraw_ground(0);
|
||||
ddraw_color(YELLOW);
|
||||
ddraw_text(vec3(+1,+1,-1), 0.04f, va("(%f,%f,%f)", cam.position.x,cam.position.y,cam.position.z));
|
||||
ddraw_color(YELLOW);
|
||||
ddraw_flush();
|
||||
}
|
||||
|
||||
// apply post-fxs from here
|
||||
fx_begin();
|
||||
|
||||
// render scene (foreground objects) with post-effects
|
||||
profile("Scene foreground") {
|
||||
int scene_flags = 0;
|
||||
scene_flags |= do_wireframe ? SCENE_WIREFRAME : 0;
|
||||
scene_flags |= do_twosided ? 0 : SCENE_CULLFACE;
|
||||
scene_render(SCENE_FOREGROUND | scene_flags);
|
||||
}
|
||||
|
||||
profile("Skeletal update") if(!window_has_pause()) {
|
||||
float delta = window_delta() * 30 ; // 30fps anim
|
||||
m1.curframe = model_animate(m1, m1.curframe + delta);
|
||||
|
||||
ddraw_text(vec3(-10,5,-10), 0.05, va("Frame: %.1f", m1.curframe));
|
||||
}
|
||||
|
||||
// post-fxs end here
|
||||
fx_end();
|
||||
|
||||
// queue ui
|
||||
if( ui_panel("Scene", 0)) {
|
||||
if(ui_toggle("Billboard X", &do_billboard_x)) {}
|
||||
if(ui_toggle("Billboard Y", &do_billboard_y)) {}
|
||||
if(ui_toggle("Billboard Z", &do_billboard_z)) {}
|
||||
if(ui_separator()) {}
|
||||
if(ui_bool("Wireframe", &do_wireframe)) {}
|
||||
if(ui_bool("Two sided", &do_twosided)) {}
|
||||
ui_panel_end();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// material demo
|
||||
// - rlyeh, public domain
|
||||
//
|
||||
// @todo: object_print(obj, "");
|
||||
|
||||
// create camera
|
||||
camera_t cam = camera();
|
||||
// load video, RGB texture, no audio
|
||||
video_t *v = video( "pexels-pachon-in-motion-17486489.mp4", VIDEO_RGB | VIDEO_NO_AUDIO | VIDEO_LOOP ); video_seek(v, 30);
|
||||
// load texture
|
||||
texture_t t1 = texture("kgirl/g01_texture.png", TEXTURE_RGB);
|
||||
texture_t t2 = texture("matcaps/material3", 0);
|
||||
// load model
|
||||
model_t m1 = model("suzanne.obj", MODEL_NO_ANIMATIONS);
|
||||
model_t m2 = model("suzanne.obj", MODEL_NO_ANIMATIONS|MODEL_MATCAPS);
|
||||
|
||||
// spawn object1 (diffuse)
|
||||
object_t* obj1 = scene_spawn();
|
||||
object_model(obj1, m1);
|
||||
object_diffuse(obj1, t1);
|
||||
object_scale(obj1, vec3(3,3,3));
|
||||
object_move(obj1, vec3(-10+5*0,0,-10));
|
||||
object_pivot(obj1, vec3(0,90,0));
|
||||
|
||||
// spawn object2 (matcap)
|
||||
object_t* obj2 = scene_spawn();
|
||||
object_model(obj2, m2);
|
||||
object_diffuse(obj2, t2);
|
||||
object_scale(obj2, vec3(3,3,3));
|
||||
object_move(obj2, vec3(-10+5*2,0,-10));
|
||||
object_pivot(obj2, vec3(0,90,0));
|
||||
|
||||
// spawn object2 (video)
|
||||
object_t* obj3 = scene_spawn();
|
||||
object_model(obj3, m1);
|
||||
object_diffuse(obj3, video_textures(v)[0]);
|
||||
object_scale(obj3, vec3(3,3,3));
|
||||
object_move(obj3, vec3(-10+5*1,0,-10));
|
||||
object_pivot(obj3, vec3(0,90,0));
|
||||
|
||||
// @todo: add shadertoy material
|
||||
static model_t cube; do_once cube = model("cube.obj", 0);
|
||||
static shadertoy_t s; do_once s = shadertoy("shadertoys/4ttGWM.fs", 256);
|
||||
model_set_texture(cube, shadertoy_render(&s, window_delta())->tx);
|
||||
model_render(cube, cam.proj, cam.view, cube.pivot, 0);
|
||||
|
||||
while(window_swap() && !input(KEY_ESC)) {
|
||||
// draw environment
|
||||
viewport_color( RGB3(22,22,32) );
|
||||
ddraw_grid(0);
|
||||
ddraw_flush();
|
||||
|
||||
// update video
|
||||
video_decode( v );
|
||||
|
||||
// draw scene
|
||||
scene_render(SCENE_FOREGROUND);
|
||||
}
|
||||
|
||||
// load static scene
|
||||
// model_t sponza = model("sponza.obj", MODEL_MATCAPS);
|
||||
// model_set_texture(sponza, texture("matcaps/normals", 0));
|
||||
// translation44(sponza.pivot, 0,-1,0);
|
||||
// rotate44(sponza.pivot, -90,1,0,0);
|
||||
// scale44(sponza.pivot, 10,10,10);
|
||||
// model_render(sponza, cam.proj, cam.view, sponza.pivot, 0);
|
||||
|
||||
// this demo supersedes following old sources:
|
||||
// https://github.com/r-lyeh/V4K/blob/45e34d7890b2b8fe1f4994f4b76e496280d83cb6/demos/00-material.c
|
||||
// https://github.com/r-lyeh/V4K/blob/45e34d7890b2b8fe1f4994f4b76e496280d83cb6/demos/00-shadertoy.c
|
||||
|
||||
#endif
|
|
@ -1,280 +0,0 @@
|
|||
// full controller demo: anims, input, collide; @todo: gamepad, input opts, easing on hits, notify on gamepad connect
|
||||
// - rlyeh, public domain.
|
||||
//
|
||||
// Compile with:
|
||||
// `make demos\99-controller.c` (windows)
|
||||
// `sh MAKE.bat demos/99-controller.c` (linux, osx)
|
||||
|
||||
#include "v4k.h"
|
||||
|
||||
int main() {
|
||||
// 75% window, MSAAx2 flag
|
||||
window_create(75, WINDOW_MSAA2);
|
||||
|
||||
// fx: load all post fx files in all subdirs
|
||||
fx_load("fx**.fs");
|
||||
|
||||
// create a camera
|
||||
camera_t cam = camera();
|
||||
camera_enable(&cam);
|
||||
|
||||
// config 3d model #1
|
||||
model_t witch = model("witch/witch.obj", 0);
|
||||
model_set_texture(witch, texture("witch/witch_diffuse.tga.png", 0));
|
||||
mat44 witch_pivot; vec3 witch_p = {-5,0,-5}, witch_r={-180,180,0}, witch_s={0.1,-0.1,0.1};
|
||||
|
||||
// config 3d model #2
|
||||
model_t girl = model("kgirl/kgirls01.fbx", 0);
|
||||
mat44 girl_pivot; vec3 girl_p = {0,0,0}, girl_r = {270,0,0}, girl_s = {2,2,2};
|
||||
|
||||
// skybox
|
||||
skybox_t sky = skybox("cubemaps/stardust", 0);
|
||||
|
||||
// BGM
|
||||
audio_play( audio_stream("waterworld-map.fur"), 0 );
|
||||
|
||||
// editor loop
|
||||
while( window_swap() ) {
|
||||
|
||||
// game camera
|
||||
profile("Game.Camera") {
|
||||
camera_t *cam = camera_get_active();
|
||||
|
||||
static vec3 source;
|
||||
do_once source = cam->position;
|
||||
|
||||
vec3 target = add3(girl_p, vec3(0,10,0));
|
||||
target = add3(target, scale3(norm3(sub3(source, target)), 10.0));
|
||||
source = mix3(source, target, 1-0.99f);
|
||||
|
||||
camera_teleport(cam, source);
|
||||
camera_lookat(cam, vec3(girl_p.x,0,girl_p.z));
|
||||
}
|
||||
|
||||
// render begin (postfx)
|
||||
fx_begin();
|
||||
|
||||
// skybox
|
||||
skybox_render(&sky, cam.proj, cam.view);
|
||||
|
||||
// world
|
||||
ddraw_grid(0);
|
||||
ddraw_flush();
|
||||
|
||||
// models
|
||||
compose44(girl.pivot, girl_p, eulerq(girl_r), girl_s);
|
||||
model_render(girl, cam.proj, cam.view, girl.pivot, 0);
|
||||
|
||||
compose44(witch.pivot, witch_p, eulerq(witch_r), witch_s);
|
||||
model_render(witch, cam.proj, cam.view, witch.pivot, 0);
|
||||
|
||||
// render end (postfx)
|
||||
fx_end();
|
||||
|
||||
// input controllers
|
||||
|
||||
double GAME_JUMP_DOWN = input_down(KEY_Z);
|
||||
double GAME_FIRE_DOWN = input_down(KEY_X);
|
||||
double GAME_JUMP = input(KEY_Z);
|
||||
double GAME_FIRE = input(KEY_X);
|
||||
double GAME_LEFT = input(KEY_J);
|
||||
double GAME_RIGHT = input(KEY_L);
|
||||
double GAME_UP = input(KEY_I);
|
||||
double GAME_DOWN = input(KEY_K);
|
||||
double GAME_AXISX = input(KEY_L) - input(KEY_J);
|
||||
double GAME_AXISY = input(KEY_I) - input(KEY_K);
|
||||
|
||||
if( !input_anykey() ) {
|
||||
if( input(GAMEPAD_CONNECTED) ) {
|
||||
vec2 filtered_lpad = input_filter_deadzone(input2(GAMEPAD_LPAD), 0.15f /*15% deadzone*/);
|
||||
GAME_JUMP_DOWN = input_down(GAMEPAD_A);
|
||||
GAME_FIRE_DOWN = input_down(GAMEPAD_B) || input_down(GAMEPAD_X) || input_down(GAMEPAD_Y);
|
||||
GAME_JUMP = input(GAMEPAD_A);
|
||||
GAME_FIRE = input(GAMEPAD_B) || input(GAMEPAD_X) || input(GAMEPAD_Y);
|
||||
GAME_AXISX = filtered_lpad.x;
|
||||
GAME_AXISY = filtered_lpad.y;
|
||||
}
|
||||
}
|
||||
|
||||
// animation controllers
|
||||
|
||||
profile("Game.Animate scene") if( !window_has_pause() ) {
|
||||
float delta = window_delta() * 30; // 30fps anim
|
||||
|
||||
// animate girl
|
||||
girl.curframe = model_animate(girl, girl.curframe + delta);
|
||||
|
||||
// jump controller: jump duration=1.5s, jump height=6 units, anims (expo->circ)
|
||||
float jump_delta = 1.0;
|
||||
static double jump_timer = 0, jump_ss = 1.5, jump_h = 6;
|
||||
if( GAME_JUMP_DOWN ) if( jump_timer == 0 ) jump_timer = time_ss();
|
||||
jump_delta = clampf(time_ss() - jump_timer, 0, jump_ss) * (1.0/jump_ss);
|
||||
if( jump_delta >= 1 ) { jump_timer = 0; }
|
||||
float y = ease_ping_pong( jump_delta, EASE_OUT|EASE_EXPO, EASE_OUT|EASE_CIRC);
|
||||
girl_p.y = y * jump_h;
|
||||
|
||||
// punch controller
|
||||
float punch_delta = 1;
|
||||
if( jump_delta >= 1 ) {
|
||||
static vec3 origin;
|
||||
static double punch_timer = 0, punch_ss = 0.5;
|
||||
if( GAME_FIRE_DOWN ) if( punch_timer == 0 ) punch_timer = time_ss(), origin = girl_p;
|
||||
punch_delta = clampf(time_ss() - punch_timer, 0, punch_ss) * (1.0/punch_ss);
|
||||
if( punch_delta >= 1 ) { punch_timer = 0; }
|
||||
else {
|
||||
float x = ease_out_expo( punch_delta );
|
||||
vec3 fwd = rotate3q(vec3(0,0,1), eulerq(vec3(girl_r.x - 170,girl_r.y,girl_r.z)));
|
||||
vec3 mix = mix3(girl_p, add3(origin,scale3(fwd,x*2)), x);
|
||||
girl_p.x = mix.x, girl_p.z = mix.z;
|
||||
}
|
||||
}
|
||||
|
||||
int modern_controller = 1;
|
||||
int running = 0;
|
||||
|
||||
// girl controller
|
||||
|
||||
// locomotion vars
|
||||
float speed = 0.2f * delta;
|
||||
float yaw_boost = GAME_AXISY > 0 ? 1.0 : 1.75;
|
||||
if(punch_delta < 1) yaw_boost = 0.0; // if firing...
|
||||
else if(punch_delta <= 0.1) yaw_boost = 4.0; // unless initial punch chaining, extra yaw
|
||||
|
||||
// old fashioned locomotion controller (boat controller)
|
||||
if(!modern_controller) {
|
||||
running = GAME_AXISY > 0;
|
||||
|
||||
girl_r.x -= 170;
|
||||
quat q = eulerq(girl_r); // += custom.pivot
|
||||
vec3 rgt = rotate3q(vec3(1,0,0), q);
|
||||
vec3 up = rotate3q(vec3(0,1,0), q);
|
||||
vec3 fwd = rotate3q(vec3(0,0,1), q);
|
||||
vec3 dir = scale3(fwd, speed * GAME_AXISY * (GAME_AXISY > 0 ? 2.0 : 0.5));
|
||||
girl_r.x += speed * 20.0 * yaw_boost * GAME_AXISX; // yaw
|
||||
girl_p = add3(girl_p, dir);
|
||||
girl_r.x += 170;
|
||||
}
|
||||
|
||||
// modern locomotion controller (mario 3d)
|
||||
if(modern_controller) {
|
||||
running = GAME_AXISX != 0 || GAME_AXISY != 0;
|
||||
|
||||
camera_t *cam = camera_get_active();
|
||||
vec3 fwd = sub3(girl_p, cam->position); fwd.y = 0; fwd = norm3(fwd);
|
||||
vec3 rgt = norm3(cross3(fwd, vec3(0,1,0)));
|
||||
|
||||
// target
|
||||
vec3 dir = add3(
|
||||
scale3(fwd, GAME_AXISY),
|
||||
scale3(rgt, GAME_AXISX)
|
||||
); dir.y = 0; dir = norm3(dir);
|
||||
|
||||
// smoothing
|
||||
static vec3 olddir; do_once olddir = dir;
|
||||
dir = mix3(dir, olddir, 1 - (yaw_boost / 4.0) * 0.85);
|
||||
olddir = dir;
|
||||
|
||||
// vis
|
||||
// ddraw_arrow(girl_p, add3(girl_p,scale3(dir,10)));
|
||||
|
||||
// apply direction
|
||||
girl_p = add3(girl_p, scale3(dir, speed * 2));
|
||||
|
||||
// apply rotation
|
||||
{
|
||||
girl_r.x -= 170;
|
||||
quat q = eulerq(girl_r);
|
||||
vec3 fwdg = rotate3q(vec3(0,0,1), q);
|
||||
girl_r.x += 170;
|
||||
|
||||
//float cosAngle = dot3(dir,fwdg);
|
||||
//float angle = acos(cosAngle) * TO_DEG;
|
||||
float angle = TO_DEG * ( atan2(fwdg.z, fwdg.x) - atan2(dir.z, dir.x));
|
||||
|
||||
if( !isnan(angle) ) {
|
||||
girl_r.x -= angle;
|
||||
while(girl_r.x> 180) girl_r.x-=360;
|
||||
while(girl_r.x<-180) girl_r.x+=360;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// anim loops
|
||||
if( jump_delta < 1 ) { // jump/kick anim
|
||||
#if 0
|
||||
girl.curframe = clampf(girl.curframe, 184, 202);
|
||||
if( girl.curframe > 202-4 && GAME_FIRE_DOWN ) girl.curframe = 184+4;
|
||||
#else
|
||||
#define loopf(frame, min, max) (frame < min ? min : frame > max ? min + frame - max : frame)
|
||||
if(girl.curframe >= 203)
|
||||
girl.curframe = loopf(girl.curframe, 203, 220);
|
||||
else
|
||||
girl.curframe = clampf(girl.curframe, 184, 202);
|
||||
if( girl.curframe > 202-4 && girl.curframe < 208 && GAME_FIRE_DOWN ) girl.curframe = 203;
|
||||
#endif
|
||||
}
|
||||
else if( punch_delta < 1 ) { // punch anim
|
||||
girl.curframe = clampf(girl.curframe, 90, 101);
|
||||
if( girl.curframe > 101-6 && GAME_FIRE_DOWN ) girl.curframe = 101-6;
|
||||
}
|
||||
else if( running ) {
|
||||
// loop running anim
|
||||
if( girl.curframe < 65 ) girl.curframe = 65;
|
||||
if( girl.curframe > 85 ) girl.curframe = 65;
|
||||
}
|
||||
else { // loop idle anim
|
||||
if( girl.curframe > 59 ) girl.curframe = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Game collisions
|
||||
|
||||
profile("Game.collisions") {
|
||||
bool punching = girl.curframe >= 90 && girl.curframe < 101;
|
||||
bool air_kicking = girl.curframe >= 184 && girl.curframe < 202;
|
||||
bool jump_kicking = girl.curframe >= 203 && girl.curframe < 220;
|
||||
bool attacking = punching || air_kicking || jump_kicking;
|
||||
|
||||
if( attacking ) {
|
||||
aabb boxg = model_aabb(girl, girl_pivot);
|
||||
aabb boxw = model_aabb(witch, witch_pivot);
|
||||
#if 0 // halve aabb. ok
|
||||
{
|
||||
vec3 diag = sub3(boxg.max, boxg.min);
|
||||
vec3 halve = scale3(diag, 0.25);
|
||||
vec3 center = scale3(add3(boxg.min, boxg.max), 0.5);
|
||||
boxg.min = sub3(center, halve);
|
||||
boxg.max = add3(center, halve);
|
||||
}
|
||||
#endif
|
||||
hit* h = aabb_hit_aabb(boxg, boxw);
|
||||
if( h && GAME_FIRE ) {
|
||||
vec3 dir = norm3(sub3(witch_p, girl_p));
|
||||
witch_p = add3(witch_p, mul3(dir,vec3(1,0,1)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ui
|
||||
if( ui_panel("Input", 0) ) { // @todo: showcase input binding
|
||||
ui_section("Controllers");
|
||||
ui_label("Gamepad #1");
|
||||
ui_label("Keys I/J/K/L + Z/X");
|
||||
ui_panel_end();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// vec2 do_gamepad_polarity = vec2(+1,+1);
|
||||
// vec2 do_gamepad_sensitivity = vec2(0.1f,0.1f);
|
||||
// vec2 do_mouse_polarity = vec2(+1,-1);
|
||||
// vec2 do_mouse_sensitivity = vec2(0.2f,0.2f);
|
||||
// float do_gamepad_deadzone = 0.15f;//
|
||||
//
|
||||
// if(ui_separator()) {}
|
||||
// if(ui_slider("Gamepad deadzone", &do_gamepad_deadzone)) {}
|
||||
// if(ui_float2("Gamepad polarity", do_gamepad_polarity.v2)) {}
|
||||
// if(ui_float2("Gamepad sensitivity", do_gamepad_sensitivity.v2)) {}
|
||||
// if(ui_separator()) {}
|
||||
// if(ui_float2("Mouse polarity", do_mouse_polarity.v2)) {}
|
||||
// if(ui_float2("Mouse sensitivity", do_mouse_sensitivity.v2)) {}//
|
877
demos/99-nodes.c
877
demos/99-nodes.c
|
@ -1,877 +0,0 @@
|
|||
#define V4K_IMPLEMENTATION
|
||||
#include "joint/v4k.h"
|
||||
|
||||
/*
|
||||
A basic node-based UI built with Nuklear.
|
||||
Builds on the node editor example included in Nuklear v1.00, with the aim of
|
||||
being used as a prototype for implementing a functioning node editor.
|
||||
|
||||
Features:
|
||||
- Nodes of different types. Currently their implementations are #included in
|
||||
the main file, but they could easily be turned into eg. a plugin system.
|
||||
- Pins/pins of different types -- currently float values and colors.
|
||||
- Adding and removing nodes.
|
||||
- Linking nodes, with validation (one link per input, only link similar pins).
|
||||
- Detaching and moving links.
|
||||
- Evaluation of output values of connected nodes.
|
||||
- Memory management based on fixed size arrays for links and node pointers
|
||||
- Multiple node types
|
||||
- Multiple pin types
|
||||
- Linking between pins of the same type
|
||||
- Detaching and reattaching links
|
||||
- Getting value from linked node if pin is connected
|
||||
|
||||
Todo:
|
||||
- Complete pin types.
|
||||
- Allow dragging from output to input pin.
|
||||
- Cut link by CTRL+clicking input pin.
|
||||
- Cut link by drawing intersect line on a link.
|
||||
- Group elemnts together with mouse, or LSHIFT+clicking.
|
||||
- Drag groups.
|
||||
- DEL elements.
|
||||
- DEL groups.
|
||||
- CTRL-C/CTRL-V/CTRL-X elements.
|
||||
- CTRL-C/CTRL-V/CTRL-X groups.
|
||||
- CTRL-Z,CTRL-Y.
|
||||
- CTRL-N.
|
||||
- CTRL-L,CTRL-S.
|
||||
- CTRL-F.
|
||||
- CTRL-Wheel Zooming.
|
||||
- Allow to extend node types from Lua.
|
||||
|
||||
Extra todo:
|
||||
- Execution Flow (see: nk_stroke_triangle, nk_fill_triangle)
|
||||
- Complete missing nodes (see: nk_draw_image, nk_draw_text)
|
||||
- Right-click could visualize node/board diagram as Lua script.
|
||||
- Once that done, copy/pasting scripts should work within editor.
|
||||
|
||||
Sources:
|
||||
- https://github.com/Immediate-Mode-UI/Nuklear/pull/561
|
||||
- https://github.com/vurtun/nuklear/blob/master/demo/node_editor.c
|
||||
*/
|
||||
|
||||
typedef enum pin_type_t {
|
||||
type_flow,
|
||||
type_int,type_float,
|
||||
type_block,type_texture,type_image,
|
||||
type_color,
|
||||
/*
|
||||
type_bool,
|
||||
type_char, type_string,
|
||||
type_int2, type_int3, type_int4,
|
||||
type_float2, type_float3, type_float4,
|
||||
type_array, type_map,
|
||||
*/
|
||||
|
||||
type_total
|
||||
} pin_type_t;
|
||||
|
||||
struct node_pin {
|
||||
pin_type_t pin_type;
|
||||
nk_bool is_connected;
|
||||
struct node* connected_node;
|
||||
int connected_pin;
|
||||
};
|
||||
|
||||
struct node {
|
||||
int ID;
|
||||
char name[32];
|
||||
struct nk_rect bounds;
|
||||
int input_count;
|
||||
int output_count;
|
||||
struct node_pin *inputs;
|
||||
struct node_pin *outputs;
|
||||
struct {
|
||||
float in_padding_x;
|
||||
float in_padding_y;
|
||||
float in_spacing_y;
|
||||
float out_padding_x;
|
||||
float out_padding_y;
|
||||
float out_spacing_y;
|
||||
} pin_spacing; /* Maybe this should be called "node_layout" and include the bounds? */
|
||||
struct node *next; /* Z ordering only */
|
||||
struct node *prev; /* Z ordering only */
|
||||
|
||||
void* (*eval_func)(struct node*, int oIndex);
|
||||
void (*display_func)(struct nk_context*, struct node*);
|
||||
};
|
||||
|
||||
struct node_link {
|
||||
struct node* input_node;
|
||||
int input_pin;
|
||||
struct node* output_node;
|
||||
int output_pin;
|
||||
nk_bool is_active;
|
||||
};
|
||||
|
||||
struct node_linking {
|
||||
int active;
|
||||
struct node *node;
|
||||
int input_id;
|
||||
int input_pin;
|
||||
};
|
||||
|
||||
struct node_editor {
|
||||
int initialized;
|
||||
struct node *node_buf[32];
|
||||
struct node_link links[64];
|
||||
struct node *output_node;
|
||||
struct node *begin;
|
||||
struct node *end;
|
||||
int node_count;
|
||||
int link_count;
|
||||
struct nk_rect bounds;
|
||||
struct node *selected;
|
||||
int show_grid;
|
||||
struct nk_vec2 scrolling;
|
||||
struct node_linking linking;
|
||||
};
|
||||
|
||||
/* === PROTOTYPES === */
|
||||
/* The node implementations need these two functions. */
|
||||
/* These could/should go in a header file along with the node and node_pin structs and be #included in the node implementations */
|
||||
|
||||
struct node* node_editor_add(struct node_editor *editor, size_t nodeSize, const char *name, struct nk_rect bounds, int in_count, int out_count);
|
||||
void* node_editor_eval_connected(struct node *node, int input_pin_number);
|
||||
/* ================== */
|
||||
|
||||
/* === NODE TYPE IMPLEMENTATIONS === */
|
||||
|
||||
#define NODE_DEFAULT_ROW_HEIGHT 25
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------------------------------
|
||||
// #include "node_output.h"
|
||||
|
||||
struct node_type_output {
|
||||
struct node node;
|
||||
struct nk_colorf input_val;
|
||||
};
|
||||
|
||||
struct nk_colorf *node_output_get(struct node* node) {
|
||||
struct node_type_output *output_node = (struct node_type_output*)node;
|
||||
if (!node->inputs[0].is_connected) {
|
||||
struct nk_colorf black = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
output_node->input_val = black;
|
||||
}
|
||||
return &output_node->input_val;
|
||||
}
|
||||
|
||||
static void node_output_display(struct nk_context *ctx, struct node *node) {
|
||||
if (node->inputs[0].is_connected) {
|
||||
struct node_type_output *output_node = (struct node_type_output*)node;
|
||||
output_node->input_val = *(struct nk_colorf*)node_editor_eval_connected(node, 0);
|
||||
nk_layout_row_dynamic(ctx, 60, 1);
|
||||
nk_button_color(ctx, nk_rgba_cf(output_node->input_val));
|
||||
}
|
||||
}
|
||||
|
||||
struct node* node_output_create(struct node_editor *editor, struct nk_vec2 position) {
|
||||
struct node_type_output *output_node = (struct node_type_output*)node_editor_add(editor, sizeof(struct node_type_output), "Output", nk_rect(position.x, position.y, 100, 100), 1, 0);
|
||||
if (output_node){
|
||||
output_node->node.inputs[0].pin_type = type_color;
|
||||
output_node->node.display_func = node_output_display;
|
||||
}
|
||||
return (struct node*)output_node;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------------------
|
||||
// #include "node_float.h"
|
||||
|
||||
struct node_type_float {
|
||||
struct node node;
|
||||
float output_val;
|
||||
};
|
||||
|
||||
static float *node_float_eval(struct node* node, int oIndex) {
|
||||
struct node_type_float *float_node = (struct node_type_float*)node;
|
||||
NK_ASSERT(oIndex == 0);
|
||||
return &float_node->output_val;
|
||||
}
|
||||
|
||||
static void node_float_draw(struct nk_context *ctx, struct node *node) {
|
||||
struct node_type_float *float_node = (struct node_type_float*)node;
|
||||
nk_layout_row_dynamic(ctx, NODE_DEFAULT_ROW_HEIGHT, 1);
|
||||
float_node->output_val = nk_propertyf(ctx, "#Value:", 0.0f, float_node->output_val, 1.0f, 0.01f, 0.01f);
|
||||
}
|
||||
|
||||
void node_float_create(struct node_editor *editor, struct nk_vec2 position) {
|
||||
struct node_type_float *float_node = (struct node_type_float*)node_editor_add(editor, sizeof(struct node_type_float), "Float", nk_rect(position.x, position.y, 180, 75), 0, 1);
|
||||
if (float_node)
|
||||
{
|
||||
float_node->output_val = 1.0f;
|
||||
float_node->node.display_func = node_float_draw;
|
||||
float_node->node.eval_func = (void*(*)(struct node*, int)) node_float_eval;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------------------
|
||||
// #include "node_color.h"
|
||||
|
||||
struct node_type_color {
|
||||
struct node node;
|
||||
float input_val[4];
|
||||
struct nk_colorf output_val;
|
||||
};
|
||||
|
||||
static struct nk_colorf *node_color_eval(struct node* node, int oIndex)
|
||||
{
|
||||
struct node_type_color *color_node = (struct node_type_color*)node;
|
||||
NK_ASSERT(oIndex == 0); /* only one output connector */
|
||||
|
||||
return &color_node->output_val;
|
||||
}
|
||||
|
||||
|
||||
static void node_color_draw(struct nk_context *ctx, struct node *node)
|
||||
{
|
||||
struct node_type_color *color_node = (struct node_type_color*)node;
|
||||
float eval_result; /* Get the values from connected nodes into this so the inputs revert on disconnect */
|
||||
const char* labels[4] = {"#R:","#G:","#B:","#A:"};
|
||||
float color_val[4]; /* Because we can't just loop through the struct... */
|
||||
nk_layout_row_dynamic(ctx, NODE_DEFAULT_ROW_HEIGHT, 1);
|
||||
nk_button_color(ctx, nk_rgba_cf(color_node->output_val));
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
if (color_node->node.inputs[i].is_connected) {
|
||||
eval_result = *(float*)node_editor_eval_connected(node, i);
|
||||
eval_result = nk_propertyf(ctx, labels[i], eval_result, eval_result, eval_result, 0.01f, 0.01f);
|
||||
color_val[i] = eval_result;
|
||||
}
|
||||
else {
|
||||
color_node->input_val[i] = nk_propertyf(ctx, labels[i], 0.0f, color_node->input_val[i], 1.0f, 0.01f, 0.01f);
|
||||
color_val[i] = color_node->input_val[i];
|
||||
}
|
||||
}
|
||||
|
||||
color_node->output_val.r = color_val[0];
|
||||
color_node->output_val.g = color_val[1];
|
||||
color_node->output_val.b = color_val[2];
|
||||
color_node->output_val.a = color_val[3];
|
||||
}
|
||||
|
||||
void node_color_create(struct node_editor *editor, struct nk_vec2 position)
|
||||
{
|
||||
struct node_type_color *color_node = (struct node_type_color*)node_editor_add(editor, sizeof(struct node_type_color), "Color", nk_rect(position.x, position.y, 180, 190), 4, 1);
|
||||
if (color_node)
|
||||
{
|
||||
const struct nk_colorf black = {0.0f, 0.0f, 0.0f, 1.0f};
|
||||
|
||||
for (int i = 0; i < color_node->node.input_count; i++)
|
||||
color_node->node.inputs[i].pin_type = type_float;
|
||||
color_node->node.outputs[0].pin_type = type_color;
|
||||
|
||||
color_node->node.pin_spacing.in_padding_y += NODE_DEFAULT_ROW_HEIGHT;
|
||||
|
||||
color_node->input_val[0] = 0.0f;
|
||||
color_node->input_val[1] = 0.0f;
|
||||
color_node->input_val[2] = 0.0f;
|
||||
color_node->input_val[3] = 1.0f;
|
||||
|
||||
color_node->output_val = black;
|
||||
|
||||
color_node->node.display_func = node_color_draw;
|
||||
color_node->node.eval_func = (void*(*)(struct node*, int)) node_color_eval;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------------------
|
||||
// #include "node_blend.h"
|
||||
|
||||
struct node_type_blend {
|
||||
struct node node;
|
||||
struct nk_colorf input_val[2];
|
||||
struct nk_colorf output_val;
|
||||
float blend_val;
|
||||
};
|
||||
|
||||
static struct nk_colorf *node_blend_eval(struct node *node, int oIndex) {
|
||||
struct node_type_blend* blend_node = (struct node_type_blend*)node;
|
||||
return &blend_node->output_val;
|
||||
}
|
||||
|
||||
static void node_blend_display(struct nk_context *ctx, struct node *node) {
|
||||
struct node_type_blend *blend_node = (struct node_type_blend*)node;
|
||||
const struct nk_colorf blank = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
float blend_amnt;
|
||||
|
||||
nk_layout_row_dynamic(ctx, NODE_DEFAULT_ROW_HEIGHT, 1);
|
||||
for (int i = 0; i < 2; i++){
|
||||
if(node->inputs[i].is_connected) {
|
||||
blend_node->input_val[i] = *(struct nk_colorf*)node_editor_eval_connected(node, i);
|
||||
}
|
||||
else {
|
||||
blend_node->input_val[i] = blank;
|
||||
}
|
||||
nk_button_color(ctx, nk_rgba_cf(blend_node->input_val[i]));
|
||||
}
|
||||
|
||||
if (node->inputs[2].is_connected) {
|
||||
blend_amnt = *(float*)node_editor_eval_connected(node, 2);
|
||||
blend_amnt = nk_propertyf(ctx, "#Blend", blend_amnt, blend_amnt, blend_amnt, 0.01f, 0.01f);
|
||||
}
|
||||
else {
|
||||
blend_node->blend_val = nk_propertyf(ctx, "#Blend", 0.0f, blend_node->blend_val, 1.0f, 0.01f, 0.01f);
|
||||
blend_amnt = blend_node->blend_val;
|
||||
}
|
||||
|
||||
|
||||
if(node->inputs[0].is_connected && node->inputs[1].is_connected) {
|
||||
blend_node->output_val.r = blend_node->input_val[0].r * (1.0f-blend_amnt) + blend_node->input_val[1].r * blend_amnt;
|
||||
blend_node->output_val.g = blend_node->input_val[0].g * (1.0f-blend_amnt) + blend_node->input_val[1].g * blend_amnt;
|
||||
blend_node->output_val.b = blend_node->input_val[0].b * (1.0f-blend_amnt) + blend_node->input_val[1].b * blend_amnt;
|
||||
blend_node->output_val.a = blend_node->input_val[0].a * (1.0f-blend_amnt) + blend_node->input_val[1].a * blend_amnt;
|
||||
}
|
||||
else {
|
||||
blend_node->output_val = blank;
|
||||
}
|
||||
}
|
||||
|
||||
void node_blend_create(struct node_editor *editor, struct nk_vec2 position) {
|
||||
struct node_type_blend* blend_node = (struct node_type_blend*)node_editor_add(editor, sizeof(struct node_type_blend), "Blend", nk_rect(position.x, position.y, 180, 130), 3, 1);
|
||||
if (blend_node) {
|
||||
const struct nk_colorf blank = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
for (int i = 0; i < (int)NK_LEN(blend_node->input_val); i++)
|
||||
blend_node->node.inputs[i].pin_type = type_color;
|
||||
blend_node->node.outputs[0].pin_type = type_color;
|
||||
|
||||
// blend_node->node.pin_spacing.in_padding_y = 42.0f;
|
||||
// blend_node->node.pin_spacing.in_spacing_y = 29.0f;
|
||||
|
||||
for (int i = 0; i < (int)NK_LEN(blend_node->input_val); i++)
|
||||
blend_node->input_val[i] = blank;
|
||||
blend_node->output_val = blank;
|
||||
|
||||
blend_node->blend_val = 0.5f;
|
||||
|
||||
blend_node->node.display_func = node_blend_display;
|
||||
blend_node->node.eval_func = (void*(*)(struct node*, int)) node_blend_eval;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================= */
|
||||
|
||||
#define NK_RGB3(r,g,b) {r,g,b,255}
|
||||
#define BG_COLOR ((struct nk_color){60,60,60,192}) // nk_rgba(0,0,0,192)
|
||||
|
||||
static
|
||||
struct editor_node_style {
|
||||
int pin_type;
|
||||
const char *shape;
|
||||
struct nk_color color_idle;
|
||||
struct nk_color color_hover;
|
||||
} styles[] = {
|
||||
// order matters:
|
||||
{ type_flow, "triangle_right", NK_RGB3(200,200,200), NK_RGB3(255,255,255) }, // if .num_links == 0
|
||||
{ type_int, "circle", NK_RGB3(33,227,175), NK_RGB3(135,239,195) },
|
||||
{ type_float, "circle", NK_RGB3(156,253,65), NK_RGB3(144,225,137) },
|
||||
{ type_block, "circle", NK_RGB3(6,165,239), NK_RGB3(137,196,247) },
|
||||
{ type_texture, "circle", NK_RGB3(148,0,0), NK_RGB3(183,137,137) },
|
||||
{ type_image, "circle", NK_RGB3(200,130,255), NK_RGB3(220,170,255) },
|
||||
{ type_color, "circle", NK_RGB3(252,200,35), NK_RGB3(255,217,140) },
|
||||
};
|
||||
|
||||
#define COLOR_FLOW_HI styles[type_flow].color_hover
|
||||
#define COLOR_FLOW_LO styles[type_flow].color_idle
|
||||
|
||||
#define GRID_SIZE 64.0f
|
||||
#define GRID_COLOR ((struct nk_color)NK_RGB3(80,80,120))
|
||||
#define GRID_THICKNESS 1.0f
|
||||
|
||||
// 4 colors: top-left, top-right, bottom-right, bottom-left
|
||||
#define GRID_BG_COLORS ((struct nk_color){30,30,30,255}), ((struct nk_color){40,20,0,255}), ((struct nk_color){30,30,30,255}), ((struct nk_color){20,30,40,255})
|
||||
|
||||
#define LINK_THICKNESS 1.0f
|
||||
#define LINK_DRAW(POINT_A,POINT_B,COLOR) do { \
|
||||
vec2 a = (POINT_A); \
|
||||
vec2 b = (POINT_B); \
|
||||
nk_stroke_line(canvas, a.x, a.y, b.x, b.y, LINK_THICKNESS, COLOR); \
|
||||
} while(0)
|
||||
#undef LINK_DRAW
|
||||
#define LINK_DRAW(POINT_A,POINT_B,COLOR) do { \
|
||||
vec2 a = (POINT_A); \
|
||||
vec2 b = (POINT_B); \
|
||||
nk_stroke_curve(canvas, a.x, a.y, a.x+50, a.y, b.x-50, b.y, b.x, b.y, LINK_THICKNESS, COLOR); \
|
||||
} while(0)
|
||||
#undef LINK_DRAW
|
||||
#define LINK_DRAW(POINT_A,POINT_B,COLOR) do { \
|
||||
vec2 a = (POINT_A); \
|
||||
vec2 b = (POINT_B); \
|
||||
float dist2 = len2( sub2( ptr2(&b.x), ptr2(&a.x) ) ); \
|
||||
vec2 mid_a = mix2( ptr2(&a.x), ptr2(&b.x), 0.25 ); mid_a.y += dist2/2; \
|
||||
vec2 mid_b = mix2( ptr2(&a.x), ptr2(&b.x), 0.75 ); mid_b.y += dist2/3; \
|
||||
nk_stroke_curve(canvas, a.x, a.y, mid_a.x, mid_a.y, mid_b.x, mid_b.y, b.x, b.y, LINK_THICKNESS, COLOR); \
|
||||
} while(0)
|
||||
|
||||
|
||||
#define PIN_RADIUS 12
|
||||
#define PIN_THICKNESS 1.0f
|
||||
#define PIN_DRAW(PIN_ADDR,POINT,RADIUS) do { \
|
||||
circle.x = (POINT).x - (RADIUS) / 2; \
|
||||
circle.y = (POINT).y - (RADIUS) / 2; \
|
||||
circle.w = circle.h = (RADIUS); \
|
||||
struct nk_color color = node_get_type_color((PIN_ADDR).pin_type); \
|
||||
if((PIN_ADDR).is_connected) \
|
||||
nk_fill_circle(canvas, circle, color); \
|
||||
else \
|
||||
nk_stroke_circle(canvas, circle, PIN_THICKNESS, color); \
|
||||
} while(0)
|
||||
|
||||
|
||||
static struct nk_color node_get_type_color(unsigned pin_type) {
|
||||
for( int i = 0; i < type_total; ++i )
|
||||
if( styles[i].pin_type == pin_type )
|
||||
return styles[i].color_idle;
|
||||
return ((struct nk_color)NK_RGB3(255,0,255));
|
||||
}
|
||||
|
||||
static void node_editor_push(struct node_editor *editor, struct node *node) {
|
||||
if (!editor->begin) {
|
||||
node->next = NULL;
|
||||
node->prev = NULL;
|
||||
editor->begin = node;
|
||||
editor->end = node;
|
||||
} else {
|
||||
node->prev = editor->end;
|
||||
if (editor->end)
|
||||
editor->end->next = node;
|
||||
node->next = NULL;
|
||||
editor->end = node;
|
||||
}
|
||||
}
|
||||
|
||||
static void node_editor_pop(struct node_editor *editor, struct node *node) {
|
||||
if (node->next)
|
||||
node->next->prev = node->prev;
|
||||
if (node->prev)
|
||||
node->prev->next = node->next;
|
||||
if (editor->end == node)
|
||||
editor->end = node->prev;
|
||||
if (editor->begin == node)
|
||||
editor->begin = node->next;
|
||||
node->next = NULL;
|
||||
node->prev = NULL;
|
||||
}
|
||||
|
||||
static struct node* node_editor_find_by_id(struct node_editor *editor, int ID) {
|
||||
struct node *iter = editor->begin;
|
||||
while (iter) {
|
||||
if (iter->ID == ID)
|
||||
return iter;
|
||||
iter = iter->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct node_link* node_editor_find_link_by_output(struct node_editor *editor, struct node *output_node, int node_input_connector) {
|
||||
for( int i = 0; i < editor->link_count; i++ ) {
|
||||
if (editor->links[i].output_node == output_node &&
|
||||
editor->links[i].output_pin == node_input_connector &&
|
||||
editor->links[i].is_active == nk_true) {
|
||||
return &editor->links[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct node_link* node_editor_find_link_by_input(struct node_editor *editor, struct node *input_node, int node_output_connector) {
|
||||
for( int i = 0; i < editor->link_count; i++ ) {
|
||||
if (editor->links[i].input_node == input_node &&
|
||||
editor->links[i].input_pin == node_output_connector &&
|
||||
editor->links[i].is_active == nk_true) {
|
||||
return &editor->links[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void node_editor_delete_link(struct node_link *link) {
|
||||
link->is_active = nk_false;
|
||||
link->input_node->outputs[link->input_pin].is_connected = nk_false;
|
||||
link->output_node->inputs[link->output_pin].is_connected = nk_false;
|
||||
}
|
||||
|
||||
struct node* node_editor_add(struct node_editor *editor, size_t nodeSize, const char *name, struct nk_rect bounds, int in_count, int out_count) {
|
||||
static int IDs = 0;
|
||||
struct node *node = NULL;
|
||||
|
||||
if ((nk_size)editor->node_count < NK_LEN(editor->node_buf)) {
|
||||
/* node_buf has unused pins */
|
||||
node = MALLOC(nodeSize);
|
||||
editor->node_buf[editor->node_count++] = node;
|
||||
node->ID = IDs++;
|
||||
} else {
|
||||
/* check for freed up pins in node_buf */
|
||||
for (int i = 0; i < editor->node_count; i++) {
|
||||
if (editor->node_buf[i] == NULL) {
|
||||
node = MALLOC(nodeSize);
|
||||
editor->node_buf[i] = node;
|
||||
node->ID = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (node == NULL) {
|
||||
puts("Node creation failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
node->bounds = bounds;
|
||||
|
||||
node->input_count = in_count;
|
||||
node->output_count = out_count;
|
||||
|
||||
node->inputs = MALLOC(node->input_count * sizeof(struct node_pin));
|
||||
node->outputs = MALLOC(node->output_count * sizeof(struct node_pin));
|
||||
|
||||
for (int i = 0; i < node->input_count; i++) {
|
||||
node->inputs[i].is_connected = nk_false;
|
||||
node->inputs[i].pin_type = type_float; /* default pin type */
|
||||
}
|
||||
for (int i = 0; i < node->output_count; i++) {
|
||||
node->outputs[i].is_connected = nk_false;
|
||||
node->outputs[i].pin_type = type_float; /* default pin type */
|
||||
}
|
||||
|
||||
/* default pin spacing */
|
||||
node->pin_spacing.in_padding_x = 2;
|
||||
node->pin_spacing.in_padding_y = 32 + 25/2 + 6; // titlebar height + next half row + adjust
|
||||
node->pin_spacing.in_spacing_y = 25; // row height+border
|
||||
node->pin_spacing.out_padding_x = 3;
|
||||
node->pin_spacing.out_padding_y = 32 + 25/2 + 6; // titlebar height + next half row + adjust
|
||||
node->pin_spacing.out_spacing_y = 25; // row height+border
|
||||
|
||||
strcpy(node->name, name);
|
||||
node_editor_push(editor, node);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
void *node_editor_eval_connected(struct node* node, int input_pin_number) {
|
||||
NK_ASSERT(node->inputs[input_pin_number].is_connected);
|
||||
return node->inputs[input_pin_number].connected_node->eval_func(node->inputs[input_pin_number].connected_node, node->inputs[input_pin_number].connected_pin);
|
||||
}
|
||||
|
||||
static void node_editor_link(struct node_editor *editor, struct node *in_node, int in_pin, struct node *out_node, int out_pin) {
|
||||
/* Confusingly, in and out nodes/pins here refer to the inputs and outputs OF THE LINK ITSELF, not the nodes */
|
||||
struct node_link *link = NULL;
|
||||
|
||||
if ((nk_size)editor->link_count < NK_LEN(editor->links)) {
|
||||
link = &editor->links[editor->link_count++];
|
||||
} else {
|
||||
for (int i = 0; i < (int)NK_LEN(editor->links); i++)
|
||||
{
|
||||
if (editor->links[i].is_active == nk_false) {
|
||||
link = &editor->links[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (link) {
|
||||
out_node->inputs[out_pin].is_connected = nk_true;
|
||||
in_node->outputs[in_pin].is_connected = nk_true;
|
||||
out_node->inputs[out_pin].connected_node = in_node;
|
||||
out_node->inputs[out_pin].connected_pin = in_pin;
|
||||
|
||||
link->input_node = in_node;
|
||||
link->input_pin = in_pin;
|
||||
link->output_node = out_node;
|
||||
link->output_pin = out_pin;
|
||||
link->is_active = nk_true;
|
||||
} else {
|
||||
puts("Too many links");
|
||||
}
|
||||
}
|
||||
|
||||
static void node_editor_init(struct node_editor *editor) {
|
||||
if (editor->initialized) return;
|
||||
|
||||
struct nk_rect total_space = nk_window_get_content_region(ui_ctx);
|
||||
struct nk_vec2 output_node_position = { total_space.w*2/3, total_space.h/3 };
|
||||
struct nk_vec2 color_node_position = { total_space.w*1/4, total_space.h/3 };
|
||||
|
||||
memset(editor, 0, sizeof(*editor));
|
||||
|
||||
editor->output_node = node_output_create(editor, output_node_position);
|
||||
node_color_create(editor, color_node_position);
|
||||
editor->show_grid = nk_true;
|
||||
|
||||
editor->initialized = 1;
|
||||
}
|
||||
|
||||
static int node_editor(struct node_editor *editor) {
|
||||
int n = 0;
|
||||
struct nk_rect total_space;
|
||||
const struct nk_input *in = &ui_ctx->input;
|
||||
struct nk_command_buffer *canvas = nk_window_get_canvas(ui_ctx);
|
||||
struct node *updated = 0;
|
||||
|
||||
node_editor_init(editor);
|
||||
|
||||
{
|
||||
/* allocate complete window space */
|
||||
total_space = nk_window_get_content_region(ui_ctx);
|
||||
nk_layout_space_begin(ui_ctx, NK_STATIC, total_space.h, editor->node_count);
|
||||
{
|
||||
struct node *it = editor->begin;
|
||||
struct nk_rect size = nk_layout_space_bounds(ui_ctx);
|
||||
struct nk_panel *nodePanel = 0;
|
||||
|
||||
//nk_fill_rect(canvas, size, 0/*rounding*/, ((struct nk_color){30,30,30,255})); // 20,30,40,255
|
||||
nk_fill_rect_multi_color(canvas, size, GRID_BG_COLORS);
|
||||
|
||||
if (editor->show_grid) {
|
||||
/* display grid */
|
||||
for (float x = (float)fmod(size.x - editor->scrolling.x, GRID_SIZE); x < size.w; x += GRID_SIZE)
|
||||
nk_stroke_line(canvas, x+size.x, size.y, x+size.x, size.y+size.h, GRID_THICKNESS, GRID_COLOR);
|
||||
for (float y = (float)fmod(size.y - editor->scrolling.y, GRID_SIZE); y < size.h; y += GRID_SIZE)
|
||||
nk_stroke_line(canvas, size.x, y+size.y, size.x+size.w, y+size.y, GRID_THICKNESS, GRID_COLOR);
|
||||
}
|
||||
|
||||
/* execute each node as a movable group */
|
||||
/* loop through nodes */
|
||||
while (it) {
|
||||
/* Output node window should not have a close button */
|
||||
nk_flags nodePanel_flags = NK_WINDOW_MOVABLE|NK_WINDOW_NO_SCROLLBAR|NK_WINDOW_BORDER|NK_WINDOW_TITLE;
|
||||
if (it != editor->output_node)
|
||||
nodePanel_flags |= NK_WINDOW_CLOSABLE;
|
||||
|
||||
/* calculate scrolled node window position and size */
|
||||
nk_layout_space_push(ui_ctx, nk_rect(it->bounds.x - editor->scrolling.x,
|
||||
it->bounds.y - editor->scrolling.y, it->bounds.w, it->bounds.h));
|
||||
|
||||
/* execute node window */
|
||||
char *name = va(" " ICON_MD_MENU " %s",it->name); //< @r-lyeh added some spacing+icon because of our UI customizations
|
||||
|
||||
struct nk_color bak = ui_ctx->style.window.fixed_background.data.color;
|
||||
ui_ctx->style.window.fixed_background.data.color = BG_COLOR;
|
||||
|
||||
if (nk_group_begin(ui_ctx, name, nodePanel_flags))
|
||||
{
|
||||
/* always have last selected node on top */
|
||||
|
||||
nodePanel = nk_window_get_panel(ui_ctx);
|
||||
if (nk_input_mouse_clicked(in, NK_BUTTON_LEFT, nodePanel->bounds) &&
|
||||
(!(it->prev && nk_input_mouse_clicked(in, NK_BUTTON_LEFT,
|
||||
nk_layout_space_rect_to_screen(ui_ctx, nodePanel->bounds)))) &&
|
||||
editor->end != it)
|
||||
{
|
||||
updated = it;
|
||||
}
|
||||
|
||||
if ((nodePanel->flags & NK_WINDOW_HIDDEN)) /* Node close button has been clicked */
|
||||
{
|
||||
/* Delete node */
|
||||
struct node_link *link_remove;
|
||||
node_editor_pop(editor, it);
|
||||
for (int n = 0; n < it->input_count; n++) {
|
||||
if ((link_remove = node_editor_find_link_by_output(editor, it, n)))
|
||||
{
|
||||
node_editor_delete_link(link_remove);
|
||||
}
|
||||
}
|
||||
for (int n = 0; n < it -> output_count; n++) {
|
||||
while((link_remove = node_editor_find_link_by_input(editor, it, n)))
|
||||
{
|
||||
node_editor_delete_link(link_remove);
|
||||
}
|
||||
}
|
||||
NK_ASSERT(editor->node_buf[it->ID] == it);
|
||||
editor->node_buf[it->ID] = NULL;
|
||||
FREE(it->inputs);
|
||||
FREE(it->outputs);
|
||||
FREE(it);
|
||||
}
|
||||
else {
|
||||
|
||||
/* ================= NODE CONTENT ===================== */
|
||||
|
||||
it->display_func(ui_ctx, it);
|
||||
|
||||
/* ==================================================== */
|
||||
|
||||
}
|
||||
nk_group_end(ui_ctx);
|
||||
|
||||
}
|
||||
|
||||
ui_ctx->style.window.fixed_background.data.color = bak;
|
||||
|
||||
if (!(nodePanel->flags & NK_WINDOW_HIDDEN))
|
||||
{
|
||||
/* node pin and linking */
|
||||
struct nk_rect bounds;
|
||||
bounds = nk_layout_space_rect_to_local(ui_ctx, nodePanel->bounds);
|
||||
bounds.x += editor->scrolling.x;
|
||||
bounds.y += editor->scrolling.y;
|
||||
it->bounds = bounds;
|
||||
|
||||
/* output pins */
|
||||
for (int n = 0; n < it->output_count; ++n) {
|
||||
struct nk_rect circle;
|
||||
struct nk_vec2 pt = {nodePanel->bounds.x, nodePanel->bounds.y};
|
||||
pt.x += nodePanel->bounds.w - PIN_RADIUS / 2 + it->pin_spacing.out_padding_x;
|
||||
pt.y += it->pin_spacing.out_padding_y + it->pin_spacing.out_spacing_y * (n);
|
||||
PIN_DRAW(it->outputs[n],pt,PIN_RADIUS);
|
||||
|
||||
/* start linking process */
|
||||
/* set linking active */
|
||||
if (nk_input_has_mouse_click_down_in_rect(in, NK_BUTTON_LEFT, circle, nk_true)) {
|
||||
editor->linking.active = nk_true;
|
||||
editor->linking.node = it;
|
||||
editor->linking.input_id = it->ID;
|
||||
editor->linking.input_pin = n;
|
||||
}
|
||||
|
||||
/* draw link being dragged (from linked pin to mouse position) */
|
||||
if (editor->linking.active && editor->linking.node == it &&
|
||||
editor->linking.input_pin == n) {
|
||||
LINK_DRAW(vec2(circle.x+3,circle.y+3),ptr2(&in->mouse.pos.x),COLOR_FLOW_HI);
|
||||
}
|
||||
}
|
||||
|
||||
/* input pins */
|
||||
for (int n = 0; n < it->input_count; ++n) {
|
||||
struct nk_rect circle;
|
||||
struct nk_vec2 pt = {nodePanel->bounds.x, nodePanel->bounds.y};
|
||||
pt.x += it->pin_spacing.in_padding_x;
|
||||
pt.y += it->pin_spacing.in_padding_y + it->pin_spacing.in_spacing_y * (n);
|
||||
PIN_DRAW(it->inputs[n],pt,PIN_RADIUS);
|
||||
|
||||
/* Detach link */
|
||||
if (nk_input_has_mouse_click_down_in_rect(in, NK_BUTTON_LEFT, circle, nk_true) &&
|
||||
editor->linking.active == nk_false &&
|
||||
it->inputs[n].is_connected == nk_true) {
|
||||
struct node_link *node_relink = node_editor_find_link_by_output(editor, it, n);
|
||||
editor->linking.active = nk_true;
|
||||
editor->linking.node = node_relink->input_node;
|
||||
editor->linking.input_id = node_relink->input_node->ID;
|
||||
editor->linking.input_pin = node_relink->input_pin;
|
||||
node_editor_delete_link(node_relink);
|
||||
}
|
||||
|
||||
/* Create link */
|
||||
if (nk_input_is_mouse_released(in, NK_BUTTON_LEFT) &&
|
||||
nk_input_is_mouse_hovering_rect(in, circle) &&
|
||||
editor->linking.active &&
|
||||
editor->linking.node != it &&
|
||||
it->inputs[n].pin_type == editor->linking.node->outputs[editor->linking.input_pin].pin_type &&
|
||||
it->inputs[n].is_connected != nk_true) {
|
||||
editor->linking.active = nk_false;
|
||||
|
||||
node_editor_link(editor, editor->linking.node,
|
||||
editor->linking.input_pin, it, n);
|
||||
}
|
||||
}
|
||||
}
|
||||
it = it->next;
|
||||
}
|
||||
|
||||
/* reset (output) linking connection */
|
||||
if (editor->linking.active && (!!input(KEY_LCTRL) || !!input(KEY_RCTRL) || nk_input_is_mouse_released(in, NK_BUTTON_LEFT))) {
|
||||
editor->linking.active = nk_false;
|
||||
editor->linking.node = NULL;
|
||||
}
|
||||
|
||||
/* draw each static link */
|
||||
for (int n = 0; n < editor->link_count; ++n) {
|
||||
struct node_link *link = &editor->links[n];
|
||||
if (link->is_active == nk_true){
|
||||
struct node *ni = link->input_node;
|
||||
struct node *no = link->output_node;
|
||||
struct nk_vec2 l0 = nk_layout_space_to_screen(ui_ctx, nk_vec2(ni->bounds.x + ni->bounds.w + ni->pin_spacing.out_padding_x, 3.0f + ni->bounds.y + ni->pin_spacing.out_padding_y + ni->pin_spacing.out_spacing_y * (link->input_pin)));
|
||||
struct nk_vec2 l1 = nk_layout_space_to_screen(ui_ctx, nk_vec2(no->bounds.x + no->pin_spacing.in_padding_x, 3.0f + no->bounds.y + no->pin_spacing.in_padding_y + no->pin_spacing.in_spacing_y * (link->output_pin)));
|
||||
|
||||
l0.x -= editor->scrolling.x;
|
||||
l0.y -= editor->scrolling.y;
|
||||
l1.x -= editor->scrolling.x;
|
||||
l1.y -= editor->scrolling.y;
|
||||
|
||||
struct nk_color color = node_get_type_color(no->inputs[link->output_pin].pin_type);
|
||||
LINK_DRAW(ptr2(&l0.x), ptr2(&l1.x), color);
|
||||
}
|
||||
}
|
||||
|
||||
if (updated) {
|
||||
/* reshuffle nodes to have least recently selected node on top */
|
||||
node_editor_pop(editor, updated);
|
||||
node_editor_push(editor, updated);
|
||||
}
|
||||
|
||||
/* node selection */
|
||||
if (nk_input_mouse_clicked(in, NK_BUTTON_LEFT, nk_layout_space_bounds(ui_ctx))) {
|
||||
it = editor->begin;
|
||||
editor->selected = NULL;
|
||||
editor->bounds = nk_rect(in->mouse.pos.x, in->mouse.pos.y, 100, 200);
|
||||
while (it) {
|
||||
struct nk_rect b = nk_layout_space_rect_to_screen(ui_ctx, it->bounds);
|
||||
b.x -= editor->scrolling.x;
|
||||
b.y -= editor->scrolling.y;
|
||||
if (nk_input_is_mouse_hovering_rect(in, b))
|
||||
editor->selected = it;
|
||||
it = it->next;
|
||||
}
|
||||
}
|
||||
|
||||
/* contextual menu */
|
||||
if (nk_contextual_begin(ui_ctx, 0, nk_vec2(150, 220), nk_window_get_bounds(ui_ctx))) {
|
||||
struct nk_vec2 wincoords = { in->mouse.pos.x-total_space.x-50, in->mouse.pos.y-total_space.y-32 };
|
||||
|
||||
#if 1
|
||||
static char *filter = 0;
|
||||
static int do_filter = 0;
|
||||
if( input_down(KEY_F) ) if( input(KEY_LCTRL) || input(KEY_RCTRL) ) do_filter ^= 1;
|
||||
int choice = ui_toolbar(ICON_MD_SEARCH ";");
|
||||
if( choice == 1 ) do_filter = 1;
|
||||
if( do_filter ) {
|
||||
ui_string(ICON_MD_CLOSE " Filter " ICON_MD_SEARCH, &filter);
|
||||
if( ui_label_icon_clicked_L.x > 0 && ui_label_icon_clicked_L.x <= 24 ) { // if clicked on CANCEL icon (1st icon)
|
||||
do_filter = 0;
|
||||
}
|
||||
} else {
|
||||
if( filter ) filter[0] = '\0';
|
||||
}
|
||||
char *filter_mask = filter && filter[0] ? va("*%s*", filter) : "*";
|
||||
#endif
|
||||
|
||||
#define ui_label_filtered(lbl) (strmatchi(lbl,filter_mask) && ui_label(lbl))
|
||||
|
||||
int close = 0;
|
||||
if (ui_label_filtered("=Add Color node")) close=1,node_color_create(editor, wincoords);
|
||||
if (ui_label_filtered("=Add Float node")) close=1,node_float_create(editor, wincoords);
|
||||
if (ui_label_filtered("=Add Blend Node")) close=1,node_blend_create(editor, wincoords);
|
||||
if (ui_label_filtered(editor->show_grid ? "=Hide Grid" : "=Show Grid"))
|
||||
close=1,editor->show_grid = !editor->show_grid;
|
||||
if(close) do_filter = 0, (filter ? filter[0] = '\0' : '\0'), nk_contextual_close(ui_ctx);
|
||||
nk_contextual_end(ui_ctx);
|
||||
}
|
||||
}
|
||||
nk_layout_space_end(ui_ctx);
|
||||
|
||||
/* window content scrolling */
|
||||
if (nk_input_is_mouse_hovering_rect(in, nk_window_get_bounds(ui_ctx)) &&
|
||||
nk_input_is_mouse_down(in, NK_BUTTON_MIDDLE)) {
|
||||
editor->scrolling.x += in->mouse.delta.x;
|
||||
editor->scrolling.y += in->mouse.delta.y;
|
||||
}
|
||||
}
|
||||
|
||||
return !nk_window_is_closed(ui_ctx, "NodeEdit");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int main() {
|
||||
static int open = 1;
|
||||
window_create(0.75, 0);
|
||||
while(window_swap() && open) {
|
||||
if( ui_window("Node editor",&open) ) {
|
||||
static struct node_editor nodeEditor = {0};
|
||||
node_editor(&nodeEditor);
|
||||
ui_window_end();
|
||||
}
|
||||
}
|
||||
}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,123 @@
|
|||
https://pixelfrog-assets.itch.io/treasure-hunters
|
||||
|
||||
Creative Commons Legal Code
|
||||
|
||||
CC0 1.0 Universal
|
||||
|
||||
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
|
||||
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
|
||||
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
|
||||
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
|
||||
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
|
||||
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
|
||||
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
|
||||
HEREUNDER.
|
||||
|
||||
Statement of Purpose
|
||||
|
||||
The laws of most jurisdictions throughout the world automatically confer
|
||||
exclusive Copyright and Related Rights (defined below) upon the creator
|
||||
and subsequent owner(s) (each and all, an "owner") of an original work of
|
||||
authorship and/or a database (each, a "Work").
|
||||
|
||||
Certain owners wish to permanently relinquish those rights to a Work for
|
||||
the purpose of contributing to a commons of creative, cultural and
|
||||
scientific works ("Commons") that the public can reliably and without fear
|
||||
of later claims of infringement build upon, modify, incorporate in other
|
||||
works, reuse and redistribute as freely as possible in any form whatsoever
|
||||
and for any purposes, including without limitation commercial purposes.
|
||||
These owners may contribute to the Commons to promote the ideal of a free
|
||||
culture and the further production of creative, cultural and scientific
|
||||
works, or to gain reputation or greater distribution for their Work in
|
||||
part through the use and efforts of others.
|
||||
|
||||
For these and/or other purposes and motivations, and without any
|
||||
expectation of additional consideration or compensation, the person
|
||||
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
|
||||
is an owner of Copyright and Related Rights in the Work, voluntarily
|
||||
elects to apply CC0 to the Work and publicly distribute the Work under its
|
||||
terms, with knowledge of his or her Copyright and Related Rights in the
|
||||
Work and the meaning and intended legal effect of CC0 on those rights.
|
||||
|
||||
1. Copyright and Related Rights. A Work made available under CC0 may be
|
||||
protected by copyright and related or neighboring rights ("Copyright and
|
||||
Related Rights"). Copyright and Related Rights include, but are not
|
||||
limited to, the following:
|
||||
|
||||
i. the right to reproduce, adapt, distribute, perform, display,
|
||||
communicate, and translate a Work;
|
||||
ii. moral rights retained by the original author(s) and/or performer(s);
|
||||
iii. publicity and privacy rights pertaining to a person's image or
|
||||
likeness depicted in a Work;
|
||||
iv. rights protecting against unfair competition in regards to a Work,
|
||||
subject to the limitations in paragraph 4(a), below;
|
||||
v. rights protecting the extraction, dissemination, use and reuse of data
|
||||
in a Work;
|
||||
vi. database rights (such as those arising under Directive 96/9/EC of the
|
||||
European Parliament and of the Council of 11 March 1996 on the legal
|
||||
protection of databases, and under any national implementation
|
||||
thereof, including any amended or successor version of such
|
||||
directive); and
|
||||
vii. other similar, equivalent or corresponding rights throughout the
|
||||
world based on applicable law or treaty, and any national
|
||||
implementations thereof.
|
||||
|
||||
2. Waiver. To the greatest extent permitted by, but not in contravention
|
||||
of, applicable law, Affirmer hereby overtly, fully, permanently,
|
||||
irrevocably and unconditionally waives, abandons, and surrenders all of
|
||||
Affirmer's Copyright and Related Rights and associated claims and causes
|
||||
of action, whether now known or unknown (including existing as well as
|
||||
future claims and causes of action), in the Work (i) in all territories
|
||||
worldwide, (ii) for the maximum duration provided by applicable law or
|
||||
treaty (including future time extensions), (iii) in any current or future
|
||||
medium and for any number of copies, and (iv) for any purpose whatsoever,
|
||||
including without limitation commercial, advertising or promotional
|
||||
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
|
||||
member of the public at large and to the detriment of Affirmer's heirs and
|
||||
successors, fully intending that such Waiver shall not be subject to
|
||||
revocation, rescission, cancellation, termination, or any other legal or
|
||||
equitable action to disrupt the quiet enjoyment of the Work by the public
|
||||
as contemplated by Affirmer's express Statement of Purpose.
|
||||
|
||||
3. Public License Fallback. Should any part of the Waiver for any reason
|
||||
be judged legally invalid or ineffective under applicable law, then the
|
||||
Waiver shall be preserved to the maximum extent permitted taking into
|
||||
account Affirmer's express Statement of Purpose. In addition, to the
|
||||
extent the Waiver is so judged Affirmer hereby grants to each affected
|
||||
person a royalty-free, non transferable, non sublicensable, non exclusive,
|
||||
irrevocable and unconditional license to exercise Affirmer's Copyright and
|
||||
Related Rights in the Work (i) in all territories worldwide, (ii) for the
|
||||
maximum duration provided by applicable law or treaty (including future
|
||||
time extensions), (iii) in any current or future medium and for any number
|
||||
of copies, and (iv) for any purpose whatsoever, including without
|
||||
limitation commercial, advertising or promotional purposes (the
|
||||
"License"). The License shall be deemed effective as of the date CC0 was
|
||||
applied by Affirmer to the Work. Should any part of the License for any
|
||||
reason be judged legally invalid or ineffective under applicable law, such
|
||||
partial invalidity or ineffectiveness shall not invalidate the remainder
|
||||
of the License, and in such case Affirmer hereby affirms that he or she
|
||||
will not (i) exercise any of his or her remaining Copyright and Related
|
||||
Rights in the Work or (ii) assert any associated claims and causes of
|
||||
action with respect to the Work, in either case contrary to Affirmer's
|
||||
express Statement of Purpose.
|
||||
|
||||
4. Limitations and Disclaimers.
|
||||
|
||||
a. No trademark or patent rights held by Affirmer are waived, abandoned,
|
||||
surrendered, licensed or otherwise affected by this document.
|
||||
b. Affirmer offers the Work as-is and makes no representations or
|
||||
warranties of any kind concerning the Work, express, implied,
|
||||
statutory or otherwise, including without limitation warranties of
|
||||
title, merchantability, fitness for a particular purpose, non
|
||||
infringement, or the absence of latent or other defects, accuracy, or
|
||||
the present or absence of errors, whether or not discoverable, all to
|
||||
the greatest extent permissible under applicable law.
|
||||
c. Affirmer disclaims responsibility for clearing rights of other persons
|
||||
that may apply to the Work or any use thereof, including without
|
||||
limitation any person's Copyright and Related Rights in the Work.
|
||||
Further, Affirmer disclaims responsibility for obtaining any necessary
|
||||
consents, permissions or other rights required for any use of the
|
||||
Work.
|
||||
d. Affirmer understands and acknowledges that Creative Commons is not a
|
||||
party to this document and has no duty or obligation with respect to
|
||||
this CC0 or use of the Work.
|
|
@ -0,0 +1,98 @@
|
|||
|
||||
goblins.png
|
||||
size: 1024, 128
|
||||
filter: Linear, Linear
|
||||
pma: true
|
||||
dagger
|
||||
bounds: 2, 18, 26, 108
|
||||
goblin/eyes-closed
|
||||
bounds: 2, 4, 34, 12
|
||||
goblin/head
|
||||
bounds: 113, 23, 103, 66
|
||||
rotate: 90
|
||||
goblin/left-arm
|
||||
bounds: 937, 89, 37, 35
|
||||
rotate: 90
|
||||
goblin/left-foot
|
||||
bounds: 609, 61, 65, 31
|
||||
rotate: 90
|
||||
goblin/left-hand
|
||||
bounds: 840, 21, 36, 41
|
||||
goblin/left-lower-leg
|
||||
bounds: 504, 56, 33, 70
|
||||
goblin/left-shoulder
|
||||
bounds: 745, 17, 29, 44
|
||||
goblin/left-upper-leg
|
||||
bounds: 397, 53, 33, 73
|
||||
goblin/neck
|
||||
bounds: 862, 85, 36, 41
|
||||
goblin/pelvis
|
||||
bounds: 776, 18, 62, 43
|
||||
goblin/right-arm
|
||||
bounds: 181, 5, 23, 50
|
||||
rotate: 90
|
||||
goblin/right-foot
|
||||
bounds: 747, 63, 63, 33
|
||||
rotate: 90
|
||||
goblin/right-hand
|
||||
bounds: 878, 3, 36, 37
|
||||
goblin/right-lower-leg
|
||||
bounds: 321, 50, 36, 76
|
||||
goblin/right-shoulder
|
||||
bounds: 663, 14, 39, 45
|
||||
goblin/right-upper-leg
|
||||
bounds: 675, 63, 34, 63
|
||||
goblin/torso
|
||||
bounds: 181, 30, 68, 96
|
||||
goblin/undie-straps
|
||||
bounds: 38, 2, 55, 19
|
||||
goblin/undies
|
||||
bounds: 974, 97, 36, 29
|
||||
goblingirl/eyes-closed
|
||||
bounds: 397, 30, 37, 21
|
||||
goblingirl/head
|
||||
bounds: 30, 23, 103, 81
|
||||
rotate: 90
|
||||
goblingirl/left-arm
|
||||
bounds: 916, 8, 37, 35
|
||||
rotate: 90
|
||||
goblingirl/left-foot
|
||||
bounds: 642, 61, 65, 31
|
||||
rotate: 90
|
||||
goblingirl/left-hand
|
||||
bounds: 900, 86, 35, 40
|
||||
goblingirl/left-lower-leg
|
||||
bounds: 539, 56, 33, 70
|
||||
goblingirl/left-shoulder
|
||||
bounds: 633, 13, 28, 46
|
||||
goblingirl/left-upper-leg
|
||||
bounds: 574, 56, 33, 70
|
||||
goblingirl/neck
|
||||
bounds: 878, 42, 35, 41
|
||||
goblingirl/pelvis
|
||||
bounds: 817, 64, 62, 43
|
||||
rotate: 90
|
||||
goblingirl/right-arm
|
||||
bounds: 603, 4, 28, 50
|
||||
goblingirl/right-foot
|
||||
bounds: 782, 63, 63, 33
|
||||
rotate: 90
|
||||
goblingirl/right-hand
|
||||
bounds: 915, 47, 36, 37
|
||||
goblingirl/right-lower-leg
|
||||
bounds: 359, 50, 36, 76
|
||||
goblingirl/right-shoulder
|
||||
bounds: 704, 16, 39, 45
|
||||
goblingirl/right-upper-leg
|
||||
bounds: 711, 63, 34, 63
|
||||
goblingirl/torso
|
||||
bounds: 251, 30, 68, 96
|
||||
goblingirl/undie-straps
|
||||
bounds: 95, 2, 55, 19
|
||||
goblingirl/undies
|
||||
bounds: 974, 66, 36, 29
|
||||
shield
|
||||
bounds: 432, 54, 70, 72
|
||||
spear
|
||||
bounds: 233, 6, 22, 368
|
||||
rotate: 90
|
|
@ -0,0 +1,627 @@
|
|||
{
|
||||
"skeleton": {
|
||||
"hash": "djttFmlR6Co",
|
||||
"spine": "4.1.17",
|
||||
"x": -92.53,
|
||||
"y": -5.3,
|
||||
"width": 234.03,
|
||||
"height": 354.91,
|
||||
"images": "./images/",
|
||||
"audio": ""
|
||||
},
|
||||
"bones": [
|
||||
{ "name": "root" },
|
||||
{ "name": "hip", "parent": "root", "x": 0.65, "y": 114.41, "color": "ffd300ff" },
|
||||
{
|
||||
"name": "torso",
|
||||
"parent": "hip",
|
||||
"length": 85.83,
|
||||
"rotation": 93.93,
|
||||
"x": -6.42,
|
||||
"y": 1.98,
|
||||
"color": "ffd300ff"
|
||||
},
|
||||
{
|
||||
"name": "neck",
|
||||
"parent": "torso",
|
||||
"length": 18.38,
|
||||
"rotation": -1.52,
|
||||
"x": 81.68,
|
||||
"y": -6.35,
|
||||
"color": "ffd300ff"
|
||||
},
|
||||
{
|
||||
"name": "head",
|
||||
"parent": "neck",
|
||||
"length": 68.29,
|
||||
"rotation": -13.92,
|
||||
"x": 20.94,
|
||||
"y": 11.59,
|
||||
"color": "ffd300ff"
|
||||
},
|
||||
{
|
||||
"name": "left-shoulder",
|
||||
"parent": "torso",
|
||||
"length": 35.43,
|
||||
"rotation": -156.96,
|
||||
"x": 74.05,
|
||||
"y": -20.39,
|
||||
"color": "ff0000ff"
|
||||
},
|
||||
{
|
||||
"name": "left-arm",
|
||||
"parent": "left-shoulder",
|
||||
"length": 35.62,
|
||||
"rotation": 28.17,
|
||||
"x": 37.86,
|
||||
"y": -2.35,
|
||||
"color": "ff0000ff"
|
||||
},
|
||||
{
|
||||
"name": "left-upper-leg",
|
||||
"parent": "hip",
|
||||
"length": 50.4,
|
||||
"rotation": -89.1,
|
||||
"x": 14.45,
|
||||
"y": 2.81,
|
||||
"color": "ff0000ff"
|
||||
},
|
||||
{
|
||||
"name": "left-lower-leg",
|
||||
"parent": "left-upper-leg",
|
||||
"length": 49.9,
|
||||
"rotation": -16.66,
|
||||
"x": 56.34,
|
||||
"y": 0.99,
|
||||
"color": "ff0000ff"
|
||||
},
|
||||
{
|
||||
"name": "left-foot",
|
||||
"parent": "left-lower-leg",
|
||||
"length": 46.5,
|
||||
"rotation": 102.43,
|
||||
"x": 58.94,
|
||||
"y": -7.61,
|
||||
"color": "ff0000ff"
|
||||
},
|
||||
{
|
||||
"name": "left-hand",
|
||||
"parent": "left-arm",
|
||||
"length": 11.52,
|
||||
"rotation": 2.7,
|
||||
"x": 35.62,
|
||||
"y": 0.08,
|
||||
"color": "ff0000ff"
|
||||
},
|
||||
{ "name": "pelvis", "parent": "hip", "x": 1.41, "y": -6.58, "color": "ffd300ff" },
|
||||
{
|
||||
"name": "right-shoulder",
|
||||
"parent": "torso",
|
||||
"length": 37.25,
|
||||
"rotation": 133.89,
|
||||
"x": 76.02,
|
||||
"y": 18.15,
|
||||
"color": "54ff00ff"
|
||||
},
|
||||
{
|
||||
"name": "right-arm",
|
||||
"parent": "right-shoulder",
|
||||
"length": 36.75,
|
||||
"rotation": 36.33,
|
||||
"x": 37.61,
|
||||
"y": 0.31,
|
||||
"color": "54ff00ff"
|
||||
},
|
||||
{
|
||||
"name": "right-upper-leg",
|
||||
"parent": "hip",
|
||||
"length": 42.46,
|
||||
"rotation": -97.5,
|
||||
"x": -20.08,
|
||||
"y": -6.84,
|
||||
"color": "54ff00ff"
|
||||
},
|
||||
{
|
||||
"name": "right-lower-leg",
|
||||
"parent": "right-upper-leg",
|
||||
"length": 58.53,
|
||||
"rotation": -14.34,
|
||||
"x": 43,
|
||||
"y": -0.62,
|
||||
"color": "54ff00ff"
|
||||
},
|
||||
{
|
||||
"name": "right-foot",
|
||||
"parent": "right-lower-leg",
|
||||
"length": 45.46,
|
||||
"rotation": 110.31,
|
||||
"x": 64.89,
|
||||
"y": 0.04,
|
||||
"color": "54ff00ff"
|
||||
},
|
||||
{
|
||||
"name": "right-hand",
|
||||
"parent": "right-arm",
|
||||
"length": 15.32,
|
||||
"rotation": 2.36,
|
||||
"x": 36.9,
|
||||
"y": 0.35,
|
||||
"color": "54ff00ff"
|
||||
}
|
||||
],
|
||||
"slots": [
|
||||
{ "name": "left-shoulder", "bone": "left-shoulder", "attachment": "left-shoulder" },
|
||||
{ "name": "left-arm", "bone": "left-arm", "attachment": "left-arm" },
|
||||
{ "name": "left-hand-item", "bone": "left-hand", "attachment": "spear" },
|
||||
{ "name": "left-hand", "bone": "left-hand", "attachment": "left-hand" },
|
||||
{ "name": "left-foot", "bone": "left-foot", "attachment": "left-foot" },
|
||||
{ "name": "left-lower-leg", "bone": "left-lower-leg", "attachment": "left-lower-leg" },
|
||||
{ "name": "left-upper-leg", "bone": "left-upper-leg", "attachment": "left-upper-leg" },
|
||||
{ "name": "neck", "bone": "neck", "attachment": "neck" },
|
||||
{ "name": "torso", "bone": "torso", "attachment": "torso" },
|
||||
{ "name": "pelvis", "bone": "pelvis", "attachment": "pelvis" },
|
||||
{ "name": "right-foot", "bone": "right-foot", "attachment": "right-foot" },
|
||||
{ "name": "right-lower-leg", "bone": "right-lower-leg", "attachment": "right-lower-leg" },
|
||||
{ "name": "undie-straps", "bone": "pelvis", "attachment": "undie-straps" },
|
||||
{ "name": "undies", "bone": "pelvis", "attachment": "undies" },
|
||||
{ "name": "right-upper-leg", "bone": "right-upper-leg", "attachment": "right-upper-leg" },
|
||||
{ "name": "head", "bone": "head", "attachment": "head" },
|
||||
{ "name": "eyes", "bone": "head" },
|
||||
{ "name": "right-shoulder", "bone": "right-shoulder", "attachment": "right-shoulder" },
|
||||
{ "name": "right-arm", "bone": "right-arm", "attachment": "right-arm" },
|
||||
{ "name": "right-hand-item", "bone": "right-hand" },
|
||||
{ "name": "right-hand", "bone": "right-hand", "attachment": "right-hand" },
|
||||
{ "name": "right-hand-item-top", "bone": "right-hand", "attachment": "shield" }
|
||||
],
|
||||
"skins": [
|
||||
{
|
||||
"name": "default",
|
||||
"attachments": {
|
||||
"left-hand-item": {
|
||||
"dagger": { "x": 7.88, "y": -23.46, "rotation": 10.48, "width": 26, "height": 108 },
|
||||
"spear": { "x": -4.56, "y": 39.2, "rotation": 13.05, "width": 22, "height": 368 }
|
||||
},
|
||||
"right-hand-item": {
|
||||
"dagger": { "x": 6.52, "y": -24.16, "rotation": -8.06, "width": 26, "height": 108 }
|
||||
},
|
||||
"right-hand-item-top": {
|
||||
"shield": { "rotation": 93.5, "width": 70, "height": 72 }
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "goblin",
|
||||
"attachments": {
|
||||
"eyes": {
|
||||
"eyes-closed": { "name": "goblin/eyes-closed", "x": 32.22, "y": -21.27, "rotation": -88.93, "width": 34, "height": 12 }
|
||||
},
|
||||
"head": {
|
||||
"head": { "name": "goblin/head", "x": 25.74, "y": 2.33, "rotation": -92.29, "width": 103, "height": 66 }
|
||||
},
|
||||
"left-arm": {
|
||||
"left-arm": {
|
||||
"name": "goblin/left-arm",
|
||||
"x": 16.7,
|
||||
"y": -1.69,
|
||||
"scaleX": 1.0573,
|
||||
"scaleY": 1.0573,
|
||||
"rotation": 33.85,
|
||||
"width": 37,
|
||||
"height": 35
|
||||
}
|
||||
},
|
||||
"left-foot": {
|
||||
"left-foot": { "name": "goblin/left-foot", "x": 24.85, "y": 8.75, "rotation": 3.32, "width": 65, "height": 31 }
|
||||
},
|
||||
"left-hand": {
|
||||
"left-hand": {
|
||||
"name": "goblin/left-hand",
|
||||
"x": 3.47,
|
||||
"y": 3.41,
|
||||
"scaleX": 0.8922,
|
||||
"scaleY": 0.8922,
|
||||
"rotation": 31.14,
|
||||
"width": 36,
|
||||
"height": 41
|
||||
}
|
||||
},
|
||||
"left-lower-leg": {
|
||||
"left-lower-leg": { "name": "goblin/left-lower-leg", "x": 23.59, "y": -2.07, "rotation": 105.76, "width": 33, "height": 70 }
|
||||
},
|
||||
"left-shoulder": {
|
||||
"left-shoulder": { "name": "goblin/left-shoulder", "x": 15.56, "y": -2.27, "rotation": 62.01, "width": 29, "height": 44 }
|
||||
},
|
||||
"left-upper-leg": {
|
||||
"left-upper-leg": { "name": "goblin/left-upper-leg", "x": 29.69, "y": -3.87, "rotation": 89.1, "width": 33, "height": 73 }
|
||||
},
|
||||
"neck": {
|
||||
"neck": { "name": "goblin/neck", "x": 10.1, "y": 0.42, "rotation": -93.7, "width": 36, "height": 41 }
|
||||
},
|
||||
"pelvis": {
|
||||
"pelvis": { "name": "goblin/pelvis", "x": -5.62, "y": 0.77, "width": 62, "height": 43 }
|
||||
},
|
||||
"right-arm": {
|
||||
"right-arm": { "name": "goblin/right-arm", "x": 16.44, "y": -1.04, "rotation": 94.32, "width": 23, "height": 50 }
|
||||
},
|
||||
"right-foot": {
|
||||
"right-foot": { "name": "goblin/right-foot", "x": 23.57, "y": 9.8, "rotation": 1.53, "width": 63, "height": 33 }
|
||||
},
|
||||
"right-hand": {
|
||||
"right-hand": { "name": "goblin/right-hand", "x": 7.89, "y": 2.78, "rotation": 91.96, "width": 36, "height": 37 }
|
||||
},
|
||||
"right-lower-leg": {
|
||||
"right-lower-leg": { "name": "goblin/right-lower-leg", "x": 25.68, "y": -3.16, "rotation": 111.84, "width": 36, "height": 76 }
|
||||
},
|
||||
"right-shoulder": {
|
||||
"right-shoulder": { "name": "goblin/right-shoulder", "x": 15.68, "y": -1.03, "rotation": 130.65, "width": 39, "height": 45 }
|
||||
},
|
||||
"right-upper-leg": {
|
||||
"right-upper-leg": { "name": "goblin/right-upper-leg", "x": 20.35, "y": 1.48, "rotation": 97.5, "width": 34, "height": 63 }
|
||||
},
|
||||
"torso": {
|
||||
"torso": { "name": "goblin/torso", "x": 38.1, "y": -3.87, "rotation": -94.95, "width": 68, "height": 96 }
|
||||
},
|
||||
"undie-straps": {
|
||||
"undie-straps": { "name": "goblin/undie-straps", "x": -3.88, "y": 13.11, "scaleX": 1.0896, "width": 55, "height": 19 }
|
||||
},
|
||||
"undies": {
|
||||
"undies": { "name": "goblin/undies", "x": 6.3, "y": 0.13, "rotation": 0.92, "width": 36, "height": 29 }
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "goblingirl",
|
||||
"attachments": {
|
||||
"eyes": {
|
||||
"eyes-closed": { "name": "goblingirl/eyes-closed", "x": 28, "y": -25.55, "rotation": -87.05, "width": 37, "height": 21 }
|
||||
},
|
||||
"head": {
|
||||
"head": { "name": "goblingirl/head", "x": 27.72, "y": -4.32, "rotation": -85.58, "width": 103, "height": 81 }
|
||||
},
|
||||
"left-arm": {
|
||||
"left-arm": { "name": "goblingirl/left-arm", "x": 19.64, "y": -2.43, "rotation": 33.05, "width": 37, "height": 35 }
|
||||
},
|
||||
"left-foot": {
|
||||
"left-foot": { "name": "goblingirl/left-foot", "x": 25.18, "y": 7.92, "rotation": 3.32, "width": 65, "height": 31 }
|
||||
},
|
||||
"left-hand": {
|
||||
"left-hand": {
|
||||
"name": "goblingirl/left-hand",
|
||||
"x": 4.34,
|
||||
"y": 2.39,
|
||||
"scaleX": 0.8965,
|
||||
"scaleY": 0.8965,
|
||||
"rotation": 30.35,
|
||||
"width": 35,
|
||||
"height": 40
|
||||
}
|
||||
},
|
||||
"left-lower-leg": {
|
||||
"left-lower-leg": { "name": "goblingirl/left-lower-leg", "x": 25.02, "y": -0.61, "rotation": 105.76, "width": 33, "height": 70 }
|
||||
},
|
||||
"left-shoulder": {
|
||||
"left-shoulder": { "name": "goblingirl/left-shoulder", "x": 19.81, "y": -0.43, "rotation": 61.22, "width": 28, "height": 46 }
|
||||
},
|
||||
"left-upper-leg": {
|
||||
"left-upper-leg": { "name": "goblingirl/left-upper-leg", "x": 30.22, "y": -2.95, "rotation": 89.1, "width": 33, "height": 70 }
|
||||
},
|
||||
"neck": {
|
||||
"neck": { "name": "goblingirl/neck", "x": 6.16, "y": -3.15, "rotation": -98.86, "width": 35, "height": 41 }
|
||||
},
|
||||
"pelvis": {
|
||||
"pelvis": { "name": "goblingirl/pelvis", "x": -3.88, "y": 3.19, "width": 62, "height": 43 }
|
||||
},
|
||||
"right-arm": {
|
||||
"right-arm": { "name": "goblingirl/right-arm", "x": 16.85, "y": -0.66, "rotation": 93.53, "width": 28, "height": 50 }
|
||||
},
|
||||
"right-foot": {
|
||||
"right-foot": { "name": "goblingirl/right-foot", "x": 23.46, "y": 9.66, "rotation": 1.53, "width": 63, "height": 33 }
|
||||
},
|
||||
"right-hand": {
|
||||
"right-hand": { "name": "goblingirl/right-hand", "x": 7.22, "y": 3.44, "rotation": 91.17, "width": 36, "height": 37 }
|
||||
},
|
||||
"right-lower-leg": {
|
||||
"right-lower-leg": { "name": "goblingirl/right-lower-leg", "x": 26.15, "y": -3.28, "rotation": 111.84, "width": 36, "height": 76 }
|
||||
},
|
||||
"right-shoulder": {
|
||||
"right-shoulder": { "name": "goblingirl/right-shoulder", "x": 14.46, "y": 0.46, "rotation": 129.85, "width": 39, "height": 45 }
|
||||
},
|
||||
"right-upper-leg": {
|
||||
"right-upper-leg": { "name": "goblingirl/right-upper-leg", "x": 19.7, "y": 2.13, "rotation": 97.5, "width": 34, "height": 63 }
|
||||
},
|
||||
"torso": {
|
||||
"torso": { "name": "goblingirl/torso", "x": 36.28, "y": -5.14, "rotation": -95.75, "width": 68, "height": 96 }
|
||||
},
|
||||
"undie-straps": {
|
||||
"undie-straps": { "name": "goblingirl/undie-straps", "x": -1.52, "y": 14.19, "width": 55, "height": 19 }
|
||||
},
|
||||
"undies": {
|
||||
"undies": { "name": "goblingirl/undies", "x": 5.4, "y": 1.71, "width": 36, "height": 29 }
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"animations": {
|
||||
"walk": {
|
||||
"slots": {
|
||||
"eyes": {
|
||||
"attachment": [
|
||||
{ "time": 0.7, "name": "eyes-closed" },
|
||||
{ "time": 0.8 }
|
||||
]
|
||||
}
|
||||
},
|
||||
"bones": {
|
||||
"left-upper-leg": {
|
||||
"rotate": [
|
||||
{ "value": -26.56 },
|
||||
{ "time": 0.1333, "value": -8.79 },
|
||||
{ "time": 0.2333, "value": 9.51 },
|
||||
{ "time": 0.3667, "value": 30.74 },
|
||||
{ "time": 0.5, "value": 25.34 },
|
||||
{ "time": 0.6333, "value": 26.12 },
|
||||
{ "time": 0.7333, "value": -7.71 },
|
||||
{ "time": 0.8667, "value": -21.19 },
|
||||
{ "time": 1, "value": -26.56 }
|
||||
],
|
||||
"translate": [
|
||||
{ "x": -1.32, "y": 1.71 },
|
||||
{ "time": 0.3667, "x": -0.06, "y": 2.43 },
|
||||
{ "time": 1, "x": -1.32, "y": 1.71 }
|
||||
]
|
||||
},
|
||||
"right-upper-leg": {
|
||||
"rotate": [
|
||||
{ "value": 42.45 },
|
||||
{ "time": 0.1333, "value": 52.11 },
|
||||
{ "time": 0.2333, "value": 8.54 },
|
||||
{ "time": 0.5, "value": -16.94 },
|
||||
{ "time": 0.6333, "value": 1.9 },
|
||||
{
|
||||
"time": 0.7333,
|
||||
"value": 28.06,
|
||||
"curve": [ 0.795, 31.71, 0.867, 58.69 ]
|
||||
},
|
||||
{
|
||||
"time": 0.8667,
|
||||
"value": 58.69,
|
||||
"curve": [ 0.933, 58.35, 1, 42.45 ]
|
||||
},
|
||||
{ "time": 1, "value": 42.45 }
|
||||
],
|
||||
"translate": [
|
||||
{ "x": 6.24 },
|
||||
{ "time": 0.2333, "x": 2.14, "y": 2.4 },
|
||||
{ "time": 0.5, "x": 2.44, "y": 4.8 },
|
||||
{ "time": 1, "x": 6.24 }
|
||||
]
|
||||
},
|
||||
"left-lower-leg": {
|
||||
"rotate": [
|
||||
{ "value": -22.98 },
|
||||
{ "time": 0.1333, "value": -63.51 },
|
||||
{ "time": 0.2333, "value": -73.76 },
|
||||
{ "time": 0.5, "value": 5.12 },
|
||||
{ "time": 0.6333, "value": -28.3 },
|
||||
{ "time": 0.7333, "value": 4.08 },
|
||||
{ "time": 0.8667, "value": 3.53 },
|
||||
{ "time": 1, "value": -22.98 }
|
||||
],
|
||||
"translate": [
|
||||
{},
|
||||
{ "time": 0.2333, "x": 2.56, "y": -0.47 },
|
||||
{ "time": 0.5 }
|
||||
]
|
||||
},
|
||||
"left-foot": {
|
||||
"rotate": [
|
||||
{ "value": -3.69 },
|
||||
{ "time": 0.1333, "value": -10.42 },
|
||||
{ "time": 0.2333, "value": -5.01 },
|
||||
{ "time": 0.3667, "value": 3.87 },
|
||||
{ "time": 0.5, "value": -3.88 },
|
||||
{ "time": 0.6333, "value": 2.78 },
|
||||
{ "time": 0.7333, "value": 1.68 },
|
||||
{ "time": 0.8667, "value": -8.54 },
|
||||
{ "time": 1, "value": -3.69 }
|
||||
]
|
||||
},
|
||||
"right-shoulder": {
|
||||
"rotate": [
|
||||
{
|
||||
"value": 5.29,
|
||||
"curve": [ 0.167, 5.29, 0.475, 6.65 ]
|
||||
},
|
||||
{ "time": 0.6333, "value": 6.65 },
|
||||
{ "time": 1, "value": 5.29 }
|
||||
]
|
||||
},
|
||||
"right-arm": {
|
||||
"rotate": [
|
||||
{
|
||||
"value": -4.03,
|
||||
"curve": [ 0.169, -3.91, 0.51, 19.66 ]
|
||||
},
|
||||
{
|
||||
"time": 0.6333,
|
||||
"value": 19.79,
|
||||
"curve": [ 0.746, 19.75, 0.922, -3.91 ]
|
||||
},
|
||||
{ "time": 1, "value": -4.03 }
|
||||
]
|
||||
},
|
||||
"right-hand": {
|
||||
"rotate": [
|
||||
{ "value": 8.99 },
|
||||
{ "time": 0.6333, "value": 0.51 },
|
||||
{ "time": 1, "value": 8.99 }
|
||||
]
|
||||
},
|
||||
"left-shoulder": {
|
||||
"rotate": [
|
||||
{
|
||||
"value": 6.26,
|
||||
"curve": [ 0.17, 6.26, 0.342, -11.79 ]
|
||||
},
|
||||
{
|
||||
"time": 0.5,
|
||||
"value": -11.79,
|
||||
"curve": [ 0.641, -11.79, 0.843, 6.16 ]
|
||||
},
|
||||
{ "time": 1, "value": 6.26 }
|
||||
],
|
||||
"translate": [
|
||||
{ "x": 1.15, "y": 0.24 }
|
||||
]
|
||||
},
|
||||
"left-hand": {
|
||||
"rotate": [
|
||||
{
|
||||
"value": -21.24,
|
||||
"curve": [ 0.148, -21.24, 0.378, -27.21 ]
|
||||
},
|
||||
{
|
||||
"time": 0.5,
|
||||
"value": -27.28,
|
||||
"curve": [ 0.621, -27.28, 0.875, -21.4 ]
|
||||
},
|
||||
{ "time": 1, "value": -21.24 }
|
||||
]
|
||||
},
|
||||
"left-arm": {
|
||||
"rotate": [
|
||||
{
|
||||
"value": 28.38,
|
||||
"curve": [ 0.17, 28.38, 0.342, 60.09 ]
|
||||
},
|
||||
{
|
||||
"time": 0.5,
|
||||
"value": 60.09,
|
||||
"curve": [ 0.641, 60.09, 0.843, 28.54 ]
|
||||
},
|
||||
{ "time": 1, "value": 28.38 }
|
||||
]
|
||||
},
|
||||
"torso": {
|
||||
"rotate": [
|
||||
{ "value": -10.28 },
|
||||
{
|
||||
"time": 0.1333,
|
||||
"value": -15.39,
|
||||
"curve": [ 0.261, -15.36, 0.324, -9.78 ]
|
||||
},
|
||||
{
|
||||
"time": 0.3667,
|
||||
"value": -9.78,
|
||||
"curve": [ 0.521, -10.8, 0.545, -15.72 ]
|
||||
},
|
||||
{
|
||||
"time": 0.6333,
|
||||
"value": -15.75,
|
||||
"curve": [ 0.688, -15.66, 0.819, -7.07 ]
|
||||
},
|
||||
{
|
||||
"time": 0.8667,
|
||||
"value": -7.07,
|
||||
"curve": [ 0.895, -7.07, 0.975, -10.25 ]
|
||||
},
|
||||
{ "time": 1, "value": -10.28 }
|
||||
],
|
||||
"translate": [
|
||||
{ "x": -1.29, "y": 1.69 }
|
||||
]
|
||||
},
|
||||
"right-foot": {
|
||||
"rotate": [
|
||||
{ "value": -5.25 },
|
||||
{ "time": 0.2333, "value": -1.91 },
|
||||
{ "time": 0.3667, "value": -6.45 },
|
||||
{ "time": 0.5, "value": -5.4 },
|
||||
{ "time": 0.7333, "value": -11.69 },
|
||||
{ "time": 0.8667, "value": 0.46 },
|
||||
{ "time": 1, "value": -5.25 }
|
||||
]
|
||||
},
|
||||
"right-lower-leg": {
|
||||
"rotate": [
|
||||
{
|
||||
"value": -3.39,
|
||||
"curve": [ 0.042, -4.05, 0.099, -45.1 ]
|
||||
},
|
||||
{
|
||||
"time": 0.1333,
|
||||
"value": -45.53,
|
||||
"curve": [ 0.156, -45.53, 0.207, -5.89 ]
|
||||
},
|
||||
{ "time": 0.2333, "value": -4.83 },
|
||||
{ "time": 0.5, "value": -19.53 },
|
||||
{ "time": 0.6333, "value": -64.8 },
|
||||
{
|
||||
"time": 0.7333,
|
||||
"value": -82.56,
|
||||
"curve": [ 0.882, -68.28, 1, -3.39 ]
|
||||
},
|
||||
{ "time": 1, "value": -3.39 }
|
||||
],
|
||||
"translate": [
|
||||
{ "time": 0.5 },
|
||||
{ "time": 0.6333, "x": 2.19, "y": 0.21 },
|
||||
{ "time": 1 }
|
||||
]
|
||||
},
|
||||
"hip": {
|
||||
"translate": [
|
||||
{ "y": -4.16 },
|
||||
{
|
||||
"time": 0.1333,
|
||||
"y": -7.06,
|
||||
"curve": [ 0.217, 0, 0.284, 0, 0.217, -0.53, 0.284, 3.27 ]
|
||||
},
|
||||
{ "time": 0.3667, "y": 6.78 },
|
||||
{ "time": 0.5, "y": -6.14 },
|
||||
{
|
||||
"time": 0.6333,
|
||||
"y": -7.06,
|
||||
"curve": [ 0.717, 0, 0.784, 0, 0.717, -0.53, 0.784, 3.27 ]
|
||||
},
|
||||
{ "time": 0.8667, "y": 6.78 },
|
||||
{ "time": 1, "y": -4.16 }
|
||||
]
|
||||
},
|
||||
"neck": {
|
||||
"rotate": [
|
||||
{ "value": 3.6 },
|
||||
{ "time": 0.1333, "value": 17.5 },
|
||||
{ "time": 0.2333, "value": 6.11 },
|
||||
{ "time": 0.3667, "value": 3.46 },
|
||||
{ "time": 0.5, "value": 5.18 },
|
||||
{ "time": 0.6333, "value": 18.36 },
|
||||
{ "time": 0.7333, "value": 6.09 },
|
||||
{ "time": 0.8667, "value": 2.29 },
|
||||
{ "time": 1, "value": 3.6 }
|
||||
]
|
||||
},
|
||||
"head": {
|
||||
"rotate": [
|
||||
{
|
||||
"value": 3.6,
|
||||
"curve": [ 0, 3.6, 0.094, -0.89 ]
|
||||
},
|
||||
{ "time": 0.1333, "value": -0.21 },
|
||||
{ "time": 0.2333, "value": 6.11 },
|
||||
{ "time": 0.3667, "value": 3.46 },
|
||||
{
|
||||
"time": 0.5,
|
||||
"value": 5.18,
|
||||
"curve": [ 0.5, 5.18, 0.617, -1.4 ]
|
||||
},
|
||||
{ "time": 0.6667, "value": 1.11 },
|
||||
{ "time": 0.7333, "value": 6.09 },
|
||||
{ "time": 0.8667, "value": 2.29 },
|
||||
{ "time": 1, "value": 3.6 }
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
Copyright (c) 2013, Esoteric Software
|
||||
|
||||
The images in this project may be redistributed as long as they are accompanied
|
||||
by this license file. The images may not be used for commercial use of any
|
||||
kind.
|
||||
|
||||
The project file is released into the public domain. It may be used as the basis
|
||||
for derivative work.
|
Binary file not shown.
After Width: | Height: | Size: 140 KiB |
Binary file not shown.
After Width: | Height: | Size: 4.8 KiB |
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<map version="1.9" tiledversion="1.9.2" orientation="orthogonal" renderorder="right-down" width="37" height="38" tilewidth="16" tileheight="16" infinite="0" nextlayerid="3" nextobjectid="1">
|
||||
<tileset firstgid="1" source="castle.tsx"/>
|
||||
<layer id="2" name="Tile BG" width="37" height="38">
|
||||
<data encoding="base64" compression="zlib">
|
||||
eJztk8sKwjAQRfMb1sderYLPrd/hqnTT//8Ep9DAdXAmkb4o3AOHkpCEQ9qG8M1uJqtgw6blNxXgWtyoucI5v12/hT1x/xD3pBustl+uOlP9fZssU61jfk+5jVM2xa5/3uEUTfq+cu7SOuftNDWdQzel/rfaaGrAdv41kxV06aa9eBBP4hnGR7GEZ5z31uu93thruohX8SE+YXwT7/CM8956vdcbYxPifftjYzURQgghhBBCCMnjAxltRQI=
|
||||
</data>
|
||||
</layer>
|
||||
<layer id="1" name="Tile FG" width="37" height="38">
|
||||
<data encoding="base64" compression="zlib">
|
||||
eJztlE1Lw0AQhicxoLd605taP489xsb6EZH6hYiKCIKFXvr//4Ez+A4Z102y0oMe5oWHdGd3Ju/OkBKlKwd9KhLOzANmoO/9RfBUZaAAdp2ZM0Xk3LKeTpkzcI66NqbxWCyL5GeRuO71edLeXAdxyXln1phpS33NC/On1MxU9+aIHyV4KnDO6piaOawHtUUT43Nh+DBon4i+z22U4CnHOdGj8aTaxPtWsR4yB8weYosA0RazjbsW8FIHnrokOSVTMW+IXUQ8DbAem72B+a2z0h5n5q6/9ZTjPnlA6GnDeFJfGpuY87bHI2rmW+OZ4klUom5tsN+y1Lqkn9+6xGSWu/Q1S5Htcdnhqc2X1F7Bc4i6Dy2+bjrudMvcMffU9Gls7mD/l1L6JJ4q4+OV4v3aYa6YfeaQOUFccp+YZ+aFmj5p3sx4qhI9/YXcU5r+oyeXy+VyuVwul8vlci2nTwIxM6E=
|
||||
</data>
|
||||
</layer>
|
||||
</map>
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<tileset version="1.9" tiledversion="1.9.2" name="castle" tilewidth="16" tileheight="16" tilecount="128" columns="8">
|
||||
<image source="castle-tileset-by-RottingPixels-(CC0).png" width="128" height="256"/>
|
||||
</tileset>
|
|
@ -56,7 +56,7 @@ TODO("obj: free obj_components()/payload2");
|
|||
|
||||
TODO("pack: mp2json, json2mp");
|
||||
TODO("pack: simplify msgpack API, make it growth similar to va()")
|
||||
#if 0 // fwk_pack proposal
|
||||
#if 0 // v4k_pack proposal
|
||||
static __thread char* mpin;
|
||||
static __thread unsigned mpinlen;
|
||||
static __thread char mpinbuf[256];
|
||||
|
|
2
hello.c
2
hello.c
|
@ -1,4 +1,4 @@
|
|||
// playground tests for FWK
|
||||
// playground tests for V4K
|
||||
// - rlyeh, public domain
|
||||
//
|
||||
// # quickstart
|
||||
|
|
BIN
tools/cook.exe
BIN
tools/cook.exe
Binary file not shown.
|
@ -7,7 +7,7 @@
|
|||
; syntax: symbols are defined in KEY=value form, as seen below.
|
||||
|
||||
TOOLS=./ ; folder where our pipeline tools are located
|
||||
ART=../demos/art/,../engine/art/,../tools/editor/art/ ; comma-separated folder(s) that store all our asset files
|
||||
ART=../demos/art/,../engine/art/,../editor/art/ ; comma-separated folder(s) that store all our asset files
|
||||
|
||||
; lines starting with @windows, @linux or @osx will be processed only where OS matches.
|
||||
; we are defining here some symbols differently for each platform.
|
||||
|
@ -25,9 +25,9 @@ ART=../demos/art/,../engine/art/,../tools/editor/art/ ; comma-separated folder(
|
|||
; also, once a symbol is found, it is replaced by its value always.
|
||||
; some predefined symbols: INPUT (input filename), OUTPUT (output filename), PRETTY (clean input filename), PROGRESS (cook progress).
|
||||
|
||||
@windows `echo Cooking PROGRESS% PRETTY...`
|
||||
@linux `echo "Cooking PROGRESS% PRETTY..."`
|
||||
@osx `echo "Cooking PROGRESS% PRETTY..."`
|
||||
;@windows `echo Cooking PROGRESS% PRETTY...`
|
||||
;@linux `echo "Cooking PROGRESS% PRETTY..."`
|
||||
;@osx `echo "Cooking PROGRESS% PRETTY..."`
|
||||
|
||||
; ------------------------------------------------------------------------------
|
||||
; groups below are collection of files that we want to cook, and then package.
|
||||
|
@ -212,4 +212,4 @@ TOOLS/ase2ini.EXE "INPUT" > OUTPUT
|
|||
|
||||
[compress]
|
||||
0|ULZ=texture,image,model,audio,font,text,shader,script
|
||||
0=video,flac,ogg,wav,mp1,mp3,jpg,png,atlas,tiled
|
||||
0=video,flac,ogg,wav,mp1,mp3,jpg,png,atlas,tiled
|
Loading…
Reference in New Issue