#pragma once #include "log.h" #include "shader.h" #include "shape.h" #include "texture.h" #include "layout.h" #include "font.h" #include "rtt.h" #include "node_message_box.h" #include "node_settings.h" #include "node_popup_menu.h" #include "node_panel_brush.h" #include "node_panel_layer.h" #include "node_panel_color.h" #include "node_panel_stroke.h" #include "node_scroll.h" #include "node_canvas.h" #include "node_dialog_layer_rename.h" #include "node_progress_bar.h" #if defined(__OBJC__) && defined(__IOS__) #import #import "GameViewController.h" #endif #if defined(__OBJC__) && defined(__OSX__) #import "main.h" #endif #ifdef __ANDROID__ #include "main.h" #endif #include "node_panel_grid.h" #include "node_panel_quick.h" struct VRController { enum class kButton : uint8_t { Pad, Trigger, Menu, Grip, A, COUNT, }; enum class kAction { Press, Release, }; std::array m_buttons; std::array m_analog_buttons; glm::mat4 m_mat; bool m_valid = false; glm::vec3 get_pos() const { return m_mat[3]; } glm::vec3 get_pos_n() const { return glm::normalize(xyz(m_mat[3])); } virtual float get_trigger_value() const { return 1.f; } }; class App { public: static App I; std::string data_path{ "." }; std::string work_path{ "." }; std::string rec_path{ "." }; std::thread rec_thread; bool rec_running = false; int rec_count = 0; std::mutex rec_mutex; std::condition_variable rec_cv; std::deque> rec_frames; RTT uirtt; Sampler sampler; Sampler sampler_stencil; Sampler sampler_linear; Plane m_face_plane; Sphere sphere; LayoutManager layout; NodeMessageBox* msgbox; NodeSettings* settings; NodeBorder* sidebar = nullptr; std::shared_ptr layers; std::shared_ptr color; std::shared_ptr stroke; std::shared_ptr grid; std::shared_ptr presets; NodePanelQuick* quick; std::map quick_mode_state; Node* floatings_container; std::shared_ptr floating_color; std::shared_ptr floating_picker; std::shared_ptr floating_presets; std::shared_ptr floating_layers; NodeCanvas* canvas; const uint16_t main_id = const_hash("main"); const std::array res_map{ 512, 1024, 1536, 2048, 4096, 8192 }; const std::array res_map_str{ "2K", "4K", "6K", "8K", "16K", "32K" }; std::string doc_name = "no-name"; std::string doc_path; std::string doc_dir; std::string doc_filename; bool has_stylus = false; bool has_vr = false; float off_x = 0; float off_y = 0; float width; float height; bool keys[256]; bool redraw = true; bool animate = false; bool ui_visible = true; bool ui_rtl = false; bool vr_active = false; bool vr_only = false; VRController vr_controllers[2]; glm::mat4 vr_head; float vr_pressure = 1.f; glm::mat4 vr_rot{ 0 }; glm::mat4 vr_uirot{ 0 }; glm::vec2 cursor{ 0, 0 }; glm::vec2 gesture_p0; glm::vec2 gesture_p1; #ifdef __ANDROID__ float zoom = 3.0; #elif __IOS__ float zoom = 2.0; #else float zoom = 1.0; #endif // __ANDROID__ #if defined(__IOS__) && defined(__OBJC__) GameViewController* ios_view; #endif #if defined(__OSX__) && defined(__OBJC__) View* osx_view; #endif #ifdef __ANDROID__ struct android_app* and_app; struct engine* and_engine; #endif std::string clipboard_get_text(); bool clipboard_set_text(const std::string& s); void pick_image(std::function callback); void pick_file(std::vector types, std::function callback); void pick_dir(std::function callback); void display_file(std::string path); void share_file(std::string path); void showKeyboard(); void hideKeyboard(); void initLog(); void init(); void initShaders(); void initAssets(); void initLayout(); void open_document(std::string path); void create(); bool request_close(); void terminate(); void clear(); void tick(float dt); void update(float dt); bool update_ui_observer(Node* n); bool vr_start(); void vr_stop(); void vr_update(float dt); void vr_draw(const glm::mat4& proj, const glm::mat4& view, const glm::mat4& pose); void vr_analog(const VRController& c, VRController::kButton b, VRController::kAction a, glm::vec2 force); void vr_digital(const VRController& c, VRController::kButton b, VRController::kAction a, glm::vec2 axis); void vr_draw_ui(); void async_start(); void async_update(); void async_redraw(); void async_end(); void resize(float w, float h); void show_cursor(); void hide_cursor(); bool mouse_down(int button, float x, float y, float pressure, kEventSource source, bool eraser); bool mouse_move(float x, float y, float pressure, kEventSource source, bool eraser); bool mouse_up(int button, float x, float y, kEventSource source, bool eraser); bool mouse_scroll(float x, float y, float delta); bool mouse_cancel(int button); bool gesture_start(const glm::vec2& p0, const glm::vec2& p1); bool gesture_move(const glm::vec2& p0, const glm::vec2& p1); bool gesture_end(); bool key_down(kKey key); bool key_up(kKey key); bool key_char(char key); void toggle_ui(); void set_stylus(); NodeMessageBox* message_box(const std::string& title, const std::string& text, bool cancel_button = false); void rec_clear(); void rec_loop(); void rec_start(); void rec_stop(); void rec_export(std::string path); void init_toolbar_main(); void init_toolbar_draw(); void init_sidebar(); void init_menu_file(); void init_menu_edit(); void init_menu_layer(); void init_menu_tools(); void init_menu_about(); void dialog_usermanual(); void dialog_changelog(); void dialog_about(); void dialog_newdoc(); void dialog_save(); void dialog_save_ver(); void dialog_open(); void dialog_browse(); void dialog_export(std::string ext); void dialog_export_layers(); void dialog_export_depth(); void dialog_export_cubes(); void dialog_layer_rename(); void dialog_resize(); void cloud_upload(); void cloud_upload_all(); void cloud_browse(); void upload(std::string filename, std::string name = "", std::function progress = nullptr); void download(std::string url, std::string dest_filepath, std::function progress = nullptr); bool check_license(); std::shared_ptr show_progress(const std::string& title); void brush_update(); void title_update(); void update_memory_usage(size_t bytes); void update_rec_frames(); int res_from_index(int i); int res_to_index(int res); std::string res_to_string(int res); void crash_test(); void ui_save(); void ui_restore(); void set_ui_rtl(bool rtl); bool get_ui_rtl() const; void cmd_convert(std::string pano_path, std::string out_path); bool is_render_thread() { extern std::thread::id render_thread_id; extern std::thread::id gl_thread; return std::this_thread::get_id() == render_thread_id || std::this_thread::get_id() == gl_thread; } // don't capture a reference to this ptr as the object may be destroyed // by the time the task is executed template::type> std::future render_task_async(T task) { #ifdef _WIN32 extern std::deque> render_tasklist; extern std::mutex render_task_mutex; extern std::condition_variable render_cv; std::packaged_task pt(task); std::future f = pt.get_future(); if (is_render_thread()) { pt(); } else { { std::lock_guard lock(render_task_mutex); render_tasklist.push_back(std::move(pt)); } render_cv.notify_all(); } return f; #endif // _WIN32 } template::type> R render_task(T task) { #ifdef _WIN32 extern std::deque> render_tasklist; extern std::mutex render_task_mutex; extern std::condition_variable render_cv; std::packaged_task pt(task); std::future f = pt.get_future(); if (is_render_thread()) { pt(); } else { { std::lock_guard lock(render_task_mutex); render_tasklist.push_back(std::move(pt)); } render_cv.notify_all(); } return f.get(); #endif // _WIN32 } void render_sync() { render_task([] {}); } };