<NME> level_editor.cpp
<BEF> ADDFILE
<MSG> PLAYGR-23 - Level editor - basic level viewport

<DFF> @@ -0,0 +1,156 @@
+#include <cetech/engine/entity/entity.h>
+#include <cetech/modules/renderer/renderer.h>
+#include <cetech/modules/debugui/debugui.h>
+#include <cetech/engine/application/application.h>
+#include <cetech/modules/level/level.h>
+#include <cetech/modules/camera/camera.h>
+#include <cetech/modules/playground/level_editor.h>
+#include <cstdio>
+#include "celib/map.inl"
+
+#include "cetech/core/hashlib/hashlib.h"
+#include "cetech/core/config/config.h"
+#include "cetech/core/memory/memory.h"
+#include "cetech/core/api/api_system.h"
+#include "cetech/core/module/module.h"
+
+CETECH_DECL_API(ct_memory_a0);
+CETECH_DECL_API(ct_renderer_a0);
+CETECH_DECL_API(ct_hash_a0);
+CETECH_DECL_API(ct_debugui_a0);
+CETECH_DECL_API(ct_app_a0);
+CETECH_DECL_API(ct_world_a0);
+CETECH_DECL_API(ct_level_a0);
+CETECH_DECL_API(ct_entity_a0);
+CETECH_DECL_API(ct_camera_a0);
+
+using namespace celib;
+
+#define MAX_LEVEL_EDITOR 8
+
+static struct {
+    bool visible[MAX_LEVEL_EDITOR];
+    ct_viewport viewport[MAX_LEVEL_EDITOR];
+    ct_world world[MAX_LEVEL_EDITOR];
+    ct_camera camera[MAX_LEVEL_EDITOR];
+    ct_entity camera_ent[MAX_LEVEL_EDITOR];
+
+    uint8_t editor_count;
+} _G;
+
+namespace level_view {
+    void gui() {
+//    fps_camera_update(_G.world, _G.camera_ent, 16 * 0.00001f, 0, 0, 1.0f, 0.0f,
+//                      0);
+
+        char dock_id[32] = {};
+
+        for (uint8_t i = 0; i < _G.editor_count; ++i) {
+            snprintf(dock_id, CETECH_ARRAY_LEN(dock_id), "Level view #%d", i+1);
+
+            if (ct_debugui_a0.BeginDock(dock_id, &_G.visible[i],
+                                        DebugUIWindowFlags_Empty)) {
+                auto th = ct_renderer_a0.viewport_get_local_resource(
+                        _G.viewport[i], ct_hash_a0.id64_from_str("bb_color"));
+
+                float size[2];
+                ct_debugui_a0.GetWindowSize(size);
+                ct_renderer_a0.resize_viewport(_G.viewport[i], size[0], size[1]);
+                ct_debugui_a0.Image2({th},
+                                     size,
+                                     (float[2]) {0.0f, 0.0f},
+                                     (float[2]) {1.0f, 1.0f},
+                                     (float[4]) {1.0f, 1.0f, 1.0f, 1.0f},
+                                     (float[4]) {0.0f, 0.0f, 0.0, 0.0f});
+            }
+            ct_debugui_a0.EndDock();
+        }
+    }
+
+    void render() {
+        for (uint8_t i = 0; i < _G.editor_count; ++i) {
+            ct_renderer_a0.render_world(_G.world[i], _G.camera[i],
+                                        _G.viewport[i]);
+        }
+    }
+
+    void open_level() {
+        uint8_t idx = _G.editor_count;
+        ++_G.editor_count;
+
+        _G.visible[idx] = true;
+
+        _G.viewport[idx] = ct_renderer_a0.create_viewport(
+                ct_hash_a0.id64_from_str("default"), 0, 0);
+
+        _G.world[idx] = ct_world_a0.create();
+
+        _G.camera_ent[idx] = ct_entity_a0.spawn(_G.world[idx],
+                                                ct_hash_a0.id64_from_str(
+                                                        "camera"));
+
+        _G.camera[idx] = ct_camera_a0.get(_G.world[idx], _G.camera_ent[idx]);
+
+        ct_level_a0.load_level(_G.world[idx],
+                               ct_hash_a0.id64_from_str("level1"));
+    }
+
+    void init() {
+        open_level();
+        open_level();
+    }
+
+    void shutdown() {
+
+    }
+}
+
+namespace level_view_module {
+
+    static ct_level_view_a0 api = {
+//            .register_module = playground::register_module,
+//            .unregister_module = playground::unregister_module,
+    };
+
+    static void _init(ct_api_a0 *api) {
+        api->register_api("ct_level_view_a0", &api);
+
+        _G = {};
+
+        ct_app_a0.register_on_init(level_view::init);
+        ct_app_a0.register_on_shutdown(level_view::shutdown);
+        ct_app_a0.register_on_render(level_view::render);
+        ct_debugui_a0.register_on_gui(level_view::gui);
+    }
+
+    static void _shutdown() {
+        ct_app_a0.unregister_on_init(level_view::init);
+        ct_app_a0.unregister_on_shutdown(level_view::shutdown);
+        ct_app_a0.unregister_on_render(level_view::render);
+        ct_debugui_a0.unregister_on_gui(level_view::gui);
+
+        _G = {};
+    }
+}
+
+CETECH_MODULE_DEF(
+        level_view,
+        {
+            CETECH_GET_API(api, ct_memory_a0);
+            CETECH_GET_API(api, ct_hash_a0);
+            CETECH_GET_API(api, ct_renderer_a0);
+            CETECH_GET_API(api, ct_debugui_a0);
+            CETECH_GET_API(api, ct_app_a0);
+            CETECH_GET_API(api, ct_world_a0);
+            CETECH_GET_API(api, ct_level_a0);
+            CETECH_GET_API(api, ct_entity_a0);
+            CETECH_GET_API(api, ct_camera_a0);
+        },
+        {
+            level_view_module::_init(api);
+        },
+        {
+            CEL_UNUSED(api);
+            level_view_module::_shutdown();
+        }
+)
\ No newline at end of file

{'commit': 'diff --git a/CMakeLists.txt b/CMakeLists.txt\nindex 7af3e7a71..7aac78ce5 100644\n--- a/CMakeLists.txt\n+++ b/CMakeLists.txt\n@@ -74,7 +74,9 @@ set(SOURCE_FILES\n         src/cetech/modules/debugui/private/ocornut-imgui/imgui.cpp\n         src/cetech/modules/debugui/private/ocornut-imgui/imgui_draw.cpp\n         src/cetech/modules/debugui/private/debugui.cpp\n+\n         src/cetech/modules/playground/private/playground.cpp\n+        src/cetech/modules/playground/private/level_editor.cpp\n \n         src/cetech/engine/machine/private/window_sdl2.cpp\n         src/cetech/engine/machine/private/machine_sdl2.cpp\ndiff --git a/examples/develop/src/fs_copy.sc b/examples/develop/src/fs_copy.sc\nindex 2ac0c5a56..4fbaf5f71 100644\n--- a/examples/develop/src/fs_copy.sc\n+++ b/examples/develop/src/fs_copy.sc\n@@ -10,4 +10,7 @@ void main()\n     gl_FragData[0] = vec4(gray, gray, gray, 1.0f);\n \n //    gl_FragData[0] = texture2D(s_input_texture,  v_texcoord0);\n+//    gl_FragData[0] = texture2D(s_input_texture,  v_texcoord0) * vec4(0.0, 1.0, 0.0, 1.0);\n+//    gl_FragData[0] = texture2D(s_input_texture,  v_texcoord0) * vec4(0.0, 1.0, 0.0, 1.0);\n+//    gl_FragData[0] = vec4(v_texcoord0, 0.0f, 1.0f);\n }\n\\ No newline at end of file\ndiff --git a/examples/module_example/example.cpp b/examples/module_example/example.cpp\nindex c6a64fc89..b4476fe42 100644\n--- a/examples/module_example/example.cpp\n+++ b/examples/module_example/example.cpp\n@@ -12,6 +12,10 @@\n #include <cetech/core/hashlib/hashlib.h>\n #include <cetech/engine/entity/entity.h>\n #include <cetech/modules/renderer/renderer.h>\n+#include <cetech/modules/transform/transform.h>\n+#include <celib/fpumath.h>\n+#include <cetech/modules/camera/camera.h>\n+#include <cetech/modules/level/level.h>\n \n CETECH_DECL_API(ct_log_a0)\n CETECH_DECL_API(ct_app_a0)\n@@ -19,8 +23,79 @@ CETECH_DECL_API(ct_keyboard_a0)\n CETECH_DECL_API(ct_playground_a0)\n CETECH_DECL_API(ct_debugui_a0)\n CETECH_DECL_API(ct_hash_a0)\n+\n CETECH_DECL_API(ct_renderer_a0)\n \n+CETECH_DECL_API(ct_transform_a0);\n+CETECH_DECL_API(ct_world_a0);\n+CETECH_DECL_API(ct_entity_a0);\n+CETECH_DECL_API(ct_camera_a0);\n+CETECH_DECL_API(ct_level_a0);\n+\n+\n+static struct G {\n+    ct_viewport viewport;\n+    ct_world world;\n+    ct_camera camera;\n+    ct_entity camera_ent;\n+} _G;\n+\n+void fps_camera_update(ct_world world,\n+                       ct_entity camera_ent,\n+                       float dt,\n+                       float dx,\n+                       float dy,\n+                       float updown,\n+                       float leftright,\n+                       bool fly_mode) {\n+    float pos[3];\n+    float rot[4];\n+    float wm[16];\n+\n+    auto transform = ct_transform_a0.get(world, camera_ent);\n+\n+    ct_transform_a0.get_position(transform, pos);\n+    ct_transform_a0.get_rotation(transform, rot);\n+    ct_transform_a0.get_world_matrix(transform, wm);\n+\n+    float x_dir[4];\n+    float z_dir[4];\n+    celib::vec4_move(x_dir, &wm[0 * 4]);\n+    celib::vec4_move(z_dir, &wm[3 * 4]);\n+\n+\n+    if (fly_mode) {\n+        z_dir[1] = 0.0f;\n+    }\n+\n+    // POS\n+    float x_dir_new[3];\n+    float z_dir_new[3];\n+\n+    celib::vec3_mul(x_dir_new, x_dir, dt * leftright);\n+    celib::vec3_mul(z_dir_new, z_dir, dt * updown);\n+\n+    celib::vec3_add(pos, pos, x_dir_new);\n+    celib::vec3_add(pos, pos, z_dir_new);\n+\n+    // ROT\n+//    float rotation_around_world_up[4];\n+//    float rotation_around_camera_right[4];\n+//\n+//\n+//\n+//    local rotation_around_world_up = Quatf.from_axis_angle(Vec3f.unit_y(), -dx * dt * 100)\n+//    local rotation_around_camera_right = Quatf.from_axis_angle(x_dir, dy * dt * 100)\n+//    local rotation = rotation_around_world_up * rotation_around_camera_right\n+//\n+//    Transform.set_position(self.transform, pos)\n+//    Transform.set_rotation(self.transform, rot * rotation)\n+//    end\n+\n+   // ct_transform_a0.set_position(transform, pos);\n+}\n+\n+\n void update(float dt) {\n     if (ct_keyboard_a0.button_state(0, ct_keyboard_a0.button_index("v"))) {\n         ct_log_a0.info("example", "PO");\n@@ -30,40 +105,50 @@ void update(float dt) {\n     ///ct_log_a0.debug("example", "%f", dt);\n }\n \n-static struct ct_playground_module module1 = {\n-        .name = "Module 1",\n-        .on_gui = []() {\n-            ct_debugui_a0.Text("dear imgui, %d", 111);\n+void module1() {\n+    static bool visible = true;\n+    if (ct_debugui_a0.BeginDock("Module 1", &visible,\n+                                DebugUIWindowFlags_Empty)) {\n+\n+\n+        ct_debugui_a0.Text("dear imgui, %d", 111);\n \n //            static float v[2] = {100.0f, 100.0f};\n //            if(ct_debugui_a0.Button("wwwwww", v)) {\n //                ct_log_a0.info("dasdsa", "dsadsadsadsad");\n //            }\n \n-            static float col[4] = {0.0f, 1.0f, 0.0f, 0.0f};\n-            ct_debugui_a0.ColorButton(col, 1, 2);\n+        static float col[4] = {0.0f, 1.0f, 0.0f, 0.0f};\n+        ct_debugui_a0.ColorButton(col, 1, 2);\n \n-            static float vv;\n-            ct_debugui_a0.DragFloat("FOO:", &vv, 1.0f, 0.0f, 10000.0f, "%.3f",\n-                                    1.0f);\n+        static float vv;\n+        ct_debugui_a0.DragFloat("FOO:", &vv, 1.0f, 0.0f, 10000.0f, "%.3f",\n+                                1.0f);\n+\n+        static float col2[4] = {0.0f, 1.0f, 0.0f, 0.0f};\n+        ct_debugui_a0.ColorEdit3("COLOR", col2);\n+\n+        static float col3[4] = {0.0f, 1.0f, 0.0f, 0.0f};\n+        ct_debugui_a0.ColorWheel("WHEEE", col3, 0.2f);\n+\n+    }\n+    ct_debugui_a0.EndDock();\n+\n+}\n+\n+void module2() {\n+    static bool visible = true;\n+    if (ct_debugui_a0.BeginDock("Module 2", &visible,\n+                                DebugUIWindowFlags_Empty)) {\n+        ct_debugui_a0.Text("dear imgui, %d", 111);\n+        ct_debugui_a0.Text("By Omar Cornut and all github contributors.");\n+        ct_debugui_a0.Text(\n+                "ImGui is licensed under the MIT License, see LICENSE for more information.");\n+    }\n+    ct_debugui_a0.EndDock();\n+}\n \n-            static float col2[4] = {0.0f, 1.0f, 0.0f, 0.0f};\n-            ct_debugui_a0.ColorEdit3("COLOR", col2);\n \n-            static float col3[4] = {0.0f, 1.0f, 0.0f, 0.0f};\n-            ct_debugui_a0.ColorWheel("WHEEE", col3, 0.2f);\n-        },\n-};\n-\n-static struct ct_playground_module module2 = {\n-        .name = "Module 2",\n-        .on_gui = []() {\n-            ct_debugui_a0.Text("dear imgui, %d", 111);\n-            ct_debugui_a0.Text("By Omar Cornut and all github contributors.");\n-            ct_debugui_a0.Text(\n-                    "ImGui is licensed under the MIT License, see LICENSE for more information.");\n-        },\n-};\n \n //==============================================================================\n // Module def\n@@ -82,6 +167,13 @@ CETECH_MODULE_DEF(\n             CETECH_GET_API(api, ct_debugui_a0);\n             CETECH_GET_API(api, ct_hash_a0);\n             CETECH_GET_API(api, ct_renderer_a0);\n+\n+\n+            CETECH_GET_API(api, ct_transform_a0);\n+            CETECH_GET_API(api, ct_world_a0);\n+            CETECH_GET_API(api, ct_entity_a0);\n+            CETECH_GET_API(api, ct_camera_a0);\n+            CETECH_GET_API(api, ct_level_a0);\n         },\n \n //==============================================================================\n@@ -91,16 +183,11 @@ CETECH_MODULE_DEF(\n             CEL_UNUSED(api);\n \n             ct_log_a0.info("example", "Init %d", reload);\n-            ct_app_a0.register_on_update(update);\n \n+            ct_app_a0.register_on_update(update);\n \n-            if (reload) {\n-                ct_playground_a0.unregister_module(module1);\n-                ct_playground_a0.unregister_module(module2);\n-            }\n-\n-            ct_playground_a0.register_module(module1);\n-            ct_playground_a0.register_module(module2);\n+            ct_debugui_a0.register_on_gui(module1);\n+            ct_debugui_a0.register_on_gui(module2);\n         },\n \n //==============================================================================\n@@ -110,11 +197,10 @@ CETECH_MODULE_DEF(\n             CEL_UNUSED(api);\n \n             ct_log_a0.info("example", "Shutdown %d", reload);\n+\n             ct_app_a0.unregister_on_update(update);\n \n-            if (!reload) {\n-                ct_playground_a0.unregister_module(module1);\n-                ct_playground_a0.unregister_module(module2);\n-            }\n+            ct_debugui_a0.unregister_on_gui(module1);\n+            ct_debugui_a0.unregister_on_gui(module2);\n         }\n )\ndiff --git a/src/cetech/modules/debugui/debugui.h b/src/cetech/modules/debugui/debugui.h\nindex cd2254d3c..640676d27 100644\n--- a/src/cetech/modules/debugui/debugui.h\n+++ b/src/cetech/modules/debugui/debugui.h\n@@ -12,6 +12,8 @@ extern "C" {\n \n #include <stddef.h>\n \n+struct ct_texture;\n+\n typedef float _vec4[4];\n typedef float _vec2[2];\n \n@@ -32,7 +34,7 @@ typedef int (*ImGuiTextEditCallback)(ImGuiTextEditCallbackData *data);\n typedef void (*ImGuiSizeConstraintCallback)(ImGuiSizeConstraintCallbackData *data);\n \n enum DebugUIWindowFlags_ {\n-\n+    DebugUIWindowFlags_Empty = 0,\n     DebugUIWindowFlags_NoTitleBar = 1 << 0,   //!< Disable title-bar\n     DebugUIWindowFlags_NoResize =\n     1 << 1,   //!< Disable user resizing with the lower-right grip\n@@ -178,8 +180,9 @@ enum DebugUISetCond_ {\n //!<! DebugUI API V0\n struct ct_debugui_a0 {\n     void (*render)(uint8_t viewid);\n-\n     void (*register_on_gui)(void (*on_gui)());\n+    void (*unregister_on_gui)(void (*on_gui)());\n+\n \n     void (*Text)(const char *fmt,\n                  ...) CTECH_ATTR_FORMAT(1, 2);\n@@ -234,13 +237,6 @@ struct ct_debugui_a0 {\n     bool (*InvisibleButton)(const char *str_id,\n                             const _vec2 size);\n \n-    void (*Image)(ImTextureID user_texture_id,\n-                  const _vec2 size,\n-                  const _vec2 uv0,\n-                  const _vec2 uv1,\n-                  const _vec4 tint_col,\n-                  const _vec4 border_col);\n-\n     void (*Image2)(struct ct_texture user_texture_id,\n                    const _vec2 size,\n                    const _vec2 uv0,\n@@ -733,6 +729,9 @@ struct ct_debugui_a0 {\n                         float size);\n \n     void (*GetWindowSize)(float size[2]);\n+\n+    bool (*BeginDock)(const char* label, bool* opened, DebugUIWindowFlags_ extra_flags);\n+    void (*EndDock)();\n };\n \n #ifdef __cplusplus\ndiff --git a/src/cetech/modules/debugui/private/debugui.cpp b/src/cetech/modules/debugui/private/debugui.cpp\nindex 0d3354939..c10199588 100644\n--- a/src/cetech/modules/debugui/private/debugui.cpp\n+++ b/src/cetech/modules/debugui/private/debugui.cpp\n@@ -74,9 +74,30 @@ namespace debugui {\n         imguiEndFrame();\n     }\n \n-    void register_on_gui(void (*on_gui)()) {\n-        array::push_back(_G.on_gui, on_gui);\n+    typedef void (*on_gui)();\n+\n+#define _DEF_ON_CLB_FCE(type, name)                                            \\\n+    static void register_ ## name ## _(type name) {                                   \\\n+        celib::array::push_back(_G.name, name);                                \\\n+    }                                                                          \\\n+    static void unregister_## name ## _(type name) {                                  \\\n+        const auto size = celib::array::size(_G.name);                         \\\n+                                                                               \\\n+        for(uint32_t i = 0; i < size; ++i) {                                   \\\n+            if(_G.name[i] != name) {                                           \\\n+                continue;                                                      \\\n+            }                                                                  \\\n+                                                                               \\\n+            uint32_t last_idx = size - 1;                                      \\\n+            _G.name[i] = _G.name[last_idx];                                    \\\n+                                                                               \\\n+            celib::array::pop_back(_G.name);                                   \\\n+            break;                                                             \\\n+        }                                                                      \\\n     }\n+\n+    _DEF_ON_CLB_FCE(on_gui, on_gui);\n+\n }\n \n static void on_render() {\n@@ -87,7 +108,9 @@ namespace debugui_module {\n \n     static ct_debugui_a0 debugui_api = {\n             .render = debugui::render,\n-            .register_on_gui = debugui::register_on_gui,\n+\n+            .register_on_gui = debugui::register_on_gui_,\n+            .unregister_on_gui = debugui::unregister_on_gui_,\n \n             .Text = imgui_wrap::Text,\n             .TextV = imgui_wrap::TextV,\n@@ -106,7 +129,6 @@ namespace debugui_module {\n             .Button = imgui_wrap::Button,\n             .SmallButton = imgui_wrap::SmallButton,\n             .InvisibleButton = imgui_wrap::InvisibleButton,\n-            .Image = imgui_wrap::Image,\n             .Image2 = imgui_wrap::Image2,\n             .ImageButton = imgui_wrap::ImageButton,\n             .Checkbox = imgui_wrap::Checkbox,\n@@ -210,6 +232,9 @@ namespace debugui_module {\n             .ColorWheel = imgui_wrap::ColorWheel,\n             .ColorWheel2 = imgui_wrap::ColorWheel2,\n             .GetWindowSize = imgui_wrap::GetWindowSize,\n+            .BeginDock = imgui_wrap::BeginDock,\n+            .EndDock = imgui_wrap::EndDock,\n+\n     };\n \n     static void _init(ct_api_a0 *api) {\ndiff --git a/src/cetech/modules/debugui/private/imgui_wrap.inl b/src/cetech/modules/debugui/private/imgui_wrap.inl\nindex 1f2756f13..1d4e189e9 100644\n--- a/src/cetech/modules/debugui/private/imgui_wrap.inl\n+++ b/src/cetech/modules/debugui/private/imgui_wrap.inl\n@@ -1130,4 +1130,14 @@ namespace imgui_wrap {\n         size[0] = v.x;\n         size[1] = v.y;\n     }\n+\n+    bool BeginDock(const char* label, bool* opened, DebugUIWindowFlags_ extra_flags)\n+    {\n+        return ImGui::BeginDock(label, opened,extra_flags);\n+    }\n+\n+    void EndDock()\n+    {\n+        ImGui::EndDock();\n+    }\n }\ndiff --git a/src/cetech/modules/playground/level_editor.h b/src/cetech/modules/playground/level_editor.h\nnew file mode 100644\nindex 000000000..329a70758\n--- /dev/null\n+++ b/src/cetech/modules/playground/level_editor.h\n@@ -0,0 +1,27 @@\n+#ifndef CETECH_LEVEL_VIEW_H\n+#define CETECH_LEVEL_VIEW_H\n+\n+#ifdef __cplusplus\n+extern "C" {\n+#endif\n+\n+//==============================================================================\n+// Includes\n+//==============================================================================\n+\n+#include <stddef.h>\n+\n+\n+//==============================================================================\n+// Api\n+//==============================================================================\n+\n+struct ct_level_view_a0 {\n+      void (*_)();\n+};\n+\n+#ifdef __cplusplus\n+}\n+#endif\n+\n+#endif //CETECH_LEVEL_VIEW_H\ndiff --git a/src/cetech/modules/playground/playground.h b/src/cetech/modules/playground/playground.h\nindex 0064dc0cc..427f0776b 100644\n--- a/src/cetech/modules/playground/playground.h\n+++ b/src/cetech/modules/playground/playground.h\n@@ -12,14 +12,14 @@ extern "C" {\n #include <stddef.h>\n \n \n-struct ct_playground_module {\n-    const char* name;\n-    void (*on_gui)();\n-    void (*on_init)();\n-    void (*on_shutdown)();\n-    void (*on_update)(float dt);\n-    void (*on_render)();\n-};\n+//struct ct_playground_module {\n+//    const char* name;\n+//    void (*on_gui)();\n+//    void (*on_init)();\n+//    void (*on_shutdown)();\n+//    void (*on_update)(float dt);\n+//    void (*on_render)();\n+//};\n \n //==============================================================================\n // Api\n@@ -27,8 +27,7 @@ struct ct_playground_module {\n \n //! Playground API V0\n struct ct_playground_a0 {\n-    void (*register_module)(ct_playground_module module);\n-    void (*unregister_module)(ct_playground_module module);\n+      void (*_)();\n };\n \n #ifdef __cplusplus\ndiff --git a/src/cetech/modules/playground/private/level_editor.cpp b/src/cetech/modules/playground/private/level_editor.cpp\nnew file mode 100644\nindex 000000000..4f419f62d\n--- /dev/null\n+++ b/src/cetech/modules/playground/private/level_editor.cpp\n@@ -0,0 +1,156 @@\n+#include <cetech/engine/entity/entity.h>\n+#include <cetech/modules/renderer/renderer.h>\n+#include <cetech/modules/debugui/debugui.h>\n+#include <cetech/engine/application/application.h>\n+#include <cetech/modules/level/level.h>\n+#include <cetech/modules/camera/camera.h>\n+#include <cetech/modules/playground/level_editor.h>\n+#include <cstdio>\n+#include "celib/map.inl"\n+\n+#include "cetech/core/hashlib/hashlib.h"\n+#include "cetech/core/config/config.h"\n+#include "cetech/core/memory/memory.h"\n+#include "cetech/core/api/api_system.h"\n+#include "cetech/core/module/module.h"\n+\n+CETECH_DECL_API(ct_memory_a0);\n+CETECH_DECL_API(ct_renderer_a0);\n+CETECH_DECL_API(ct_hash_a0);\n+CETECH_DECL_API(ct_debugui_a0);\n+CETECH_DECL_API(ct_app_a0);\n+CETECH_DECL_API(ct_world_a0);\n+CETECH_DECL_API(ct_level_a0);\n+CETECH_DECL_API(ct_entity_a0);\n+CETECH_DECL_API(ct_camera_a0);\n+\n+using namespace celib;\n+\n+#define MAX_LEVEL_EDITOR 8\n+\n+static struct {\n+    bool visible[MAX_LEVEL_EDITOR];\n+    ct_viewport viewport[MAX_LEVEL_EDITOR];\n+    ct_world world[MAX_LEVEL_EDITOR];\n+    ct_camera camera[MAX_LEVEL_EDITOR];\n+    ct_entity camera_ent[MAX_LEVEL_EDITOR];\n+\n+    uint8_t editor_count;\n+} _G;\n+\n+namespace level_view {\n+    void gui() {\n+//    fps_camera_update(_G.world, _G.camera_ent, 16 * 0.00001f, 0, 0, 1.0f, 0.0f,\n+//                      0);\n+\n+        char dock_id[32] = {};\n+\n+        for (uint8_t i = 0; i < _G.editor_count; ++i) {\n+            snprintf(dock_id, CETECH_ARRAY_LEN(dock_id), "Level view #%d", i+1);\n+\n+            if (ct_debugui_a0.BeginDock(dock_id, &_G.visible[i],\n+                                        DebugUIWindowFlags_Empty)) {\n+                auto th = ct_renderer_a0.viewport_get_local_resource(\n+                        _G.viewport[i], ct_hash_a0.id64_from_str("bb_color"));\n+\n+                float size[2];\n+                ct_debugui_a0.GetWindowSize(size);\n+                ct_renderer_a0.resize_viewport(_G.viewport[i], size[0], size[1]);\n+                ct_debugui_a0.Image2({th},\n+                                     size,\n+                                     (float[2]) {0.0f, 0.0f},\n+                                     (float[2]) {1.0f, 1.0f},\n+                                     (float[4]) {1.0f, 1.0f, 1.0f, 1.0f},\n+                                     (float[4]) {0.0f, 0.0f, 0.0, 0.0f});\n+            }\n+            ct_debugui_a0.EndDock();\n+        }\n+    }\n+\n+    void render() {\n+        for (uint8_t i = 0; i < _G.editor_count; ++i) {\n+            ct_renderer_a0.render_world(_G.world[i], _G.camera[i],\n+                                        _G.viewport[i]);\n+        }\n+    }\n+\n+    void open_level() {\n+        uint8_t idx = _G.editor_count;\n+        ++_G.editor_count;\n+\n+        _G.visible[idx] = true;\n+\n+        _G.viewport[idx] = ct_renderer_a0.create_viewport(\n+                ct_hash_a0.id64_from_str("default"), 0, 0);\n+\n+        _G.world[idx] = ct_world_a0.create();\n+\n+        _G.camera_ent[idx] = ct_entity_a0.spawn(_G.world[idx],\n+                                                ct_hash_a0.id64_from_str(\n+                                                        "camera"));\n+\n+        _G.camera[idx] = ct_camera_a0.get(_G.world[idx], _G.camera_ent[idx]);\n+\n+        ct_level_a0.load_level(_G.world[idx],\n+                               ct_hash_a0.id64_from_str("level1"));\n+    }\n+\n+    void init() {\n+        open_level();\n+        open_level();\n+    }\n+\n+    void shutdown() {\n+\n+    }\n+}\n+\n+namespace level_view_module {\n+\n+    static ct_level_view_a0 api = {\n+//            .register_module = playground::register_module,\n+//            .unregister_module = playground::unregister_module,\n+    };\n+\n+    static void _init(ct_api_a0 *api) {\n+        api->register_api("ct_level_view_a0", &api);\n+\n+        _G = {};\n+\n+        ct_app_a0.register_on_init(level_view::init);\n+        ct_app_a0.register_on_shutdown(level_view::shutdown);\n+        ct_app_a0.register_on_render(level_view::render);\n+        ct_debugui_a0.register_on_gui(level_view::gui);\n+    }\n+\n+    static void _shutdown() {\n+        ct_app_a0.unregister_on_init(level_view::init);\n+        ct_app_a0.unregister_on_shutdown(level_view::shutdown);\n+        ct_app_a0.unregister_on_render(level_view::render);\n+        ct_debugui_a0.unregister_on_gui(level_view::gui);\n+\n+        _G = {};\n+    }\n+}\n+\n+CETECH_MODULE_DEF(\n+        level_view,\n+        {\n+            CETECH_GET_API(api, ct_memory_a0);\n+            CETECH_GET_API(api, ct_hash_a0);\n+            CETECH_GET_API(api, ct_renderer_a0);\n+            CETECH_GET_API(api, ct_debugui_a0);\n+            CETECH_GET_API(api, ct_app_a0);\n+            CETECH_GET_API(api, ct_world_a0);\n+            CETECH_GET_API(api, ct_level_a0);\n+            CETECH_GET_API(api, ct_entity_a0);\n+            CETECH_GET_API(api, ct_camera_a0);\n+        },\n+        {\n+            level_view_module::_init(api);\n+        },\n+        {\n+            CEL_UNUSED(api);\n+            level_view_module::_shutdown();\n+        }\n+)\n\\ No newline at end of file\ndiff --git a/src/cetech/modules/playground/private/playground.cpp b/src/cetech/modules/playground/private/playground.cpp\nindex 3bc72f7d4..d8e9d5184 100644\n--- a/src/cetech/modules/playground/private/playground.cpp\n+++ b/src/cetech/modules/playground/private/playground.cpp\n@@ -1,6 +1,5 @@\n #include <cetech/engine/entity/entity.h>\n #include <cetech/modules/renderer/renderer.h>\n-#include <cetech/core/blob/blob.h>\n #include <cetech/modules/debugui/debugui.h>\n #include <cetech/modules/debugui/private/bgfx_imgui/imgui.h>\n #include <cetech/modules/playground/playground.h>\n@@ -30,56 +29,12 @@ using namespace celib;\n static struct PlaygroundGlobal {\n     uint64_t type;\n \n-    Map<ct_playground_module> module_map;\n-\n     ct_viewport viewport;\n     ct_world world;\n     ct_camera camera;\n } _G;\n \n namespace playground {\n-    void register_module(ct_playground_module module) {\n-        uint64_t h = ct_hash_a0.id64_from_str(module.name);\n-        map::set(_G.module_map, h, module);\n-\n-        if(module.on_init) {\n-            ct_app_a0.register_on_init(module.on_init);\n-        }\n-\n-        if(module.on_shutdown) {\n-            ct_app_a0.register_on_shutdown(module.on_shutdown);\n-        }\n-\n-        if(module.on_update) {\n-            ct_app_a0.register_on_update(module.on_update);\n-        }\n-\n-        if(module.on_render) {\n-            ct_renderer_a0.register_on_render(module.on_render);\n-        }\n-    }\n-\n-    void unregister_module(ct_playground_module module) {\n-        uint64_t h = ct_hash_a0.id64_from_str(module.name);\n-        map::remove(_G.module_map, h);\n-\n-        if(module.on_init) {\n-            ct_app_a0.unregister_on_init(module.on_init);\n-        }\n-\n-        if(module.on_shutdown) {\n-            ct_app_a0.unregister_on_shutdown(module.on_shutdown);\n-        }\n-\n-        if(module.on_update) {\n-            ct_app_a0.unregister_on_update(module.on_update);\n-        }\n-\n-        if(module.on_render) {\n-            ct_renderer_a0.unregister_on_render(module.on_render);\n-        }\n-    }\n-\n     float draw_main_menu() {\n         float menu_height = 0;\n         if (ImGui::BeginMainMenuBar()) {\n@@ -116,9 +71,6 @@ namespace playground {\n     }\n \n     void on_gui() {\n-        auto ct_it = celib::map::begin(_G.module_map);\n-        auto ct_end = celib::map::end(_G.module_map);\n-\n         auto menu_height = draw_main_menu();\n \n         uint32_t w, h;\n@@ -126,62 +78,14 @@ namespace playground {\n         auto pos = ImVec2(0, menu_height);\n \n         ImGui::RootDock(pos, ImVec2(w, h - 25.0f));\n-\n-        bool en = true;\n-        while (ct_it != ct_end) {\n-            auto module = ct_it->value;\n-\n-            if (ImGui::BeginDock(module.name, &en)) {\n-                module.on_gui();\n-            }\n-            ImGui::EndDock();\n-\n-            ++ct_it;\n-        }\n     }\n }\n \n-static struct ct_playground_module engine_viewport = {\n-        .name = "Render",\n-        .on_shutdown = 0,\n-        .on_init = []() {\n-            _G.viewport = ct_renderer_a0.create_viewport(\n-                    ct_hash_a0.id64_from_str("default"), 0, 0);\n-\n-            _G.world = ct_world_a0.create();\n-\n-            auto camera_ent = ct_entity_a0.spawn(_G.world, ct_hash_a0.id64_from_str("camera"));\n-            _G.camera = ct_camera_a0.get(_G.world, camera_ent);\n-\n-            ct_level_a0.load_level(_G.world, ct_hash_a0.id64_from_str("level1"));\n-        },\n-\n-        .on_gui = []() {\n-            auto th = ct_renderer_a0.viewport_get_local_resource(\n-                    _G.viewport,\n-                    ct_hash_a0.id64_from_str("bb_color"));\n-\n-            float size[2];\n-            ct_debugui_a0.GetWindowSize(size);\n-\n-            ct_debugui_a0.Image2({th},\n-                                 size,\n-                                 (float[2]) {0.0f, 0.0f},\n-                                 (float[2]) {1.0f, 1.0f},\n-                                 (float[4]) {1.0f, 1.0f, 1.0f, 1.0f},\n-                                 (float[4]) {0.0f, 0.0f, 0.0, 0.0f});\n-        },\n-\n-        .on_render = [](){\n-            ct_renderer_a0.render_world(_G.world, _G.camera, _G.viewport);\n-        }\n-};\n-\n namespace playground_module {\n \n     static ct_playground_a0 playground_api = {\n-            .register_module = playground::register_module,\n-            .unregister_module = playground::unregister_module,\n+//            .register_module = playground::register_module,\n+//            .unregister_module = playground::unregister_module,\n     };\n \n \n@@ -191,16 +95,9 @@ namespace playground_module {\n         ct_debugui_a0.register_on_gui(playground::on_gui);\n \n         _G = {};\n-        _G.module_map.init(ct_memory_a0.main_allocator());\n-\n-        playground::register_module(engine_viewport);\n     }\n \n     static void _shutdown() {\n-        _G.module_map.destroy();\n-\n-        playground::unregister_module(engine_viewport);\n-\n         _G = {};\n     }\n }\ndiff --git a/src/cetech/modules/renderer/private/material/material.cpp b/src/cetech/modules/renderer/private/material/material.cpp\nindex cfa0e9c6d..638524f51 100644\n--- a/src/cetech/modules/renderer/private/material/material.cpp\n+++ b/src/cetech/modules/renderer/private/material/material.cpp\n@@ -191,7 +191,7 @@ namespace material {\n                     ut = bgfx::UniformType::Int1;\n                     break;\n                 case MAT_VAR_TEXTURE:\n-                case MAT_VAR_TEXTURE2:\n+                case MAT_VAR_TEXTURE_HANDLER:\n                     ut = bgfx::UniformType::Int1;\n                     break;\n                 case MAT_VAR_VEC4:\n@@ -241,9 +241,10 @@ namespace material {\n         return UINT32_MAX;\n     }\n \n-    void set_texture2(struct ct_material material,\n-                      const char *slot,\n-                      ct_texture texture) {\n+    void set_texture_handler(struct ct_material material,\n+                             const char *slot,\n+                             ct_texture texture) {\n+\n         uint32_t idx = map::get(_G.instace_map, material.idx,\n                                 UINT32_MAX);\n \n@@ -255,8 +256,8 @@ namespace material {\n         auto *uniforms = material_blob::uniforms(resource);\n \n         int slot_idx = _find_uniform_slot(resource, slot);\n-        uniforms[slot_idx].t = texture.idx;\n-        uniforms[slot_idx].type = MAT_VAR_TEXTURE2;\n+        uniforms[slot_idx].th = texture.idx;\n+        uniforms[slot_idx].type = MAT_VAR_TEXTURE_HANDLER;\n     }\n \n     void set_texture(ct_material material,\n@@ -341,11 +342,8 @@ namespace material {\n                 }\n                     break;\n \n-                //TODO : dklsamdlsamkdm????\n-                case MAT_VAR_TEXTURE2: {\n-                    bgfx::setTexture(texture_stage, u_handler[i], {\n-                            static_cast<uint16_t>(uniform.t)});\n-\n+                case MAT_VAR_TEXTURE_HANDLER: {\n+                    bgfx::setTexture(texture_stage, u_handler[i], {uniform.th});\n                     ++texture_stage;\n                 }\n                     break;\n@@ -364,8 +362,7 @@ namespace material {\n                           | BGFX_STATE_DEPTH_TEST_LESS\n                           | BGFX_STATE_DEPTH_WRITE\n                           | BGFX_STATE_CULL_CCW\n-                          | BGFX_STATE_MSAA\n-        );\n+                          | BGFX_STATE_MSAA );\n \n         bgfx::setState(state, 0);\n                 \ndiff --git a/src/cetech/modules/renderer/private/material/material.h b/src/cetech/modules/renderer/private/material/material.h\nindex b6036787f..1e1338ecc 100644\n--- a/src/cetech/modules/renderer/private/material/material.h\n+++ b/src/cetech/modules/renderer/private/material/material.h\n@@ -5,7 +5,7 @@ enum material_variable_type {\n     MAT_VAR_NONE = 0,\n     MAT_VAR_INT,\n     MAT_VAR_TEXTURE,\n-    MAT_VAR_TEXTURE2, //TODO: RENAME\n+    MAT_VAR_TEXTURE_HANDLER, //TODO: RENAME\n     MAT_VAR_VEC4,\n     MAT_VAR_MAT44\n };\n@@ -16,6 +16,7 @@ struct material_variable {\n         int i;\n         float f;\n         uint64_t t;\n+        uint16_t th;\n         float v3[3];\n         float v4[4];\n         float m44[16];\n@@ -34,9 +35,9 @@ namespace material {\n                      uint64_t texture);\n \n     // TODO: rename\n-    void set_texture2(struct ct_material material,\n-                     const char *slot,\n-                     struct ct_texture texture);\n+    void set_texture_handler(struct ct_material material,\n+                             const char *slot,\n+                             struct ct_texture texture);\n \n     void set_mat44f(struct ct_material material,\n                     const char *slot,\ndiff --git a/src/cetech/modules/renderer/private/renderer.cpp b/src/cetech/modules/renderer/private/renderer.cpp\nindex 42b0fb1f1..3e4e4c3af 100644\n--- a/src/cetech/modules/renderer/private/renderer.cpp\n+++ b/src/cetech/modules/renderer/private/renderer.cpp\n@@ -102,19 +102,17 @@ struct GConfig {\n //==============================================================================\n // Private\n //==============================================================================\n-struct PosTexCoord0Vertex\n-{\n+struct PosTexCoord0Vertex {\n     float m_x;\n     float m_y;\n     float m_z;\n     float m_u;\n     float m_v;\n \n-    static void init()\n-    {\n+    static void init() {\n         ms_decl\n                 .begin()\n-                .add(bgfx::Attrib::Position,  3, bgfx::AttribType::Float)\n+                .add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float)\n                 .add(bgfx::Attrib::TexCoord0, 2, bgfx::AttribType::Float)\n                 .end();\n     }\n@@ -125,31 +123,34 @@ struct PosTexCoord0Vertex\n bgfx::VertexDecl PosTexCoord0Vertex::ms_decl;\n \n \n-void screenSpaceQuad(float _textureWidth, float _textureHeight, float _texelHalf, bool _originBottomLeft, float _width = 1.0f, float _height = 1.0f)\n-{\n-    if (3 == bgfx::getAvailTransientVertexBuffer(3, PosTexCoord0Vertex::ms_decl) )\n-    {\n+void screenSpaceQuad(float _textureWidth,\n+                     float _textureHeight,\n+                     float _texelHalf,\n+                     bool _originBottomLeft,\n+                     float _width = 1.0f,\n+                     float _height = 1.0f) {\n+    if (3 ==\n+        bgfx::getAvailTransientVertexBuffer(3, PosTexCoord0Vertex::ms_decl)) {\n         bgfx::TransientVertexBuffer vb;\n         bgfx::allocTransientVertexBuffer(&vb, 3, PosTexCoord0Vertex::ms_decl);\n-        PosTexCoord0Vertex* vertex = (PosTexCoord0Vertex*)vb.data;\n+        PosTexCoord0Vertex *vertex = (PosTexCoord0Vertex *) vb.data;\n \n         const float minx = -_width;\n-        const float maxx =  _width;\n+        const float maxx = _width;\n         const float miny = 0.0f;\n-        const float maxy = _height*2.0f;\n+        const float maxy = _height * 2.0f;\n \n-        const float texelHalfW = _texelHalf/_textureWidth;\n-        const float texelHalfH = _texelHalf/_textureHeight;\n+        const float texelHalfW = _texelHalf / _textureWidth;\n+        const float texelHalfH = _texelHalf / _textureHeight;\n         const float minu = -1.0f + texelHalfW;\n-        const float maxu =  1.0f + texelHalfH;\n+        const float maxu = 1.0f + texelHalfH;\n \n         const float zz = 0.0f;\n \n         float minv = texelHalfH;\n         float maxv = 2.0f + texelHalfH;\n \n-        if (_originBottomLeft)\n-        {\n+        if (_originBottomLeft) {\n             float temp = minv;\n             minv = maxv;\n             maxv = temp;\n@@ -216,6 +217,7 @@ bgfx::BackbufferRatio::Enum ratio_id_to_enum(uint64_t id) {\n     } _RatioIdToEnum[] = {\n             {.id = ct_hash_a0.id64_from_str(\n                     ""), .e = bgfx::BackbufferRatio::Count},\n+\n             {.id = ct_hash_a0.id64_from_str(\n                     "equal"), .e = bgfx::BackbufferRatio::Equal},\n     };\n@@ -236,8 +238,6 @@ bgfx::BackbufferRatio::Enum ratio_id_to_enum(uint64_t id) {\n // render global\n //==============================================================================\n \n-\n-\n #include "renderconfig_blob.h"\n \n \n@@ -359,8 +359,8 @@ void renderer_get_size(uint32_t *width,\n }\n \n \n-uint16_t _render_viewport_get_local_resource(viewport_instance& instance,\n-                                            uint64_t name) {\n+uint16_t _render_viewport_get_local_resource(viewport_instance &instance,\n+                                             uint64_t name) {\n \n \n     for (int i = 0; i < instance.resource_count; ++i) {\n@@ -384,18 +384,14 @@ uint16_t render_viewport_get_local_resource(ct_viewport viewport,\n     return _render_viewport_get_local_resource(vi, name);\n }\n \n-ct_viewport renderer_create_viewport(uint64_t name,\n-                                     float width,\n-                                     float height) {\n-    auto id = celib::handler::create(_G.viewport_handler);\n+void _init_viewport(viewport_instance &vi,\n+                    uint64_t name,\n+                    float width,\n+                    float height) {\n \n     auto *resource = ct_resource_a0.get(_G.type, name);\n     auto *blob = renderconfig_blob::get(resource);\n \n-    auto idx = celib::array::size(_G.viewport_instances);\n-\n-    viewport_instance vi = {};\n-\n     if (!width || !height) {\n         uint32_t w, h;\n         renderer_get_size(&w, &h);\n@@ -405,14 +401,13 @@ ct_viewport renderer_create_viewport(uint64_t name,\n \n     vi.size[0] = width;\n     vi.size[1] = height;\n-\n+    vi.viewport = name;\n     for (uint32_t i = 0; i < blob->viewport_count; ++i) {\n         auto &vp = renderconfig_blob::viewport(blob)[i];\n         if (vp.name != name) {\n             continue;\n         }\n \n-\n         for (uint32_t j = 0; j < blob->layer_count; ++j) {\n             auto layer_name = renderconfig_blob::layers_name(blob)[j];\n             if (layer_name != vp.layer) {\n@@ -424,7 +419,8 @@ ct_viewport renderer_create_viewport(uint64_t name,\n             auto localresource_offset = renderconfig_blob::layers_localresource_offset(\n                     blob)[j];\n             auto *localresource =\n-                    renderconfig_blob::local_resource(blob) + localresource_offset;\n+                    renderconfig_blob::local_resource(blob) +\n+                    localresource_offset;\n \n             vi.resource_count = localresource_count;\n \n@@ -442,8 +438,13 @@ ct_viewport renderer_create_viewport(uint64_t name,\n                                               | BGFX_TEXTURE_U_CLAMP\n                                               | BGFX_TEXTURE_V_CLAMP;\n \n-                auto h = bgfx::createTexture2D(ration, false, 1, format,\n-                                               samplerFlags);\n+                if (0 != vi.local_resource[k]) {\n+                    bgfx::destroy((bgfx::TextureHandle) {vi.local_resource[k]});\n+                }\n+\n+                auto h = bgfx::createTexture2D(static_cast<uint16_t>(width),\n+                                               static_cast<uint16_t>(height),\n+                                               false, 1, format, samplerFlags);\n \n                 vi.local_resource[k] = h.idx;\n                 vi.local_resource_name[k] = lr.name;\n@@ -456,23 +457,51 @@ ct_viewport renderer_create_viewport(uint64_t name,\n             vi.layer_count = entry_count;\n             vi.layers = entry;\n \n+            vi.fb_count = entry_count;\n             for (int k = 0; k < entry_count; ++k) {\n                 auto &e = entry[k];\n \n                 bgfx::TextureHandle th[e.output_count];\n                 for (int l = 0; l < e.output_count; ++l) {\n                     // TODO if not found in local then find in global\n-                    th[l] = {_render_viewport_get_local_resource(vi, e.output[l])};\n+                    th[l] = {_render_viewport_get_local_resource(vi,\n+                                                                 e.output[l])};\n+                }\n+\n+                if (0 != vi.framebuffers[k]) {\n+                    bgfx::destroy((bgfx::FrameBufferHandle) {\n+                            vi.framebuffers[k]});\n                 }\n \n                 auto fb = bgfx::createFrameBuffer(e.output_count, th, false);\n-                vi.framebuffers[vi.fb_count] = fb.idx;\n-                ++vi.fb_count;\n+                vi.framebuffers[k] = fb.idx;\n             }\n-\n         }\n     }\n+}\n+\n+void resize_viewport(ct_viewport viewport,\n+                     float width,\n+                     float height) {\n+\n+    auto idx = celib::map::get(_G.viewport_instance_map, viewport.idx,\n+                               UINT32_MAX);\n+    auto &vi = _G.viewport_instances[idx];\n+\n+    if ((width != vi.size[0]) || (height != vi.size[1])) {\n+        _init_viewport(vi, vi.viewport, width, height);\n+    }\n+\n+}\n \n+ct_viewport renderer_create_viewport(uint64_t name,\n+                                     float width,\n+                                     float height) {\n+    viewport_instance vi = {};\n+    _init_viewport(vi, name, width, height);\n+\n+    auto idx = celib::array::size(_G.viewport_instances);\n+    auto id = celib::handler::create(_G.viewport_handler);\n     celib::map::set(_G.viewport_instance_map, id, idx);\n     celib::array::push_back(_G.viewport_instances, vi);\n \n@@ -485,7 +514,6 @@ ct_viewport renderer_create_viewport(uint64_t name,\n //==============================================================================\n namespace renderconfig_resource {\n \n-\n     void *loader(ct_vio *input,\n                  cel_alloc *allocator) {\n         const int64_t size = input->size(input->inst);\n@@ -554,443 +582,441 @@ namespace renderconfig_resource {\n \n //// COMPIELr\n namespace renderconfig_compiler {\n-    namespace {\n-        struct compiler_output {\n-            celib::Array<render_resource_t> global_resource;\n-            celib::Array<render_resource_t> local_resource;\n-            celib::Array<uint64_t> layer_names;\n-            celib::Array<uint32_t> layers_entry_count;\n-            celib::Array<uint32_t> layers_localresource_count;\n-            celib::Array<uint32_t> layers_localresource_offset;\n-            celib::Array<uint32_t> layers_entry_offset;\n-            celib::Array<layer_entry_t> layers_entry;\n-            celib::Array<viewport_entry_t> viewport;\n-        };\n+    struct compiler_output {\n+        celib::Array<render_resource_t> global_resource;\n+        celib::Array<render_resource_t> local_resource;\n+        celib::Array<uint64_t> layer_names;\n+        celib::Array<uint32_t> layers_entry_count;\n+        celib::Array<uint32_t> layers_localresource_count;\n+        celib::Array<uint32_t> layers_localresource_offset;\n+        celib::Array<uint32_t> layers_entry_offset;\n+        celib::Array<layer_entry_t> layers_entry;\n+        celib::Array<viewport_entry_t> viewport;\n+    };\n \n \n-        int compiler(const char *filename,\n-                     ct_vio *source_vio,\n-                     ct_vio *build_vio,\n-                     ct_compilator_api *compilator_api) {\n+    int compiler(const char *filename,\n+                 ct_vio *source_vio,\n+                 ct_vio *build_vio,\n+                 ct_compilator_api *compilator_api) {\n \n-            char *source_data =\n-                    CEL_ALLOCATE(ct_memory_a0.main_allocator(), char,\n-                                 source_vio->size(source_vio->inst) + 1);\n-            memset(source_data, 0, source_vio->size(source_vio->inst) + 1);\n+        char *source_data =\n+                CEL_ALLOCATE(ct_memory_a0.main_allocator(), char,\n+                             source_vio->size(source_vio->inst) + 1);\n+        memset(source_data, 0, source_vio->size(source_vio->inst) + 1);\n \n-            source_vio->read(source_vio->inst, source_data, sizeof(char),\n-                             source_vio->size(source_vio->inst));\n+        source_vio->read(source_vio->inst, source_data, sizeof(char),\n+                         source_vio->size(source_vio->inst));\n \n-            yaml_document_t h;\n-            yaml_node_t root = yaml_load_str(source_data, &h);\n+        yaml_document_t h;\n+        yaml_node_t root = yaml_load_str(source_data, &h);\n \n-            struct compiler_output output = {};\n-            output.global_resource.init(ct_memory_a0.main_allocator());\n-            output.layer_names.init(ct_memory_a0.main_allocator());\n-            output.layers_entry_count.init(ct_memory_a0.main_allocator());\n-            output.layers_entry_offset.init(ct_memory_a0.main_allocator());\n-            output.layers_entry.init(ct_memory_a0.main_allocator());\n-            output.viewport.init(ct_memory_a0.main_allocator());\n-            output.local_resource.init(ct_memory_a0.main_allocator());\n-            output.layers_localresource_count.init(\n-                    ct_memory_a0.main_allocator());\n-            output.layers_localresource_offset.init(\n-                    ct_memory_a0.main_allocator());\n+        struct compiler_output output = {};\n+        output.global_resource.init(ct_memory_a0.main_allocator());\n+        output.layer_names.init(ct_memory_a0.main_allocator());\n+        output.layers_entry_count.init(ct_memory_a0.main_allocator());\n+        output.layers_entry_offset.init(ct_memory_a0.main_allocator());\n+        output.layers_entry.init(ct_memory_a0.main_allocator());\n+        output.viewport.init(ct_memory_a0.main_allocator());\n+        output.local_resource.init(ct_memory_a0.main_allocator());\n+        output.layers_localresource_count.init(\n+                ct_memory_a0.main_allocator());\n+        output.layers_localresource_offset.init(\n+                ct_memory_a0.main_allocator());\n \n \n-            //==================================================================\n-            // Global resource\n-            //==================================================================\n-            yaml_node_t global_resource = yaml_get_node(root,\n-                                                        "global_resource");\n-            if (yaml_is_valid(global_resource)) {\n-                yaml_node_foreach_seq(\n-                        global_resource,\n-                        [](uint32_t idx,\n-                           yaml_node_t value,\n-                           void *_data) {\n-                            char str_buffer[128] = {};\n-                            render_resource_t gs = {};\n+        //==================================================================\n+        // Global resource\n+        //==================================================================\n+        yaml_node_t global_resource = yaml_get_node(root,\n+                                                    "global_resource");\n+        if (yaml_is_valid(global_resource)) {\n+            yaml_node_foreach_seq(\n+                    global_resource,\n+                    [](uint32_t idx,\n+                       yaml_node_t value,\n+                       void *_data) {\n+                        char str_buffer[128] = {};\n+                        render_resource_t gs = {};\n \n-                            compiler_output &output = *((compiler_output *) _data);\n+                        compiler_output &output = *((compiler_output *) _data);\n \n-                            ////////////////////////////////////////////////////\n-                            yaml_node_t name = yaml_get_node(value, "name");\n-                            yaml_as_string(name, str_buffer,\n-                                           CETECH_ARRAY_LEN(str_buffer) - 1);\n+                        ////////////////////////////////////////////////////\n+                        yaml_node_t name = yaml_get_node(value, "name");\n+                        yaml_as_string(name, str_buffer,\n+                                       CETECH_ARRAY_LEN(str_buffer) - 1);\n \n-                            gs.name = ct_hash_a0.id64_from_str(str_buffer);\n+                        gs.name = ct_hash_a0.id64_from_str(str_buffer);\n \n \n-                            /////////////////////////////////////////////////////\n-                            yaml_node_t type = yaml_get_node(value, "type");\n-                            yaml_as_string(type, str_buffer,\n-                                           CETECH_ARRAY_LEN(str_buffer) - 1);\n+                        /////////////////////////////////////////////////////\n+                        yaml_node_t type = yaml_get_node(value, "type");\n+                        yaml_as_string(type, str_buffer,\n+                                       CETECH_ARRAY_LEN(str_buffer) - 1);\n \n-                            gs.type = ct_hash_a0.id64_from_str(str_buffer);\n+                        gs.type = ct_hash_a0.id64_from_str(str_buffer);\n \n \n-                            /////////////////////////////////////////////////////\n-                            yaml_node_t format = yaml_get_node(value, "format");\n-                            yaml_as_string(format, str_buffer,\n-                                           CETECH_ARRAY_LEN(str_buffer) - 1);\n+                        /////////////////////////////////////////////////////\n+                        yaml_node_t format = yaml_get_node(value, "format");\n+                        yaml_as_string(format, str_buffer,\n+                                       CETECH_ARRAY_LEN(str_buffer) - 1);\n \n-                            gs.format = ct_hash_a0.id64_from_str(str_buffer);\n+                        gs.format = ct_hash_a0.id64_from_str(str_buffer);\n \n-                            /////////////////////////////////////////////////////\n-                            yaml_node_t ration = yaml_get_node(value, "ration");\n-                            yaml_as_string(ration, str_buffer,\n-                                           CETECH_ARRAY_LEN(str_buffer) - 1);\n+                        /////////////////////////////////////////////////////\n+                        yaml_node_t ration = yaml_get_node(value, "ration");\n+                        yaml_as_string(ration, str_buffer,\n+                                       CETECH_ARRAY_LEN(str_buffer) - 1);\n \n-                            gs.ration = ct_hash_a0.id64_from_str(str_buffer);\n+                        gs.ration = ct_hash_a0.id64_from_str(str_buffer);\n \n \n-                            celib::array::push_back(output.global_resource, gs);\n-                        }, &output);\n-            }\n+                        celib::array::push_back(output.global_resource, gs);\n+                    }, &output);\n+        }\n+\n+        //==================================================================\n+        // layers\n+        //==================================================================\n+        yaml_node_t layers = yaml_get_node(root, "layers");\n+        if (yaml_is_valid(layers)) {\n+\n+            yaml_node_foreach_dict(\n+                    layers,\n+                    [](yaml_node_t key,\n+                       yaml_node_t value,\n+                       void *_data) {\n+                        char str_buffer[128] = {};\n+\n+                        compiler_output &output = *((compiler_output *) _data);\n+\n+                        yaml_as_string(key, str_buffer,\n+                                       CETECH_ARRAY_LEN(str_buffer) - 1);\n+\n+                        auto name_id = ct_hash_a0.id64_from_str(str_buffer);\n+                        auto layer_offset = celib::array::size(\n+                                output.layers_entry);\n+\n+                        celib::array::push_back(output.layer_names,\n+                                                name_id);\n+                        celib::array::push_back(output.layers_entry_offset,\n+                                                layer_offset);\n+\n+                        yaml_node_foreach_seq(\n+                                value,\n+                                [](uint32_t idx,\n+                                   yaml_node_t value,\n+                                   void *_data) {\n+                                    char str_buffer[128] = {};\n+                                    layer_entry_t le = {};\n+\n+                                    auto &output = *((compiler_output *) _data);\n+\n+                                    ////////////////////////////////////////////////////\n+                                    yaml_node_t name = yaml_get_node(value,\n+                                                                     "name");\n+                                    yaml_as_string(name, str_buffer,\n+                                                   CETECH_ARRAY_LEN(\n+                                                           str_buffer) - 1);\n+\n+                                    le.name = ct_hash_a0.id64_from_str(\n+                                            str_buffer);\n+\n+\n+                                    /////////////////////////////////////////////////////\n+                                    yaml_node_t type = yaml_get_node(value,\n+                                                                     "type");\n+\n+                                    yaml_as_string(type, str_buffer,\n+                                                   CETECH_ARRAY_LEN(\n+                                                           str_buffer) - 1);\n+\n+                                    le.type = ct_hash_a0.id64_from_str(\n+                                            str_buffer);\n+\n+                                    /////////////////////////////////////////////////////\n+                                    yaml_node_t input = yaml_get_node(value,\n+                                                                      "input");\n+                                    if (yaml_is_valid(input)) {\n+                                        yaml_node_foreach_seq(\n+                                                input,\n+                                                [](uint32_t idx,\n+                                                   yaml_node_t value,\n+                                                   void *_data) {\n+                                                    char str_buffer[128] = {};\n+                                                    auto &le = *((layer_entry_t *) _data);\n+\n+                                                    yaml_as_string(value,\n+                                                                   str_buffer,\n+                                                                   CETECH_ARRAY_LEN(\n+                                                                           str_buffer) -\n+                                                                   1);\n+\n+                                                    le.input[idx] = ct_hash_a0.id64_from_str(\n+                                                            str_buffer);\n+                                                    ++le.input_count;\n+\n+                                                }, &le);\n+                                    }\n+\n+                                    /////////////////////////////////////////////////////\n+                                    yaml_node_t output_t = yaml_get_node(\n+                                            value,\n+                                            "output");\n+                                    if (yaml_is_valid(output_t)) {\n+                                        yaml_node_foreach_seq(\n+                                                output_t,\n+                                                [](uint32_t idx,\n+                                                   yaml_node_t value,\n+                                                   void *_data) {\n+                                                    char str_buffer[128] = {};\n+                                                    auto &le = *((layer_entry_t *) _data);\n+\n+                                                    yaml_as_string(value,\n+                                                                   str_buffer,\n+                                                                   CETECH_ARRAY_LEN(\n+                                                                           str_buffer) -\n+                                                                   1);\n+\n+                                                    le.output[idx] = ct_hash_a0.id64_from_str(\n+                                                            str_buffer);\n+                                                    ++le.output_count;\n+\n+                                                }, &le);\n+                                    }\n+\n+\n+                                    celib::array::push_back(\n+                                            output.layers_entry, le);\n+\n+                                }, &output);\n+\n+                        celib::array::push_back(output.layers_entry_count,\n+                                                celib::array::size(\n+                                                        output.layers_entry) -\n+                                                layer_offset);\n+\n+                    }, &output);\n+        }\n+\n+        //==================================================================\n+        // Viewport\n+        //==================================================================\n+        yaml_node_t viewport = yaml_get_node(root, "viewport");\n+        if (yaml_is_valid(viewport)) {\n+\n+            yaml_node_foreach_dict(\n+                    viewport,\n+                    [](yaml_node_t key,\n+                       yaml_node_t value,\n+                       void *_data) {\n+                        char str_buffer[128] = {};\n+\n+                        compiler_output &output = *((compiler_output *) _data);\n+\n+                        yaml_as_string(key, str_buffer,\n+                                       CETECH_ARRAY_LEN(str_buffer) - 1);\n \n-            //==================================================================\n-            // layers\n-            //==================================================================\n-            yaml_node_t layers = yaml_get_node(root, "layers");\n-            if (yaml_is_valid(layers)) {\n+                        auto name_id = ct_hash_a0.id64_from_str(str_buffer);\n \n-                yaml_node_foreach_dict(\n-                        layers,\n-                        [](yaml_node_t key,\n-                           yaml_node_t value,\n-                           void *_data) {\n-                            char str_buffer[128] = {};\n+                        yaml_as_string(key, str_buffer,\n+                                       CETECH_ARRAY_LEN(str_buffer) - 1);\n \n-                            compiler_output &output = *((compiler_output *) _data);\n+                        yaml_node_t layers = yaml_get_node(value, "layers");\n+                        yaml_as_string(layers, str_buffer,\n+                                       CETECH_ARRAY_LEN(str_buffer) - 1);\n+                        auto layers_id = ct_hash_a0.id64_from_str(\n+                                str_buffer);\n \n-                            yaml_as_string(key, str_buffer,\n-                                           CETECH_ARRAY_LEN(str_buffer) - 1);\n \n-                            auto name_id = ct_hash_a0.id64_from_str(str_buffer);\n-                            auto layer_offset = celib::array::size(\n-                                    output.layers_entry);\n+                        viewport_entry_t ve = {};\n \n-                            celib::array::push_back(output.layer_names,\n-                                                    name_id);\n-                            celib::array::push_back(output.layers_entry_offset,\n-                                                    layer_offset);\n+                        ve.name = name_id;\n+                        ve.layer = layers_id;\n \n+                        celib::array::push_back(output.viewport, ve);\n+\n+                        //////\n+                        auto localresource_offset = celib::array::size(\n+                                output.local_resource);\n+\n+                        celib::array::push_back(\n+                                output.layers_localresource_offset,\n+                                localresource_offset);\n+\n+                        yaml_node_t local_resource = yaml_get_node(value,\n+                                                                   "local_resource");\n+                        if (yaml_is_valid(local_resource)) {\n                             yaml_node_foreach_seq(\n-                                    value,\n+                                    local_resource,\n                                     [](uint32_t idx,\n                                        yaml_node_t value,\n                                        void *_data) {\n                                         char str_buffer[128] = {};\n-                                        layer_entry_t le = {};\n+                                        render_resource_t gs = {};\n \n-                                        auto &output = *((compiler_output *) _data);\n+                                        compiler_output &output = *((compiler_output *) _data);\n \n                                         ////////////////////////////////////////////////////\n-                                        yaml_node_t name = yaml_get_node(value,\n-                                                                         "name");\n+                                        yaml_node_t name = yaml_get_node(\n+                                                value, "name");\n                                         yaml_as_string(name, str_buffer,\n                                                        CETECH_ARRAY_LEN(\n-                                                               str_buffer) - 1);\n+                                                               str_buffer) -\n+                                                       1);\n \n-                                        le.name = ct_hash_a0.id64_from_str(\n+                                        gs.name = ct_hash_a0.id64_from_str(\n                                                 str_buffer);\n \n \n                                         /////////////////////////////////////////////////////\n-                                        yaml_node_t type = yaml_get_node(value,\n-                                                                         "type");\n-\n+                                        yaml_node_t type = yaml_get_node(\n+                                                value, "type");\n                                         yaml_as_string(type, str_buffer,\n                                                        CETECH_ARRAY_LEN(\n-                                                               str_buffer) - 1);\n+                                                               str_buffer) -\n+                                                       1);\n \n-                                        le.type = ct_hash_a0.id64_from_str(\n+                                        gs.type = ct_hash_a0.id64_from_str(\n                                                 str_buffer);\n \n-                                        /////////////////////////////////////////////////////\n-                                        yaml_node_t input = yaml_get_node(value,\n-                                                                          "input");\n-                                        if (yaml_is_valid(input)) {\n-                                            yaml_node_foreach_seq(\n-                                                    input,\n-                                                    [](uint32_t idx,\n-                                                       yaml_node_t value,\n-                                                       void *_data) {\n-                                                        char str_buffer[128] = {};\n-                                                        auto &le = *((layer_entry_t *) _data);\n-\n-                                                        yaml_as_string(value,\n-                                                                       str_buffer,\n-                                                                       CETECH_ARRAY_LEN(\n-                                                                               str_buffer) -\n-                                                                       1);\n-\n-                                                        le.input[idx] = ct_hash_a0.id64_from_str(\n-                                                                str_buffer);\n-                                                        ++le.input_count;\n-\n-                                                    }, &le);\n-                                        }\n \n                                         /////////////////////////////////////////////////////\n-                                        yaml_node_t output_t = yaml_get_node(\n-                                                value,\n-                                                "output");\n-                                        if (yaml_is_valid(output_t)) {\n-                                            yaml_node_foreach_seq(\n-                                                    output_t,\n-                                                    [](uint32_t idx,\n-                                                       yaml_node_t value,\n-                                                       void *_data) {\n-                                                        char str_buffer[128] = {};\n-                                                        auto &le = *((layer_entry_t *) _data);\n-\n-                                                        yaml_as_string(value,\n-                                                                       str_buffer,\n-                                                                       CETECH_ARRAY_LEN(\n-                                                                               str_buffer) -\n-                                                                       1);\n-\n-                                                        le.output[idx] = ct_hash_a0.id64_from_str(\n-                                                                str_buffer);\n-                                                        ++le.output_count;\n-\n-                                                    }, &le);\n-                                        }\n-\n-\n-                                        celib::array::push_back(\n-                                                output.layers_entry, le);\n-\n-                                    }, &output);\n-\n-                            celib::array::push_back(output.layers_entry_count,\n-                                                    celib::array::size(\n-                                                            output.layers_entry) -\n-                                                    layer_offset);\n-\n-                        }, &output);\n-            }\n-\n-            //==================================================================\n-            // Viewport\n-            //==================================================================\n-            yaml_node_t viewport = yaml_get_node(root, "viewport");\n-            if (yaml_is_valid(viewport)) {\n-\n-                yaml_node_foreach_dict(\n-                        viewport,\n-                        [](yaml_node_t key,\n-                           yaml_node_t value,\n-                           void *_data) {\n-                            char str_buffer[128] = {};\n-\n-                            compiler_output &output = *((compiler_output *) _data);\n-\n-                            yaml_as_string(key, str_buffer,\n-                                           CETECH_ARRAY_LEN(str_buffer) - 1);\n-\n-                            auto name_id = ct_hash_a0.id64_from_str(str_buffer);\n-\n-                            yaml_as_string(key, str_buffer,\n-                                           CETECH_ARRAY_LEN(str_buffer) - 1);\n-\n-                            yaml_node_t layers = yaml_get_node(value, "layers");\n-                            yaml_as_string(layers, str_buffer,\n-                                           CETECH_ARRAY_LEN(str_buffer) - 1);\n-                            auto layers_id = ct_hash_a0.id64_from_str(\n-                                    str_buffer);\n+                                        yaml_node_t format = yaml_get_node(\n+                                                value, "format");\n+                                        yaml_as_string(format, str_buffer,\n+                                                       CETECH_ARRAY_LEN(\n+                                                               str_buffer) -\n+                                                       1);\n \n+                                        gs.format = ct_hash_a0.id64_from_str(\n+                                                str_buffer);\n \n-                            viewport_entry_t ve = {};\n+                                        /////////////////////////////////////////////////////\n+                                        yaml_node_t ration = yaml_get_node(\n+                                                value, "ration");\n+                                        yaml_as_string(ration, str_buffer,\n+                                                       CETECH_ARRAY_LEN(\n+                                                               str_buffer) -\n+                                                       1);\n \n-                            ve.name = name_id;\n-                            ve.layer = layers_id;\n+                                        gs.ration = ct_hash_a0.id64_from_str(\n+                                                str_buffer);\n \n-                            celib::array::push_back(output.viewport, ve);\n \n-                            //////\n-                            auto localresource_offset = celib::array::size(\n-                                    output.local_resource);\n+                                        celib::array::push_back(\n+                                                output.local_resource, gs);\n+                                    }, &output);\n \n                             celib::array::push_back(\n-                                    output.layers_localresource_offset,\n+                                    output.layers_localresource_count,\n+                                    celib::array::size(\n+                                            output.local_resource) -\n                                     localresource_offset);\n+                        }\n \n-                            yaml_node_t local_resource = yaml_get_node(value,\n-                                                                       "local_resource");\n-                            if (yaml_is_valid(local_resource)) {\n-                                yaml_node_foreach_seq(\n-                                        local_resource,\n-                                        [](uint32_t idx,\n-                                           yaml_node_t value,\n-                                           void *_data) {\n-                                            char str_buffer[128] = {};\n-                                            render_resource_t gs = {};\n-\n-                                            compiler_output &output = *((compiler_output *) _data);\n-\n-                                            ////////////////////////////////////////////////////\n-                                            yaml_node_t name = yaml_get_node(\n-                                                    value, "name");\n-                                            yaml_as_string(name, str_buffer,\n-                                                           CETECH_ARRAY_LEN(\n-                                                                   str_buffer) -\n-                                                           1);\n-\n-                                            gs.name = ct_hash_a0.id64_from_str(\n-                                                    str_buffer);\n-\n-\n-                                            /////////////////////////////////////////////////////\n-                                            yaml_node_t type = yaml_get_node(\n-                                                    value, "type");\n-                                            yaml_as_string(type, str_buffer,\n-                                                           CETECH_ARRAY_LEN(\n-                                                                   str_buffer) -\n-                                                           1);\n-\n-                                            gs.type = ct_hash_a0.id64_from_str(\n-                                                    str_buffer);\n-\n-\n-                                            /////////////////////////////////////////////////////\n-                                            yaml_node_t format = yaml_get_node(\n-                                                    value, "format");\n-                                            yaml_as_string(format, str_buffer,\n-                                                           CETECH_ARRAY_LEN(\n-                                                                   str_buffer) -\n-                                                           1);\n-\n-                                            gs.format = ct_hash_a0.id64_from_str(\n-                                                    str_buffer);\n-\n-                                            /////////////////////////////////////////////////////\n-                                            yaml_node_t ration = yaml_get_node(\n-                                                    value, "ration");\n-                                            yaml_as_string(ration, str_buffer,\n-                                                           CETECH_ARRAY_LEN(\n-                                                                   str_buffer) -\n-                                                           1);\n-\n-                                            gs.ration = ct_hash_a0.id64_from_str(\n-                                                    str_buffer);\n-\n-\n-                                            celib::array::push_back(\n-                                                    output.local_resource, gs);\n-                                        }, &output);\n-\n-                                celib::array::push_back(\n-                                        output.layers_localresource_count,\n-                                        celib::array::size(\n-                                                output.local_resource) -\n-                                        localresource_offset);\n-                            }\n-\n-                        }, &output);\n-            }\n-\n-            renderconfig_blob::blob_t resource = {\n-                    .global_resource_count = celib::array::size(\n-                            output.global_resource),\n-\n-                    .layer_count = celib::array::size(\n-                            output.layer_names),\n-\n-                    .layer_entry_count = celib::array::size(\n-                            output.layers_entry),\n-\n-                    .local_resource_count = celib::array::size(\n-                            output.local_resource),\n-\n-                    .viewport_count = celib::array::size(output.viewport),\n-            };\n-\n-\n-            build_vio->write(build_vio->inst, &resource, sizeof(resource), 1);\n-\n-            build_vio->write(build_vio->inst,\n-                             celib::array::begin(output.global_resource),\n-                             sizeof(render_resource_t),\n-                             celib::array::size(output.global_resource));\n-\n-            build_vio->write(build_vio->inst,\n-                             celib::array::begin(output.local_resource),\n-                             sizeof(render_resource_t),\n-                             celib::array::size(output.local_resource));\n-\n-            build_vio->write(build_vio->inst,\n-                             celib::array::begin(output.layer_names),\n-                             sizeof(uint64_t),\n-                             celib::array::size(output.layer_names));\n-\n-            build_vio->write(build_vio->inst,\n-                             celib::array::begin(output.layers_entry_count),\n-                             sizeof(uint32_t),\n-                             celib::array::size(output.layers_entry_count));\n-\n-            build_vio->write(build_vio->inst,\n-                             celib::array::begin(output.layers_entry_offset),\n-                             sizeof(uint32_t),\n-                             celib::array::size(output.layers_entry_offset));\n-\n+                    }, &output);\n+        }\n \n-            build_vio->write(build_vio->inst,\n-                             celib::array::begin(\n-                                     output.layers_localresource_count),\n-                             sizeof(uint32_t),\n-                             celib::array::size(\n-                                     output.layers_localresource_count));\n+        renderconfig_blob::blob_t resource = {\n+                .global_resource_count = celib::array::size(\n+                        output.global_resource),\n \n-            build_vio->write(build_vio->inst,\n-                             celib::array::begin(\n-                                     output.layers_localresource_offset),\n-                             sizeof(uint32_t),\n-                             celib::array::size(\n-                                     output.layers_localresource_offset));\n+                .layer_count = celib::array::size(\n+                        output.layer_names),\n \n+                .layer_entry_count = celib::array::size(\n+                        output.layers_entry),\n \n-            build_vio->write(build_vio->inst,\n-                             celib::array::begin(output.layers_entry),\n-                             sizeof(layer_entry_t),\n-                             celib::array::size(output.layers_entry));\n+                .local_resource_count = celib::array::size(\n+                        output.local_resource),\n \n-            build_vio->write(build_vio->inst,\n-                             celib::array::begin(output.viewport),\n-                             sizeof(viewport_entry_t),\n-                             celib::array::size(output.viewport));\n+                .viewport_count = celib::array::size(output.viewport),\n+        };\n \n-            output.global_resource.destroy();\n-            output.layer_names.destroy();\n-            output.layers_entry_count.destroy();\n-            output.layers_entry_offset.destroy();\n-            output.layers_entry.destroy();\n-            output.viewport.destroy();\n-            output.local_resource.destroy();\n-            output.layers_localresource_count.destroy();\n-            output.layers_localresource_offset.destroy();\n \n-            CEL_FREE(ct_memory_a0.main_allocator(), source_data);\n-            return 1;\n-        }\n+        build_vio->write(build_vio->inst, &resource, sizeof(resource), 1);\n+\n+        build_vio->write(build_vio->inst,\n+                         celib::array::begin(output.global_resource),\n+                         sizeof(render_resource_t),\n+                         celib::array::size(output.global_resource));\n+\n+        build_vio->write(build_vio->inst,\n+                         celib::array::begin(output.local_resource),\n+                         sizeof(render_resource_t),\n+                         celib::array::size(output.local_resource));\n+\n+        build_vio->write(build_vio->inst,\n+                         celib::array::begin(output.layer_names),\n+                         sizeof(uint64_t),\n+                         celib::array::size(output.layer_names));\n+\n+        build_vio->write(build_vio->inst,\n+                         celib::array::begin(output.layers_entry_count),\n+                         sizeof(uint32_t),\n+                         celib::array::size(output.layers_entry_count));\n+\n+        build_vio->write(build_vio->inst,\n+                         celib::array::begin(output.layers_entry_offset),\n+                         sizeof(uint32_t),\n+                         celib::array::size(output.layers_entry_offset));\n+\n+\n+        build_vio->write(build_vio->inst,\n+                         celib::array::begin(\n+                                 output.layers_localresource_count),\n+                         sizeof(uint32_t),\n+                         celib::array::size(\n+                                 output.layers_localresource_count));\n+\n+        build_vio->write(build_vio->inst,\n+                         celib::array::begin(\n+                                 output.layers_localresource_offset),\n+                         sizeof(uint32_t),\n+                         celib::array::size(\n+                                 output.layers_localresource_offset));\n+\n+\n+        build_vio->write(build_vio->inst,\n+                         celib::array::begin(output.layers_entry),\n+                         sizeof(layer_entry_t),\n+                         celib::array::size(output.layers_entry));\n+\n+        build_vio->write(build_vio->inst,\n+                         celib::array::begin(output.viewport),\n+                         sizeof(viewport_entry_t),\n+                         celib::array::size(output.viewport));\n+\n+        output.global_resource.destroy();\n+        output.layer_names.destroy();\n+        output.layers_entry_count.destroy();\n+        output.layers_entry_offset.destroy();\n+        output.layers_entry.destroy();\n+        output.viewport.destroy();\n+        output.local_resource.destroy();\n+        output.layers_localresource_count.destroy();\n+        output.layers_localresource_offset.destroy();\n+\n+        CEL_FREE(ct_memory_a0.main_allocator(), source_data);\n+        return 1;\n+    }\n \n-        int init(struct ct_api_a0 *api) {\n-            ct_resource_a0.compiler_register(\n-                    ct_hash_a0.id64_from_str("render_config"),\n-                    compiler);\n+    int init(struct ct_api_a0 *api) {\n+        ct_resource_a0.compiler_register(\n+                ct_hash_a0.id64_from_str("render_config"),\n+                compiler);\n \n-            return 1;\n-        }\n+        return 1;\n     }\n }\n /////\n #define _DEF_ON_CLB_FCE(type, name)                                            \\\n-    static void register_ ## name ## _(type name) {                                   \\\n+    static void register_ ## name ## _(type name) {                            \\\n         celib::array::push_back(_G.name, name);                                \\\n     }                                                                          \\\n-    static void unregister_## name ## _(type name) {                                  \\\n+    static void unregister_## name ## _(type name) {                           \\\n         const auto size = celib::array::size(_G.name);                         \\\n                                                                                \\\n         for(uint32_t i = 0; i < size; ++i) {                                   \\\n@@ -1023,12 +1049,13 @@ namespace renderer_module {\n             .unregister_on_render =unregister_on_render_,\n             .create_viewport = renderer_create_viewport,\n             .viewport_get_local_resource = render_viewport_get_local_resource,\n+            .resize_viewport = resize_viewport,\n     };\n \n     static struct ct_material_a0 material_api = {\n             .resource_create = material::create,\n             .set_texture = material::set_texture,\n-            .set_texture2 = material::set_texture2,\n+            .set_texture_handler = material::set_texture_handler,\n             .set_mat44f = material::set_mat44f,\n             .submit = material::submit\n     };\n@@ -1137,7 +1164,8 @@ namespace renderer_module {\n                                            proj_matrix);\n \n                     // TODO: CULLING\n-                    ct_mesh_renderer_a0.render_all(world, viewid, viewport->layers[layerid].name);\n+                    ct_mesh_renderer_a0.render_all(world, viewid,\n+                                                   viewport->layers[layerid].name);\n                 });\n \n \n@@ -1148,8 +1176,8 @@ namespace renderer_module {\n                    uint8_t layerid,\n                    ct_world world,\n                    ct_camera camera) {\n-                    static ct_material copy_material = material_api.resource_create(ct_hash_a0.id64_from_str("copy"));\n-\n+                    static ct_material copy_material = material_api.resource_create(\n+                            ct_hash_a0.id64_from_str("copy"));\n \n                     bgfx::setViewRect(viewid, 0, 0,\n                                       (uint16_t) viewport->size[0],  // TODO: SHITTT\n@@ -1159,18 +1187,24 @@ namespace renderer_module {\n                     bgfx::setViewFrameBuffer(viewid, {fb});\n \n                     float proj[16];\n-                    celib::mat4_ortho(proj, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 100.0f, 0.0f, true);\n+                    celib::mat4_ortho(proj, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f,\n+                                      100.0f, 0.0f, true);\n \n                     bgfx::setViewTransform(viewid, NULL, proj);\n \n-                    auto& layer_entry = viewport->layers[layerid];\n+                    auto &layer_entry = viewport->layers[layerid];\n \n-                    screenSpaceQuad( viewport->size[0], viewport->size[1], 0.0f, true);\n+                    screenSpaceQuad(viewport->size[0], viewport->size[1], 0.0f,\n+                                    true);\n \n-                    auto input_tex = _render_viewport_get_local_resource(*viewport, layer_entry.input[0]);\n+                    auto input_tex = _render_viewport_get_local_resource(\n+                            *viewport, layer_entry.input[0]);\n \n-                    material_api.set_texture2(copy_material, "s_input_texture", {input_tex});\n-                    material_api.submit(copy_material, layer_entry.name, viewid);\n+                    material_api.set_texture_handler(copy_material,\n+                                                     "s_input_texture",\n+                                                     {input_tex});\n+                    material_api.submit(copy_material, layer_entry.name,\n+                                        viewid);\n                 });\n \n \n@@ -1224,6 +1258,5 @@ CETECH_MODULE_DEF(\n             CEL_UNUSED(api);\n \n             renderer_module::_shutdown();\n-\n         }\n )\n\\ No newline at end of file\ndiff --git a/src/cetech/modules/renderer/private/shader/shader.cpp b/src/cetech/modules/renderer/private/shader/shader.cpp\nindex 9fb8df656..2227bc962 100644\n--- a/src/cetech/modules/renderer/private/shader/shader.cpp\n+++ b/src/cetech/modules/renderer/private/shader/shader.cpp\n@@ -77,18 +77,22 @@ namespace shader_resource {\n \n     void online(uint64_t name,\n                 void *data) {\n-        auto resource = shader_blob::get(data);\n+        auto* resource = shader_blob::get(data);\n \n-        auto vs_mem = bgfx::alloc(shader_blob::vs_size(resource));\n-        auto fs_mem = bgfx::alloc(shader_blob::fs_size(resource));\n+        bgfx::ProgramHandle program = BGFX_INVALID_HANDLE;\n \n-        memcpy(vs_mem->data, (resource + 1), resource->vs_size);\n-        memcpy(fs_mem->data, ((char *) (resource + 1)) + resource->vs_size,\n-               resource->fs_size);\n+        if(resource) {\n+            auto vs_mem = bgfx::alloc(shader_blob::vs_size(resource));\n+            auto fs_mem = bgfx::alloc(shader_blob::fs_size(resource));\n \n-        auto vs_shader = bgfx::createShader(vs_mem);\n-        auto fs_shader = bgfx::createShader(fs_mem);\n-        auto program = bgfx::createProgram(vs_shader, fs_shader, 1);\n+            memcpy(vs_mem->data, (resource + 1), resource->vs_size);\n+            memcpy(fs_mem->data, ((char *) (resource + 1)) + resource->vs_size,\n+                   resource->fs_size);\n+\n+            auto vs_shader = bgfx::createShader(vs_mem);\n+            auto fs_shader = bgfx::createShader(fs_mem);\n+            program = bgfx::createProgram(vs_shader, fs_shader, 1);\n+        }\n \n         map::set(_G.handler_map, name, program);\n     }\ndiff --git a/src/cetech/modules/renderer/renderer.h b/src/cetech/modules/renderer/renderer.h\nindex 5b6dc20c9..d9a75d10d 100644\n--- a/src/cetech/modules/renderer/renderer.h\n+++ b/src/cetech/modules/renderer/renderer.h\n@@ -63,7 +63,7 @@ struct ct_material_a0 {\n     //! Submit material for actual render\n     void (*submit)(struct ct_material material,  uint64_t layer, uint8_t viewid);\n \n-    void (*set_texture2)(struct ct_material material,\n+    void (*set_texture_handler)(struct ct_material material,\n                       const char *slot,\n                       struct ct_texture texture);\n };\n@@ -168,7 +168,7 @@ struct viewport_instance {\n \n     layer_entry_t *layers;\n \n-    uint64_t layers_name;\n+    uint64_t viewport;\n     uint32_t layer_count;\n \n     uint32_t fb_count;\n@@ -207,12 +207,13 @@ struct ct_renderer_a0 {\n                          struct ct_camera camera,\n                          struct ct_viewport viewport);\n \n-    void (*register_layer_pass)(uint64_t  type, ct_renderer_on_pass_t on_pass);\n+    void (*register_layer_pass)(uint64_t type, ct_renderer_on_pass_t on_pass);\n \n     void (*register_on_render)(ct_render_on_render on_render);\n     void (*unregister_on_render)(ct_render_on_render on_render);\n \n     struct ct_viewport (*create_viewport)(uint64_t name, float width, float height);\n+    void (*resize_viewport)(struct ct_viewport viewport, float width, float height);\n     uint16_t (*viewport_get_local_resource)(ct_viewport viewport,uint64_t name);\n };\n \ndiff --git a/src/cetech/modules/static_module.h b/src/cetech/modules/static_module.h\nindex ebada0f20..b0acac9fd 100644\n--- a/src/cetech/modules/static_module.h\n+++ b/src/cetech/modules/static_module.h\n@@ -3,6 +3,10 @@\n //==============================================================================\n \n extern "C" void init_static_modules() {\n+    //==========================================================================\n+    // Engine\n+    //==========================================================================\n+\n     CETECH_ADD_STATIC_MODULE(transform);\n     CETECH_ADD_STATIC_MODULE(scenegraph);\n     CETECH_ADD_STATIC_MODULE(camera);\n@@ -12,5 +16,10 @@ extern "C" void init_static_modules() {\n     CETECH_ADD_STATIC_MODULE(luasys);\n \n     CETECH_ADD_STATIC_MODULE(debugui);\n+\n+    //==========================================================================\n+    // Playground\n+    //==========================================================================\n     CETECH_ADD_STATIC_MODULE(playground);\n+    CETECH_ADD_STATIC_MODULE(level_view);\n }\n', 'commit_subject': 'PLAYGR-23 - Level editor - basic level viewport', 'repo_name': 'cyberegoorg/cetech', 'committer': {'name': 'Ondra Voves', 'email': 'a6f730fbf1f3d74d6f3faf191093f4121e4ecc86@cyberego.org', 'time_sec': '1502747345', 'tz_offset': '120', 'date': {'seconds': '1502747345'}}, 'commit_tree': '077da024bbda2b50ea4095a6b7597ab6507526c4', 'commit_message': 'PLAYGR-23 - Level editor - basic level viewport\n', 'language_name': 'Shell', 'license': 'cc0-1.0', 'hunks': '@@ -0,0 +1,156 @@\n+#include <cetech/engine/entity/entity.h>\n+#include <cetech/modules/renderer/renderer.h>\n+#include <cetech/modules/debugui/debugui.h>\n+#include <cetech/engine/application/application.h>\n+#include <cetech/modules/level/level.h>\n+#include <cetech/modules/camera/camera.h>\n+#include <cetech/modules/playground/level_editor.h>\n+#include <cstdio>\n+#include "celib/map.inl"\n+\n+#include "cetech/core/hashlib/hashlib.h"\n+#include "cetech/core/config/config.h"\n+#include "cetech/core/memory/memory.h"\n+#include "cetech/core/api/api_system.h"\n+#include "cetech/core/module/module.h"\n+\n+CETECH_DECL_API(ct_memory_a0);\n+CETECH_DECL_API(ct_renderer_a0);\n+CETECH_DECL_API(ct_hash_a0);\n+CETECH_DECL_API(ct_debugui_a0);\n+CETECH_DECL_API(ct_app_a0);\n+CETECH_DECL_API(ct_world_a0);\n+CETECH_DECL_API(ct_level_a0);\n+CETECH_DECL_API(ct_entity_a0);\n+CETECH_DECL_API(ct_camera_a0);\n+\n+using namespace celib;\n+\n+#define MAX_LEVEL_EDITOR 8\n+\n+static struct {\n+    bool visible[MAX_LEVEL_EDITOR];\n+    ct_viewport viewport[MAX_LEVEL_EDITOR];\n+    ct_world world[MAX_LEVEL_EDITOR];\n+    ct_camera camera[MAX_LEVEL_EDITOR];\n+    ct_entity camera_ent[MAX_LEVEL_EDITOR];\n+\n+    uint8_t editor_count;\n+} _G;\n+\n+namespace level_view {\n+    void gui() {\n+//    fps_camera_update(_G.world, _G.camera_ent, 16 * 0.00001f, 0, 0, 1.0f, 0.0f,\n+//                      0);\n+\n+        char dock_id[32] = {};\n+\n+        for (uint8_t i = 0; i < _G.editor_count; ++i) {\n+            snprintf(dock_id, CETECH_ARRAY_LEN(dock_id), "Level view #%d", i+1);\n+\n+            if (ct_debugui_a0.BeginDock(dock_id, &_G.visible[i],\n+                                        DebugUIWindowFlags_Empty)) {\n+                auto th = ct_renderer_a0.viewport_get_local_resource(\n+                        _G.viewport[i], ct_hash_a0.id64_from_str("bb_color"));\n+\n+                float size[2];\n+                ct_debugui_a0.GetWindowSize(size);\n+                ct_renderer_a0.resize_viewport(_G.viewport[i], size[0], size[1]);\n+                ct_debugui_a0.Image2({th},\n+                                     size,\n+                                     (float[2]) {0.0f, 0.0f},\n+                                     (float[2]) {1.0f, 1.0f},\n+                                     (float[4]) {1.0f, 1.0f, 1.0f, 1.0f},\n+                                     (float[4]) {0.0f, 0.0f, 0.0, 0.0f});\n+            }\n+            ct_debugui_a0.EndDock();\n+        }\n+    }\n+\n+    void render() {\n+        for (uint8_t i = 0; i < _G.editor_count; ++i) {\n+            ct_renderer_a0.render_world(_G.world[i], _G.camera[i],\n+                                        _G.viewport[i]);\n+        }\n+    }\n+\n+    void open_level() {\n+        uint8_t idx = _G.editor_count;\n+        ++_G.editor_count;\n+\n+        _G.visible[idx] = true;\n+\n+        _G.viewport[idx] = ct_renderer_a0.create_viewport(\n+                ct_hash_a0.id64_from_str("default"), 0, 0);\n+\n+        _G.world[idx] = ct_world_a0.create();\n+\n+        _G.camera_ent[idx] = ct_entity_a0.spawn(_G.world[idx],\n+                                                ct_hash_a0.id64_from_str(\n+                                                        "camera"));\n+\n+        _G.camera[idx] = ct_camera_a0.get(_G.world[idx], _G.camera_ent[idx]);\n+\n+        ct_level_a0.load_level(_G.world[idx],\n+                               ct_hash_a0.id64_from_str("level1"));\n+    }\n+\n+    void init() {\n+        open_level();\n+        open_level();\n+    }\n+\n+    void shutdown() {\n+\n+    }\n+}\n+\n+namespace level_view_module {\n+\n+    static ct_level_view_a0 api = {\n+//            .register_module = playground::register_module,\n+//            .unregister_module = playground::unregister_module,\n+    };\n+\n+    static void _init(ct_api_a0 *api) {\n+        api->register_api("ct_level_view_a0", &api);\n+\n+        _G = {};\n+\n+        ct_app_a0.register_on_init(level_view::init);\n+        ct_app_a0.register_on_shutdown(level_view::shutdown);\n+        ct_app_a0.register_on_render(level_view::render);\n+        ct_debugui_a0.register_on_gui(level_view::gui);\n+    }\n+\n+    static void _shutdown() {\n+        ct_app_a0.unregister_on_init(level_view::init);\n+        ct_app_a0.unregister_on_shutdown(level_view::shutdown);\n+        ct_app_a0.unregister_on_render(level_view::render);\n+        ct_debugui_a0.unregister_on_gui(level_view::gui);\n+\n+        _G = {};\n+    }\n+}\n+\n+CETECH_MODULE_DEF(\n+        level_view,\n+        {\n+            CETECH_GET_API(api, ct_memory_a0);\n+            CETECH_GET_API(api, ct_hash_a0);\n+            CETECH_GET_API(api, ct_renderer_a0);\n+            CETECH_GET_API(api, ct_debugui_a0);\n+            CETECH_GET_API(api, ct_app_a0);\n+            CETECH_GET_API(api, ct_world_a0);\n+            CETECH_GET_API(api, ct_level_a0);\n+            CETECH_GET_API(api, ct_entity_a0);\n+            CETECH_GET_API(api, ct_camera_a0);\n+        },\n+        {\n+            level_view_module::_init(api);\n+        },\n+        {\n+            CEL_UNUSED(api);\n+            level_view_module::_shutdown();\n+        }\n+)\n\\ No newline at end of file\n', 'addition_count': 156, 'deletion_count': 0, 'src_file': '/dev/null', 'tgt_file': 'b/src/cetech/modules/playground/private/level_editor.cpp', 'file_extension': '.cpp', 'before_file': 'ADDFILE', 'message': 'PLAYGR-23 - Level editor - basic level viewport\n', 'author_name': 'Ondra Voves', 'lang': 'cpp'}