// scene demo
// - rlyeh, public domain

#include "v4k.h"

int main() {
    // options
    bool  do_twosided = 1;
    bool  do_wireframe = 0;
    bool  do_billboard_x = 0, do_billboard_y = 0, do_billboard_z = 0;

    // 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", 0);
    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