Extract dialog workflow, bootstrap, and canvas tail helpers
This commit is contained in:
@@ -92,6 +92,7 @@ set(PP_PANOPAINTER_APP_SOURCES
|
|||||||
src/app_cloud.cpp
|
src/app_cloud.cpp
|
||||||
src/app_commands.cpp
|
src/app_commands.cpp
|
||||||
src/app_dialogs.cpp
|
src/app_dialogs.cpp
|
||||||
|
src/app_dialogs_workflow.cpp
|
||||||
src/app_dialogs_export.cpp
|
src/app_dialogs_export.cpp
|
||||||
src/app_dialogs_info_openers.cpp
|
src/app_dialogs_info_openers.cpp
|
||||||
src/app_events.cpp
|
src/app_events.cpp
|
||||||
@@ -164,6 +165,7 @@ set(PP_PANOPAINTER_UI_SOURCES
|
|||||||
|
|
||||||
set(PP_WINDOWS_PLATFORM_SOURCES
|
set(PP_WINDOWS_PLATFORM_SOURCES
|
||||||
src/main.cpp
|
src/main.cpp
|
||||||
|
src/platform_windows/windows_bootstrap_helpers.cpp
|
||||||
src/platform_windows/windows_platform_services.cpp
|
src/platform_windows/windows_platform_services.cpp
|
||||||
src/platform_windows/windows_platform_services.h
|
src/platform_windows/windows_platform_services.h
|
||||||
src/platform_windows/windows_splash.cpp
|
src/platform_windows/windows_splash.cpp
|
||||||
|
|||||||
@@ -83,12 +83,12 @@ Current hotspot files:
|
|||||||
- `src/app_layout.cpp`: 1249 lines
|
- `src/app_layout.cpp`: 1249 lines
|
||||||
- `src/canvas_modes.cpp`: 1798 lines
|
- `src/canvas_modes.cpp`: 1798 lines
|
||||||
- `src/node.cpp`: 1551 lines
|
- `src/node.cpp`: 1551 lines
|
||||||
- `src/main.cpp`: 1117 lines
|
- `src/main.cpp`: 909 lines
|
||||||
- `src/node_panel_brush.cpp`: 1197 lines
|
- `src/node_panel_brush.cpp`: 1197 lines
|
||||||
- `src/node_stroke_preview.cpp`: 933 lines
|
- `src/node_stroke_preview.cpp`: 933 lines
|
||||||
- `src/node_canvas.cpp`: 897 lines
|
- `src/node_canvas.cpp`: 905 lines
|
||||||
- `src/app.cpp`: 502 lines
|
- `src/app.cpp`: 502 lines
|
||||||
- `src/app_dialogs.cpp`: 441 lines
|
- `src/app_dialogs.cpp`: 142 lines
|
||||||
|
|
||||||
Current architecture mismatches that must be treated as real blockers:
|
Current architecture mismatches that must be treated as real blockers:
|
||||||
|
|
||||||
@@ -128,7 +128,8 @@ Current architecture mismatches that must be treated as real blockers:
|
|||||||
per-layer GL setup now also routes through
|
per-layer GL setup now also routes through
|
||||||
`make_legacy_canvas_draw_merge_layer_path_gl_execution(...)` even though the
|
`make_legacy_canvas_draw_merge_layer_path_gl_execution(...)` even though the
|
||||||
remaining draw lambdas and broader node draw loop still live in
|
remaining draw lambdas and broader node draw loop still live in
|
||||||
`src/node_canvas.cpp`.
|
`src/node_canvas.cpp`, where the post-draw/display-resolve tail now also
|
||||||
|
routes through `execute_node_canvas_draw_merge_tail(...)`.
|
||||||
- `app_layout.cpp` and `app_dialogs.cpp` are still mixed shell/controller files
|
- `app_layout.cpp` and `app_dialogs.cpp` are still mixed shell/controller files
|
||||||
rather than thin composition/binding surfaces, even though tools-menu binding
|
rather than thin composition/binding surfaces, even though tools-menu binding
|
||||||
plus nested panels/options submenu wiring now live in
|
plus nested panels/options submenu wiring now live in
|
||||||
@@ -142,7 +143,9 @@ Current architecture mismatches that must be treated as real blockers:
|
|||||||
and the corresponding `App::dialog_*` entrypoints are thinner, while the
|
and the corresponding `App::dialog_*` entrypoints are thinner, while the
|
||||||
export/video/PPBR dialog family now also lives in
|
export/video/PPBR dialog family now also lives in
|
||||||
`src/app_dialogs_export.cpp` and those `App::dialog_*` entrypoints are
|
`src/app_dialogs_export.cpp` and those `App::dialog_*` entrypoints are
|
||||||
thinner too.
|
thinner too, while new/open/save/browse/resize workflow entrypoints now also
|
||||||
|
live in `src/app_dialogs_workflow.cpp` and `src/app_dialogs.cpp` is now
|
||||||
|
mostly a thin dialog dispatch surface.
|
||||||
- `App`, `Canvas`, `Node`, retained workers, and platform entrypoints still use
|
- `App`, `Canvas`, `Node`, retained workers, and platform entrypoints still use
|
||||||
global singleton reach, raw observer pointers, retained static worker
|
global singleton reach, raw observer pointers, retained static worker
|
||||||
ownership in several app families, and ad hoc mutex/condition-variable
|
ownership in several app families, and ad hoc mutex/condition-variable
|
||||||
@@ -171,6 +174,9 @@ Current architecture mismatches that must be treated as real blockers:
|
|||||||
in `src/platform_windows/windows_stylus_input.cpp` instead of `src/main.cpp`,
|
in `src/platform_windows/windows_stylus_input.cpp` instead of `src/main.cpp`,
|
||||||
while the retained Win32 VR/HMD shell now also routes through
|
while the retained Win32 VR/HMD shell now also routes through
|
||||||
`src/platform_windows/windows_vr_shell.h` instead of staying inline in
|
`src/platform_windows/windows_vr_shell.h` instead of staying inline in
|
||||||
|
`src/main.cpp`, while RenderDoc startup/frame capture, SHCore DPI bootstrap,
|
||||||
|
Win32 error-string conversion, and the GL debug pre/post callbacks now also
|
||||||
|
live in `src/platform_windows/windows_bootstrap_helpers.cpp` instead of
|
||||||
`src/main.cpp`,
|
`src/main.cpp`,
|
||||||
while `App::rec_loop()` now delegates worker-iteration orchestration into
|
while `App::rec_loop()` now delegates worker-iteration orchestration into
|
||||||
the retained recording bridge, `App::update_rec_frames()` now delegates
|
the retained recording bridge, `App::update_rec_frames()` now delegates
|
||||||
|
|||||||
@@ -205,6 +205,11 @@ Current slice:
|
|||||||
`make_node_canvas_layer_path_execution(...)` helper, which materially thins
|
`make_node_canvas_layer_path_execution(...)` helper, which materially thins
|
||||||
`NodeCanvas::draw()` even though the broader draw loop still lives in
|
`NodeCanvas::draw()` even though the broader draw loop still lives in
|
||||||
`src/node_canvas.cpp`.
|
`src/node_canvas.cpp`.
|
||||||
|
- `NodeCanvas` post-draw callback assembly, smoothing-mask face execution, and
|
||||||
|
optional display resolve now also route through
|
||||||
|
`execute_node_canvas_draw_merge_tail(...)`, which trims another live tail
|
||||||
|
block from `NodeCanvas::draw()` even though the broader outer draw shell is
|
||||||
|
still inline.
|
||||||
|
|
||||||
Write scope:
|
Write scope:
|
||||||
- `src/node_stroke_preview.cpp`
|
- `src/node_stroke_preview.cpp`
|
||||||
@@ -343,6 +348,9 @@ Current slice:
|
|||||||
`src/app_dialogs_export.cpp`, and the corresponding `App::dialog_*`
|
`src/app_dialogs_export.cpp`, and the corresponding `App::dialog_*`
|
||||||
entrypoints are now thin call-throughs, but new/open/save/browse/resize and
|
entrypoints are now thin call-throughs, but new/open/save/browse/resize and
|
||||||
retained dialog execution are still inline in `src/app_dialogs.cpp`.
|
retained dialog execution are still inline in `src/app_dialogs.cpp`.
|
||||||
|
- New/open/save/browse/resize workflow entrypoints now also live in
|
||||||
|
`src/app_dialogs_workflow.cpp`, and `src/app_dialogs.cpp` is down to the
|
||||||
|
remaining thin entrypoints plus layer-rename retained dialog glue.
|
||||||
|
|
||||||
Write scope:
|
Write scope:
|
||||||
- `src/app_dialogs.cpp`
|
- `src/app_dialogs.cpp`
|
||||||
@@ -448,6 +456,10 @@ Current slice:
|
|||||||
state, now routes through `src/platform_windows/windows_vr_shell.h` instead
|
state, now routes through `src/platform_windows/windows_vr_shell.h` instead
|
||||||
of staying inline in `src/main.cpp`, but broader retained Win32 shell state
|
of staying inline in `src/main.cpp`, but broader retained Win32 shell state
|
||||||
is still open
|
is still open
|
||||||
|
- RenderDoc startup/frame capture, SHCore DPI bootstrap, Win32 error-string
|
||||||
|
conversion, `UnadjustWindowRectEx`, and GL debug pre/post callbacks now also
|
||||||
|
live in `src/platform_windows/windows_bootstrap_helpers.cpp` instead of
|
||||||
|
`src/main.cpp`
|
||||||
- prepared-file background work now runs through an `AppRuntime`-owned worker
|
- prepared-file background work now runs through an `AppRuntime`-owned worker
|
||||||
queue instead of a retained static worker in `src/app_events.cpp`
|
queue instead of a retained static worker in `src/app_events.cpp`
|
||||||
- canvas async import/export/save/open background work now also runs through an
|
- canvas async import/export/save/open background work now also runs through an
|
||||||
|
|||||||
@@ -2,100 +2,29 @@
|
|||||||
#include "app.h"
|
#include "app.h"
|
||||||
#include "app_core/app_dialog.h"
|
#include "app_core/app_dialog.h"
|
||||||
#include "app_core/document_layer.h"
|
#include "app_core/document_layer.h"
|
||||||
#include "app_core/document_resize.h"
|
|
||||||
#include "app_core/document_export.h"
|
|
||||||
#include "app_core/document_session.h"
|
|
||||||
#include "legacy_document_canvas_services.h"
|
|
||||||
#include "legacy_app_dialog_services.h"
|
#include "legacy_app_dialog_services.h"
|
||||||
#include "legacy_brush_package_export_services.h"
|
|
||||||
#include "legacy_document_export_services.h"
|
|
||||||
#include "legacy_document_layer_services.h"
|
#include "legacy_document_layer_services.h"
|
||||||
#include "legacy_document_session_services.h"
|
|
||||||
#include "legacy_ui_overlay_services.h"
|
#include "legacy_ui_overlay_services.h"
|
||||||
#include "node_dialog_open.h"
|
#include "node_dialog_layer_rename.h"
|
||||||
#include "node_dialog_browse.h"
|
|
||||||
#include "node_dialog_resize.h"
|
|
||||||
#include "node_dialog_cloud.h"
|
|
||||||
|
|
||||||
#ifdef __QUEST__
|
#ifdef __QUEST__
|
||||||
#include "oculus_vr.h"
|
#include "oculus_vr.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace pp::panopainter {
|
namespace pp::panopainter {
|
||||||
void open_usermanual_dialog(App& app);
|
|
||||||
void open_changelog_dialog(App& app);
|
|
||||||
void open_about_dialog(App& app);
|
|
||||||
void open_whatsnew_dialog(App& app, bool force_show);
|
|
||||||
void open_shortcuts_dialog(App& app);
|
|
||||||
void open_document_export_dialog(App& app, std::string ext);
|
void open_document_export_dialog(App& app, std::string ext);
|
||||||
void open_document_export_layers_dialog(App& app);
|
void open_document_export_layers_dialog(App& app);
|
||||||
void open_document_export_anim_frames_dialog(App& app);
|
void open_document_export_anim_frames_dialog(App& app);
|
||||||
void open_document_export_depth_dialog(App& app);
|
void open_document_export_depth_dialog(App& app);
|
||||||
void open_document_export_cube_faces_dialog(App& app);
|
void open_document_export_cube_faces_dialog(App& app);
|
||||||
|
void open_ppbr_export_dialog(App& app);
|
||||||
void open_document_timelapse_export_dialog(App& app);
|
void open_document_timelapse_export_dialog(App& app);
|
||||||
void open_document_export_mp4_dialog(App& app);
|
void open_document_export_mp4_dialog(App& app);
|
||||||
void open_ppbr_export_dialog(App& app);
|
void open_usermanual_dialog(App& app);
|
||||||
}
|
void open_changelog_dialog(App& app);
|
||||||
|
void open_about_dialog(App& app);
|
||||||
namespace {
|
void open_whatsnew_dialog(App& app, bool force_show);
|
||||||
|
void open_shortcuts_dialog(App& app);
|
||||||
void wire_document_browse_dialog_actions(
|
|
||||||
App& app,
|
|
||||||
const std::shared_ptr<NodeDialogBrowse>& dialog,
|
|
||||||
Node& overlay_anchor,
|
|
||||||
pp::ui::NodeHandle overlay_handle)
|
|
||||||
{
|
|
||||||
const auto close_dialog = [&overlay_anchor, overlay_handle]() {
|
|
||||||
const auto close_status =
|
|
||||||
pp::panopainter::close_legacy_overlay_node(overlay_anchor, overlay_handle);
|
|
||||||
(void)close_status;
|
|
||||||
};
|
|
||||||
|
|
||||||
dialog->btn_ok->on_click = [&app, dialog, close_dialog](Node*)
|
|
||||||
{
|
|
||||||
if (dialog->is_selected())
|
|
||||||
{
|
|
||||||
app.open_document(dialog->selected_path);
|
|
||||||
close_dialog();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
dialog->btn_cancel->on_click = [close_dialog](Node*)
|
|
||||||
{
|
|
||||||
close_dialog();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
void wire_document_save_dialog_buttons(
|
|
||||||
App& app,
|
|
||||||
const std::shared_ptr<NodeDialogSave>& dialog,
|
|
||||||
std::function<void()> close_dialog)
|
|
||||||
{
|
|
||||||
dialog->btn_ok->on_click = [&app, dialog](Node*)
|
|
||||||
{
|
|
||||||
std::string name = dialog->input->m_text;
|
|
||||||
const auto plan = pp::app::plan_document_file_save(
|
|
||||||
app.work_path,
|
|
||||||
name,
|
|
||||||
[](const std::string& path) {
|
|
||||||
return Asset::exist(path);
|
|
||||||
});
|
|
||||||
if (!plan)
|
|
||||||
{
|
|
||||||
app.message_box("Warning", "You need to specify a name to file.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto status =
|
|
||||||
pp::panopainter::execute_legacy_document_file_save_plan(app, plan.value(), dialog);
|
|
||||||
if (!status.ok())
|
|
||||||
LOG("Document file save action failed: %s", status.message);
|
|
||||||
};
|
|
||||||
dialog->btn_cancel->on_click = [close_dialog](Node*)
|
|
||||||
{
|
|
||||||
close_dialog();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<NodeProgressBar> App::show_progress(const std::string& title, int total /*= 0*/)
|
std::shared_ptr<NodeProgressBar> App::show_progress(const std::string& title, int total /*= 0*/)
|
||||||
@@ -139,234 +68,6 @@ void App::dialog_about()
|
|||||||
pp::panopainter::open_about_dialog(*this);
|
pp::panopainter::open_about_dialog(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void App::continue_document_workflow_after_optional_save(std::function<void()> action)
|
|
||||||
{
|
|
||||||
const bool has_canvas = canvas != nullptr;
|
|
||||||
const bool has_unsaved_changes = has_canvas && Canvas::I->m_unsaved;
|
|
||||||
const auto decision = pp::app::plan_document_workflow(has_canvas, has_unsaved_changes);
|
|
||||||
const auto status = pp::panopainter::execute_legacy_document_workflow_decision(
|
|
||||||
*this,
|
|
||||||
decision,
|
|
||||||
std::move(action));
|
|
||||||
if (!status.ok())
|
|
||||||
LOG("Document workflow action failed: %s", status.message);
|
|
||||||
}
|
|
||||||
|
|
||||||
void App::dialog_newdoc()
|
|
||||||
{
|
|
||||||
auto show_dialog = [this] {
|
|
||||||
auto* overlay_anchor = layout[main_id];
|
|
||||||
if (!overlay_anchor) {
|
|
||||||
LOG("New document dialog open failed: main layout anchor is missing");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto dialog = pp::panopainter::make_legacy_overlay_node<NodeDialogNewDoc>(*this);
|
|
||||||
dialog->input->set_text("name");
|
|
||||||
|
|
||||||
App::I->showKeyboard();
|
|
||||||
|
|
||||||
const auto overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*overlay_anchor, dialog);
|
|
||||||
if (!overlay) {
|
|
||||||
App::I->hideKeyboard();
|
|
||||||
LOG("New document dialog open failed: %s", overlay.status().message);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const auto overlay_handle = overlay.value();
|
|
||||||
|
|
||||||
const auto close_dialog = [this, overlay_anchor, overlay_handle]() {
|
|
||||||
const auto close_status = pp::panopainter::close_legacy_overlay_node(*overlay_anchor, overlay_handle);
|
|
||||||
(void)close_status;
|
|
||||||
App::I->hideKeyboard();
|
|
||||||
};
|
|
||||||
|
|
||||||
dialog->btn_ok->on_click = [this, dialog](Node*)
|
|
||||||
{
|
|
||||||
std::string name = dialog->input->m_text;
|
|
||||||
const auto plan = pp::app::plan_new_document(
|
|
||||||
work_path,
|
|
||||||
name,
|
|
||||||
dialog->m_resolution->m_current_index,
|
|
||||||
[](const std::string& path) {
|
|
||||||
return Asset::exist(path);
|
|
||||||
});
|
|
||||||
if (!plan)
|
|
||||||
{
|
|
||||||
const bool missing_name =
|
|
||||||
plan.status().code == pp::foundation::StatusCode::invalid_argument;
|
|
||||||
message_box(
|
|
||||||
"Warning",
|
|
||||||
missing_name ? "You need to specify a name to file." : plan.status().message);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto status = pp::panopainter::execute_legacy_new_document_plan(*this, plan.value(), dialog);
|
|
||||||
if (!status.ok())
|
|
||||||
LOG("New document action failed: %s", status.message);
|
|
||||||
|
|
||||||
};
|
|
||||||
dialog->btn_cancel->on_click = [close_dialog](Node*)
|
|
||||||
{
|
|
||||||
close_dialog();
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
continue_document_workflow_after_optional_save(show_dialog);
|
|
||||||
}
|
|
||||||
|
|
||||||
// DEPRECATED
|
|
||||||
void App::dialog_open()
|
|
||||||
{
|
|
||||||
auto show_dialog = [this] {
|
|
||||||
// load thumbnail test
|
|
||||||
auto* overlay_anchor = layout[main_id];
|
|
||||||
if (!overlay_anchor) {
|
|
||||||
LOG("Open document dialog open failed: main layout anchor is missing");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto dialog = pp::panopainter::make_legacy_overlay_node<NodeDialogOpen>(*this);
|
|
||||||
|
|
||||||
const auto overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*overlay_anchor, dialog);
|
|
||||||
if (!overlay) {
|
|
||||||
LOG("Open document dialog open failed: %s", overlay.status().message);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const auto overlay_handle = overlay.value();
|
|
||||||
|
|
||||||
const auto close_dialog = [overlay_anchor, overlay_handle]() {
|
|
||||||
const auto close_status = pp::panopainter::close_legacy_overlay_node(*overlay_anchor, overlay_handle);
|
|
||||||
(void)close_status;
|
|
||||||
};
|
|
||||||
|
|
||||||
dialog->btn_ok->on_click = [this, dialog](Node*)
|
|
||||||
{
|
|
||||||
// canvas->reset_camera();
|
|
||||||
// layers->clear();
|
|
||||||
// doc_name = dialog->selected_name;
|
|
||||||
// canvas->m_canvas->project_open(dialog->selected_path, [this](bool success) {
|
|
||||||
// // on complete
|
|
||||||
// async_start();
|
|
||||||
// title_update();
|
|
||||||
// for (auto& i : canvas->m_canvas->m_order)
|
|
||||||
// layers->add_layer(canvas->m_canvas->m_layers[i]->m_name.c_str());
|
|
||||||
// async_end();
|
|
||||||
// });
|
|
||||||
// dialog->destroy();
|
|
||||||
// ActionManager::clear();
|
|
||||||
};
|
|
||||||
dialog->btn_cancel->on_click = [close_dialog](Node*)
|
|
||||||
{
|
|
||||||
close_dialog();
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
continue_document_workflow_after_optional_save(show_dialog);
|
|
||||||
}
|
|
||||||
|
|
||||||
void App::dialog_browse()
|
|
||||||
{
|
|
||||||
auto show_dialog = [this] {
|
|
||||||
auto* overlay_anchor = layout[main_id];
|
|
||||||
if (!overlay_anchor) {
|
|
||||||
LOG("Browse document dialog open failed: main layout anchor is missing");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto dialog = pp::panopainter::make_legacy_overlay_node<NodeDialogBrowse>(*this);
|
|
||||||
dialog->search_paths = document_browse_roots();
|
|
||||||
|
|
||||||
const auto overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*overlay_anchor, dialog);
|
|
||||||
if (!overlay) {
|
|
||||||
LOG("Browse document dialog open failed: %s", overlay.status().message);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const auto overlay_handle = overlay.value();
|
|
||||||
wire_document_browse_dialog_actions(*this, dialog, *overlay_anchor, overlay_handle);
|
|
||||||
};
|
|
||||||
|
|
||||||
continue_document_workflow_after_optional_save(show_dialog);
|
|
||||||
}
|
|
||||||
|
|
||||||
void save_document_version(App& app)
|
|
||||||
{
|
|
||||||
const auto target = pp::app::find_next_document_version_target(
|
|
||||||
app.doc_dir,
|
|
||||||
app.doc_name,
|
|
||||||
[](const std::string& path) {
|
|
||||||
return Asset::exist(path);
|
|
||||||
});
|
|
||||||
if (!target) {
|
|
||||||
app.message_box("Saving Error", target.status().message);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto status = pp::panopainter::execute_legacy_document_version_save(app, target.value());
|
|
||||||
if (!status.ok())
|
|
||||||
LOG("Document version save action failed: %s", status.message);
|
|
||||||
}
|
|
||||||
|
|
||||||
void App::dialog_save_ver()
|
|
||||||
{
|
|
||||||
if (!check_license())
|
|
||||||
{
|
|
||||||
message_box("License", "This function is disabled in demo mode.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
save_document_version(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void App::save_document(pp::app::DocumentSaveIntent intent)
|
|
||||||
{
|
|
||||||
const auto decision = pp::app::plan_document_save(
|
|
||||||
Canvas::I->m_newdoc,
|
|
||||||
Canvas::I->m_unsaved,
|
|
||||||
intent);
|
|
||||||
const auto status = pp::panopainter::execute_legacy_document_save_decision(*this, decision);
|
|
||||||
if (!status.ok())
|
|
||||||
LOG("Document save action failed: %s", status.message);
|
|
||||||
}
|
|
||||||
|
|
||||||
void App::dialog_save()
|
|
||||||
{
|
|
||||||
if (!check_license())
|
|
||||||
{
|
|
||||||
message_box("License", "This function is disabled in demo mode.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (canvas)
|
|
||||||
{
|
|
||||||
auto* overlay_anchor = layout[main_id];
|
|
||||||
if (!overlay_anchor) {
|
|
||||||
LOG("Save document dialog open failed: main layout anchor is missing");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto dialog = pp::panopainter::make_legacy_overlay_node<NodeDialogSave>(*this);
|
|
||||||
dialog->input->set_text(doc_name);
|
|
||||||
|
|
||||||
App::I->showKeyboard();
|
|
||||||
|
|
||||||
const auto overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*overlay_anchor, dialog);
|
|
||||||
if (!overlay) {
|
|
||||||
App::I->hideKeyboard();
|
|
||||||
LOG("Save document dialog open failed: %s", overlay.status().message);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const auto overlay_handle = overlay.value();
|
|
||||||
|
|
||||||
const auto close_dialog = [this, overlay_anchor, overlay_handle]() {
|
|
||||||
const auto close_status = pp::panopainter::close_legacy_overlay_node(*overlay_anchor, overlay_handle);
|
|
||||||
(void)close_status;
|
|
||||||
App::I->hideKeyboard();
|
|
||||||
};
|
|
||||||
|
|
||||||
wire_document_save_dialog_buttons(*this, dialog, close_dialog);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void App::dialog_export(std::string ext)
|
void App::dialog_export(std::string ext)
|
||||||
{
|
{
|
||||||
pp::panopainter::open_document_export_dialog(*this, ext);
|
pp::panopainter::open_document_export_dialog(*this, ext);
|
||||||
@@ -387,47 +88,6 @@ void App::dialog_export_depth()
|
|||||||
pp::panopainter::open_document_export_depth_dialog(*this);
|
pp::panopainter::open_document_export_depth_dialog(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void App::dialog_resize()
|
|
||||||
{
|
|
||||||
auto* overlay_anchor = layout[main_id];
|
|
||||||
if (!overlay_anchor) {
|
|
||||||
LOG("Resize dialog open failed: main layout anchor is missing");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto dialog = pp::panopainter::make_legacy_overlay_node<NodeDialogResize>(*this);
|
|
||||||
const auto overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*overlay_anchor, dialog);
|
|
||||||
if (!overlay) {
|
|
||||||
LOG("Resize dialog open failed: %s", overlay.status().message);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const auto overlay_handle = overlay.value();
|
|
||||||
|
|
||||||
const auto close_dialog = [overlay_anchor, overlay_handle]() {
|
|
||||||
const auto close_status =
|
|
||||||
pp::panopainter::close_legacy_overlay_node(*overlay_anchor, overlay_handle);
|
|
||||||
(void)close_status;
|
|
||||||
};
|
|
||||||
|
|
||||||
dialog->btn_ok->on_click = [this, dialog, close_dialog](Node*)
|
|
||||||
{
|
|
||||||
const auto plan = pp::app::plan_document_resize(
|
|
||||||
dialog->combo ? dialog->combo->m_current_index : 0);
|
|
||||||
if (!plan)
|
|
||||||
{
|
|
||||||
close_dialog();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const auto status = pp::panopainter::execute_legacy_document_resize_plan(*this, plan.value());
|
|
||||||
if (!status.ok())
|
|
||||||
LOG("Document resize failed: %s", status.message);
|
|
||||||
close_dialog();
|
|
||||||
};
|
|
||||||
dialog->btn_cancel->on_click = [close_dialog](Node*) {
|
|
||||||
close_dialog();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
void App::dialog_export_cube_faces()
|
void App::dialog_export_cube_faces()
|
||||||
{
|
{
|
||||||
pp::panopainter::open_document_export_cube_faces_dialog(*this);
|
pp::panopainter::open_document_export_cube_faces_dialog(*this);
|
||||||
|
|||||||
343
src/app_dialogs_workflow.cpp
Normal file
343
src/app_dialogs_workflow.cpp
Normal file
@@ -0,0 +1,343 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
#include "app.h"
|
||||||
|
#include "app_core/document_resize.h"
|
||||||
|
#include "legacy_document_canvas_services.h"
|
||||||
|
#include "legacy_document_session_services.h"
|
||||||
|
#include "legacy_ui_overlay_services.h"
|
||||||
|
#include "node_dialog_browse.h"
|
||||||
|
#include "node_dialog_open.h"
|
||||||
|
#include "node_dialog_resize.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
void wire_document_browse_dialog_actions(
|
||||||
|
App& app,
|
||||||
|
const std::shared_ptr<NodeDialogBrowse>& dialog,
|
||||||
|
Node& overlay_anchor,
|
||||||
|
pp::ui::NodeHandle overlay_handle)
|
||||||
|
{
|
||||||
|
const auto close_dialog = [&overlay_anchor, overlay_handle]() {
|
||||||
|
const auto close_status =
|
||||||
|
pp::panopainter::close_legacy_overlay_node(overlay_anchor, overlay_handle);
|
||||||
|
(void)close_status;
|
||||||
|
};
|
||||||
|
|
||||||
|
dialog->btn_ok->on_click = [&app, dialog, close_dialog](Node*)
|
||||||
|
{
|
||||||
|
if (dialog->is_selected())
|
||||||
|
{
|
||||||
|
app.open_document(dialog->selected_path);
|
||||||
|
close_dialog();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
dialog->btn_cancel->on_click = [close_dialog](Node*)
|
||||||
|
{
|
||||||
|
close_dialog();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void wire_document_save_dialog_buttons(
|
||||||
|
App& app,
|
||||||
|
const std::shared_ptr<NodeDialogSave>& dialog,
|
||||||
|
std::function<void()> close_dialog)
|
||||||
|
{
|
||||||
|
dialog->btn_ok->on_click = [&app, dialog](Node*)
|
||||||
|
{
|
||||||
|
std::string name = dialog->input->m_text;
|
||||||
|
const auto plan = pp::app::plan_document_file_save(
|
||||||
|
app.work_path,
|
||||||
|
name,
|
||||||
|
[](const std::string& path) {
|
||||||
|
return Asset::exist(path);
|
||||||
|
});
|
||||||
|
if (!plan)
|
||||||
|
{
|
||||||
|
app.message_box("Warning", "You need to specify a name to file.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto status =
|
||||||
|
pp::panopainter::execute_legacy_document_file_save_plan(app, plan.value(), dialog);
|
||||||
|
if (!status.ok())
|
||||||
|
LOG("Document file save action failed: %s", status.message);
|
||||||
|
};
|
||||||
|
dialog->btn_cancel->on_click = [close_dialog](Node*)
|
||||||
|
{
|
||||||
|
close_dialog();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void save_document_version(App& app)
|
||||||
|
{
|
||||||
|
const auto target = pp::app::find_next_document_version_target(
|
||||||
|
app.doc_dir,
|
||||||
|
app.doc_name,
|
||||||
|
[](const std::string& path) {
|
||||||
|
return Asset::exist(path);
|
||||||
|
});
|
||||||
|
if (!target) {
|
||||||
|
app.message_box("Saving Error", target.status().message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto status = pp::panopainter::execute_legacy_document_version_save(app, target.value());
|
||||||
|
if (!status.ok())
|
||||||
|
LOG("Document version save action failed: %s", status.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
void App::continue_document_workflow_after_optional_save(std::function<void()> action)
|
||||||
|
{
|
||||||
|
const bool has_canvas = canvas != nullptr;
|
||||||
|
const bool has_unsaved_changes = has_canvas && Canvas::I->m_unsaved;
|
||||||
|
const auto decision = pp::app::plan_document_workflow(has_canvas, has_unsaved_changes);
|
||||||
|
const auto status = pp::panopainter::execute_legacy_document_workflow_decision(
|
||||||
|
*this,
|
||||||
|
decision,
|
||||||
|
std::move(action));
|
||||||
|
if (!status.ok())
|
||||||
|
LOG("Document workflow action failed: %s", status.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
void App::dialog_newdoc()
|
||||||
|
{
|
||||||
|
auto show_dialog = [this] {
|
||||||
|
auto* overlay_anchor = layout[main_id];
|
||||||
|
if (!overlay_anchor) {
|
||||||
|
LOG("New document dialog open failed: main layout anchor is missing");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto dialog = pp::panopainter::make_legacy_overlay_node<NodeDialogNewDoc>(*this);
|
||||||
|
dialog->input->set_text("name");
|
||||||
|
|
||||||
|
App::I->showKeyboard();
|
||||||
|
|
||||||
|
const auto overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*overlay_anchor, dialog);
|
||||||
|
if (!overlay) {
|
||||||
|
App::I->hideKeyboard();
|
||||||
|
LOG("New document dialog open failed: %s", overlay.status().message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto overlay_handle = overlay.value();
|
||||||
|
|
||||||
|
const auto close_dialog = [this, overlay_anchor, overlay_handle]() {
|
||||||
|
const auto close_status =
|
||||||
|
pp::panopainter::close_legacy_overlay_node(*overlay_anchor, overlay_handle);
|
||||||
|
(void)close_status;
|
||||||
|
App::I->hideKeyboard();
|
||||||
|
};
|
||||||
|
|
||||||
|
dialog->btn_ok->on_click = [this, dialog](Node*)
|
||||||
|
{
|
||||||
|
std::string name = dialog->input->m_text;
|
||||||
|
const auto plan = pp::app::plan_new_document(
|
||||||
|
work_path,
|
||||||
|
name,
|
||||||
|
dialog->m_resolution->m_current_index,
|
||||||
|
[](const std::string& path) {
|
||||||
|
return Asset::exist(path);
|
||||||
|
});
|
||||||
|
if (!plan)
|
||||||
|
{
|
||||||
|
const bool missing_name =
|
||||||
|
plan.status().code == pp::foundation::StatusCode::invalid_argument;
|
||||||
|
message_box(
|
||||||
|
"Warning",
|
||||||
|
missing_name ? "You need to specify a name to file." : plan.status().message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto status =
|
||||||
|
pp::panopainter::execute_legacy_new_document_plan(*this, plan.value(), dialog);
|
||||||
|
if (!status.ok())
|
||||||
|
LOG("New document action failed: %s", status.message);
|
||||||
|
|
||||||
|
};
|
||||||
|
dialog->btn_cancel->on_click = [close_dialog](Node*)
|
||||||
|
{
|
||||||
|
close_dialog();
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
continue_document_workflow_after_optional_save(show_dialog);
|
||||||
|
}
|
||||||
|
|
||||||
|
// DEPRECATED
|
||||||
|
void App::dialog_open()
|
||||||
|
{
|
||||||
|
auto show_dialog = [this] {
|
||||||
|
// load thumbnail test
|
||||||
|
auto* overlay_anchor = layout[main_id];
|
||||||
|
if (!overlay_anchor) {
|
||||||
|
LOG("Open document dialog open failed: main layout anchor is missing");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto dialog = pp::panopainter::make_legacy_overlay_node<NodeDialogOpen>(*this);
|
||||||
|
|
||||||
|
const auto overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*overlay_anchor, dialog);
|
||||||
|
if (!overlay) {
|
||||||
|
LOG("Open document dialog open failed: %s", overlay.status().message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto overlay_handle = overlay.value();
|
||||||
|
|
||||||
|
const auto close_dialog = [overlay_anchor, overlay_handle]() {
|
||||||
|
const auto close_status =
|
||||||
|
pp::panopainter::close_legacy_overlay_node(*overlay_anchor, overlay_handle);
|
||||||
|
(void)close_status;
|
||||||
|
};
|
||||||
|
|
||||||
|
dialog->btn_ok->on_click = [this, dialog](Node*)
|
||||||
|
{
|
||||||
|
// canvas->reset_camera();
|
||||||
|
// layers->clear();
|
||||||
|
// doc_name = dialog->selected_name;
|
||||||
|
// canvas->m_canvas->project_open(dialog->selected_path, [this](bool success) {
|
||||||
|
// // on complete
|
||||||
|
// async_start();
|
||||||
|
// title_update();
|
||||||
|
// for (auto& i : canvas->m_canvas->m_order)
|
||||||
|
// layers->add_layer(canvas->m_canvas->m_layers[i]->m_name.c_str());
|
||||||
|
// async_end();
|
||||||
|
// });
|
||||||
|
// dialog->destroy();
|
||||||
|
// ActionManager::clear();
|
||||||
|
};
|
||||||
|
dialog->btn_cancel->on_click = [close_dialog](Node*)
|
||||||
|
{
|
||||||
|
close_dialog();
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
continue_document_workflow_after_optional_save(show_dialog);
|
||||||
|
}
|
||||||
|
|
||||||
|
void App::dialog_browse()
|
||||||
|
{
|
||||||
|
auto show_dialog = [this] {
|
||||||
|
auto* overlay_anchor = layout[main_id];
|
||||||
|
if (!overlay_anchor) {
|
||||||
|
LOG("Browse document dialog open failed: main layout anchor is missing");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto dialog = pp::panopainter::make_legacy_overlay_node<NodeDialogBrowse>(*this);
|
||||||
|
dialog->search_paths = document_browse_roots();
|
||||||
|
|
||||||
|
const auto overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*overlay_anchor, dialog);
|
||||||
|
if (!overlay) {
|
||||||
|
LOG("Browse document dialog open failed: %s", overlay.status().message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto overlay_handle = overlay.value();
|
||||||
|
wire_document_browse_dialog_actions(*this, dialog, *overlay_anchor, overlay_handle);
|
||||||
|
};
|
||||||
|
|
||||||
|
continue_document_workflow_after_optional_save(show_dialog);
|
||||||
|
}
|
||||||
|
|
||||||
|
void App::dialog_save_ver()
|
||||||
|
{
|
||||||
|
if (!check_license())
|
||||||
|
{
|
||||||
|
message_box("License", "This function is disabled in demo mode.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
save_document_version(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void App::save_document(pp::app::DocumentSaveIntent intent)
|
||||||
|
{
|
||||||
|
const auto decision = pp::app::plan_document_save(
|
||||||
|
Canvas::I->m_newdoc,
|
||||||
|
Canvas::I->m_unsaved,
|
||||||
|
intent);
|
||||||
|
const auto status = pp::panopainter::execute_legacy_document_save_decision(*this, decision);
|
||||||
|
if (!status.ok())
|
||||||
|
LOG("Document save action failed: %s", status.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
void App::dialog_save()
|
||||||
|
{
|
||||||
|
if (!check_license())
|
||||||
|
{
|
||||||
|
message_box("License", "This function is disabled in demo mode.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (canvas)
|
||||||
|
{
|
||||||
|
auto* overlay_anchor = layout[main_id];
|
||||||
|
if (!overlay_anchor) {
|
||||||
|
LOG("Save document dialog open failed: main layout anchor is missing");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto dialog = pp::panopainter::make_legacy_overlay_node<NodeDialogSave>(*this);
|
||||||
|
dialog->input->set_text(doc_name);
|
||||||
|
|
||||||
|
App::I->showKeyboard();
|
||||||
|
|
||||||
|
const auto overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*overlay_anchor, dialog);
|
||||||
|
if (!overlay) {
|
||||||
|
App::I->hideKeyboard();
|
||||||
|
LOG("Save document dialog open failed: %s", overlay.status().message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto overlay_handle = overlay.value();
|
||||||
|
|
||||||
|
const auto close_dialog = [this, overlay_anchor, overlay_handle]() {
|
||||||
|
const auto close_status =
|
||||||
|
pp::panopainter::close_legacy_overlay_node(*overlay_anchor, overlay_handle);
|
||||||
|
(void)close_status;
|
||||||
|
App::I->hideKeyboard();
|
||||||
|
};
|
||||||
|
|
||||||
|
wire_document_save_dialog_buttons(*this, dialog, close_dialog);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void App::dialog_resize()
|
||||||
|
{
|
||||||
|
auto* overlay_anchor = layout[main_id];
|
||||||
|
if (!overlay_anchor) {
|
||||||
|
LOG("Resize dialog open failed: main layout anchor is missing");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto dialog = pp::panopainter::make_legacy_overlay_node<NodeDialogResize>(*this);
|
||||||
|
const auto overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*overlay_anchor, dialog);
|
||||||
|
if (!overlay) {
|
||||||
|
LOG("Resize dialog open failed: %s", overlay.status().message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto overlay_handle = overlay.value();
|
||||||
|
|
||||||
|
const auto close_dialog = [overlay_anchor, overlay_handle]() {
|
||||||
|
const auto close_status =
|
||||||
|
pp::panopainter::close_legacy_overlay_node(*overlay_anchor, overlay_handle);
|
||||||
|
(void)close_status;
|
||||||
|
};
|
||||||
|
|
||||||
|
dialog->btn_ok->on_click = [this, dialog, close_dialog](Node*)
|
||||||
|
{
|
||||||
|
const auto plan = pp::app::plan_document_resize(
|
||||||
|
dialog->combo ? dialog->combo->m_current_index : 0);
|
||||||
|
if (!plan)
|
||||||
|
{
|
||||||
|
close_dialog();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto status = pp::panopainter::execute_legacy_document_resize_plan(*this, plan.value());
|
||||||
|
if (!status.ok())
|
||||||
|
LOG("Document resize failed: %s", status.message);
|
||||||
|
close_dialog();
|
||||||
|
};
|
||||||
|
dialog->btn_cancel->on_click = [close_dialog](Node*) {
|
||||||
|
close_dialog();
|
||||||
|
};
|
||||||
|
}
|
||||||
104
src/main.cpp
104
src/main.cpp
@@ -43,6 +43,15 @@ namespace pp::platform::windows {
|
|||||||
void unlock_async_render_context();
|
void unlock_async_render_context();
|
||||||
void swap_async_render_context();
|
void swap_async_render_context();
|
||||||
}
|
}
|
||||||
|
extern HRESULT(*GetDpiForMonitor_fn)(HMONITOR hmonitor, MONITOR_DPI_TYPE dpiType, UINT* dpiX, UINT* dpiY);
|
||||||
|
extern HRESULT(*SetProcessDpiAwareness_fn)(PROCESS_DPI_AWARENESS value);
|
||||||
|
bool win32_renderdoc_init();
|
||||||
|
void win32_renderdoc_frame_start();
|
||||||
|
void win32_renderdoc_frame_end();
|
||||||
|
void init_shcore_API();
|
||||||
|
std::string GetLastErrorAsString();
|
||||||
|
void _pre_call_callback(const char* name, void* funcptr, int len_args, ...);
|
||||||
|
void _post_call_callback(const char* name, void* funcptr, int len_args, ...);
|
||||||
struct RetainedState
|
struct RetainedState
|
||||||
{
|
{
|
||||||
HINSTANCE hInst{};
|
HINSTANCE hInst{};
|
||||||
@@ -120,71 +129,6 @@ void pp_windows_enqueue_main_task(std::packaged_task<void()> task)
|
|||||||
|
|
||||||
std::atomic<int> running{-1};
|
std::atomic<int> running{-1};
|
||||||
|
|
||||||
#ifdef USE_RENDERDOC
|
|
||||||
RENDERDOC_API_1_4_0* rdoc_api = NULL;
|
|
||||||
bool win32_renderdoc_init()
|
|
||||||
{
|
|
||||||
// At init, on windows
|
|
||||||
if (HMODULE mod = GetModuleHandleA("renderdoc.dll"))
|
|
||||||
{
|
|
||||||
pRENDERDOC_GetAPI RENDERDOC_GetAPI =
|
|
||||||
(pRENDERDOC_GetAPI)GetProcAddress(mod, "RENDERDOC_GetAPI");
|
|
||||||
return RENDERDOC_GetAPI(eRENDERDOC_API_Version_1_1_2, (void**)&rdoc_api);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void win32_renderdoc_frame_start()
|
|
||||||
{
|
|
||||||
if (rdoc_api)
|
|
||||||
rdoc_api->StartFrameCapture(NULL, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void win32_renderdoc_frame_end()
|
|
||||||
{
|
|
||||||
if (rdoc_api)
|
|
||||||
rdoc_api->EndFrameCapture(NULL, NULL);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
void win32_renderdoc_frame_start() { }
|
|
||||||
void win32_renderdoc_frame_end() { }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
HRESULT(*GetDpiForMonitor_fn)(HMONITOR hmonitor, MONITOR_DPI_TYPE dpiType, UINT* dpiX, UINT* dpiY);
|
|
||||||
HRESULT(*SetProcessDpiAwareness_fn)(PROCESS_DPI_AWARENESS value);
|
|
||||||
void init_shcore_API()
|
|
||||||
{
|
|
||||||
HMODULE dll = LoadLibrary(L"Shcore.dll");
|
|
||||||
if (!dll)
|
|
||||||
{
|
|
||||||
LOG("cannot load Shcore.dll");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
LOG("loaded Shcore.dll");
|
|
||||||
GetDpiForMonitor_fn = (decltype(GetDpiForMonitor_fn))GetProcAddress(dll, "GetDpiForMonitor");
|
|
||||||
SetProcessDpiAwareness_fn = (decltype(SetProcessDpiAwareness_fn))GetProcAddress(dll, "SetProcessDpiAwareness");
|
|
||||||
}
|
|
||||||
|
|
||||||
//Returns the last Win32 error, in string format. Returns an empty string if there is no error.
|
|
||||||
std::string GetLastErrorAsString()
|
|
||||||
{
|
|
||||||
//Get the error message, if any.
|
|
||||||
DWORD errorMessageID = ::GetLastError();
|
|
||||||
if (errorMessageID == 0)
|
|
||||||
return std::string(); //No error message has been recorded
|
|
||||||
|
|
||||||
LPSTR messageBuffer = nullptr;
|
|
||||||
size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
||||||
NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL);
|
|
||||||
|
|
||||||
std::string message(messageBuffer, size);
|
|
||||||
|
|
||||||
//Free the buffer.
|
|
||||||
LocalFree(messageBuffer);
|
|
||||||
|
|
||||||
return message;
|
|
||||||
}
|
|
||||||
|
|
||||||
void destroy_window()
|
void destroy_window()
|
||||||
{
|
{
|
||||||
auto& state = retained_state();
|
auto& state = retained_state();
|
||||||
@@ -531,36 +475,6 @@ void win32_save_window_state()
|
|||||||
p.rcNormalPosition.right,
|
p.rcNormalPosition.right,
|
||||||
p.rcNormalPosition.bottom });
|
p.rcNormalPosition.bottom });
|
||||||
}
|
}
|
||||||
BOOL UnadjustWindowRectEx(LPRECT prc, DWORD dwStyle, BOOL fMenu, DWORD dwExStyle)
|
|
||||||
{
|
|
||||||
RECT rc;
|
|
||||||
SetRectEmpty(&rc);
|
|
||||||
BOOL fRc = AdjustWindowRectEx(&rc, dwStyle, fMenu, dwExStyle);
|
|
||||||
if (fRc) {
|
|
||||||
prc->left -= rc.left;
|
|
||||||
prc->top -= rc.top;
|
|
||||||
prc->right -= rc.right;
|
|
||||||
prc->bottom -= rc.bottom;
|
|
||||||
}
|
|
||||||
return fRc;
|
|
||||||
}
|
|
||||||
|
|
||||||
void _pre_call_callback(const char* name, void* funcptr, int len_args, ...)
|
|
||||||
{
|
|
||||||
assert(App::I->is_render_thread());
|
|
||||||
}
|
|
||||||
|
|
||||||
void _post_call_callback(const char* name, void* funcptr, int len_args, ...)
|
|
||||||
{
|
|
||||||
GLenum error_code;
|
|
||||||
error_code = glad_glGetError();
|
|
||||||
|
|
||||||
if (error_code != pp::renderer::gl::no_error_code())
|
|
||||||
{
|
|
||||||
LOG("ERROR %d in %s\n", error_code, name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
auto& state = retained_state();
|
auto& state = retained_state();
|
||||||
|
|||||||
@@ -395,6 +395,101 @@ pp::panopainter::LegacyCanvasDrawMergeLayerPathExecution make_node_canvas_layer_
|
|||||||
draw_layer_frame);
|
draw_layer_frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void execute_node_canvas_draw_merge_tail(
|
||||||
|
NodeCanvas& node_canvas,
|
||||||
|
const glm::mat4& ortho_proj,
|
||||||
|
const glm::mat4& proj,
|
||||||
|
const glm::mat4& camera,
|
||||||
|
const glm::ivec4& c)
|
||||||
|
{
|
||||||
|
apply_node_canvas_capability(pp::renderer::gl::depth_test_state(), false);
|
||||||
|
|
||||||
|
pp::panopainter::execute_legacy_canvas_draw_merge_post_draw_callbacks(
|
||||||
|
node_canvas.m_canvas->m_smask_active,
|
||||||
|
node_canvas.m_canvas->m_current_mode == kCanvasMode::Copy || node_canvas.m_canvas->m_current_mode == kCanvasMode::Cut,
|
||||||
|
node_canvas.m_canvas->m_smask_mode,
|
||||||
|
node_canvas.m_canvas->m_current_mode != kCanvasMode::Grid,
|
||||||
|
[&] {
|
||||||
|
node_canvas.m_canvas->modes[(int)kCanvasMode::MaskFree][0]->on_Draw(ortho_proj, proj, camera);
|
||||||
|
},
|
||||||
|
[&] {
|
||||||
|
node_canvas.m_canvas->modes[(int)kCanvasMode::MaskLine][0]->on_Draw(ortho_proj, proj, camera);
|
||||||
|
},
|
||||||
|
[&] {
|
||||||
|
pp::panopainter::execute_legacy_canvas_draw_merge_smask_faces(
|
||||||
|
pp::panopainter::LegacyCanvasDrawMergeTextureMaskUniforms {
|
||||||
|
.texture_slot = 0,
|
||||||
|
.pattern_offset = node_canvas.m_outline_pan,
|
||||||
|
},
|
||||||
|
proj,
|
||||||
|
camera,
|
||||||
|
node_canvas.m_canvas->m_layers.size() + 500.f,
|
||||||
|
std::to_array(node_canvas.m_canvas->m_plane_transform),
|
||||||
|
{
|
||||||
|
.set_active_texture_unit = [&] {
|
||||||
|
set_active_texture_unit(0);
|
||||||
|
},
|
||||||
|
.enable_blend = [&] {
|
||||||
|
apply_node_canvas_capability(pp::renderer::gl::blend_state(), true);
|
||||||
|
},
|
||||||
|
.bind_face_texture = [&](int plane_index) {
|
||||||
|
node_canvas.m_canvas->m_smask.rtt(plane_index).bindTexture();
|
||||||
|
},
|
||||||
|
.draw_face = [&] {
|
||||||
|
node_canvas.m_face_plane.draw_fill();
|
||||||
|
},
|
||||||
|
.unbind_face_texture = [&](int plane_index) {
|
||||||
|
node_canvas.m_canvas->m_smask.rtt(plane_index).unbindTexture();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
pp::panopainter::make_legacy_canvas_draw_merge_grid_modes_draw(
|
||||||
|
&Canvas::modes[(int)kCanvasMode::Grid],
|
||||||
|
ortho_proj,
|
||||||
|
proj,
|
||||||
|
camera),
|
||||||
|
pp::panopainter::make_legacy_canvas_draw_merge_heightmap_draw(App::I->grid.get(), proj, camera),
|
||||||
|
pp::panopainter::make_legacy_canvas_draw_merge_current_modes_draw(
|
||||||
|
node_canvas.m_canvas->m_mode,
|
||||||
|
ortho_proj,
|
||||||
|
proj,
|
||||||
|
camera));
|
||||||
|
|
||||||
|
if (node_canvas.m_density != 1.f) {
|
||||||
|
pp::panopainter::execute_legacy_canvas_draw_merge_display_resolve(
|
||||||
|
pp::panopainter::LegacyCanvasDrawMergeDisplayResolveUniforms {
|
||||||
|
.texture = {
|
||||||
|
.mvp = glm::ortho<float>(-1, 1, -1, 1),
|
||||||
|
.texture_slot = 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.unbind_resolve_framebuffer = [&] {
|
||||||
|
node_canvas.m_rtt.unbindFramebuffer();
|
||||||
|
},
|
||||||
|
.clear_color_buffer = [&] {
|
||||||
|
clear_node_canvas_color_buffer({ 1.f, 1.f, 1.f, 0.f });
|
||||||
|
},
|
||||||
|
.apply_viewport = [&] {
|
||||||
|
apply_node_canvas_viewport(c.x + App::I->off_x, c.y + App::I->off_y, c.z, c.w);
|
||||||
|
},
|
||||||
|
.bind_sampler = [&] {
|
||||||
|
node_canvas.m_sampler_nearest.bind(0);
|
||||||
|
},
|
||||||
|
.bind_resolve_texture = [&] {
|
||||||
|
set_active_texture_unit(0);
|
||||||
|
node_canvas.m_rtt.bindTexture();
|
||||||
|
},
|
||||||
|
.draw = [&] {
|
||||||
|
node_canvas.m_face_plane.draw_fill();
|
||||||
|
},
|
||||||
|
.unbind_resolve_texture = [&] {
|
||||||
|
node_canvas.m_rtt.unbindTexture();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Node* NodeCanvas::clone_instantiate() const
|
Node* NodeCanvas::clone_instantiate() const
|
||||||
@@ -700,93 +795,7 @@ void NodeCanvas::draw()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
apply_node_canvas_capability(pp::renderer::gl::depth_test_state(), false);
|
execute_node_canvas_draw_merge_tail(*this, ortho_proj, proj, camera, c);
|
||||||
|
|
||||||
pp::panopainter::execute_legacy_canvas_draw_merge_post_draw_callbacks(
|
|
||||||
m_canvas->m_smask_active,
|
|
||||||
m_canvas->m_current_mode == kCanvasMode::Copy || m_canvas->m_current_mode == kCanvasMode::Cut,
|
|
||||||
m_canvas->m_smask_mode,
|
|
||||||
m_canvas->m_current_mode != kCanvasMode::Grid,
|
|
||||||
[&] {
|
|
||||||
m_canvas->modes[(int)kCanvasMode::MaskFree][0]->on_Draw(ortho_proj, proj, camera);
|
|
||||||
},
|
|
||||||
[&] {
|
|
||||||
m_canvas->modes[(int)kCanvasMode::MaskLine][0]->on_Draw(ortho_proj, proj, camera);
|
|
||||||
},
|
|
||||||
[&] {
|
|
||||||
pp::panopainter::execute_legacy_canvas_draw_merge_smask_faces(
|
|
||||||
pp::panopainter::LegacyCanvasDrawMergeTextureMaskUniforms {
|
|
||||||
.texture_slot = 0,
|
|
||||||
.pattern_offset = m_outline_pan,
|
|
||||||
},
|
|
||||||
proj,
|
|
||||||
camera,
|
|
||||||
m_canvas->m_layers.size() + 500.f,
|
|
||||||
std::to_array(m_canvas->m_plane_transform),
|
|
||||||
{
|
|
||||||
.set_active_texture_unit = [&] {
|
|
||||||
set_active_texture_unit(0);
|
|
||||||
},
|
|
||||||
.enable_blend = [&] {
|
|
||||||
apply_node_canvas_capability(pp::renderer::gl::blend_state(), true);
|
|
||||||
},
|
|
||||||
.bind_face_texture = [&](int plane_index) {
|
|
||||||
m_canvas->m_smask.rtt(plane_index).bindTexture();
|
|
||||||
},
|
|
||||||
.draw_face = [&] {
|
|
||||||
m_face_plane.draw_fill();
|
|
||||||
},
|
|
||||||
.unbind_face_texture = [&](int plane_index) {
|
|
||||||
m_canvas->m_smask.rtt(plane_index).unbindTexture();
|
|
||||||
},
|
|
||||||
});
|
|
||||||
},
|
|
||||||
pp::panopainter::make_legacy_canvas_draw_merge_grid_modes_draw(
|
|
||||||
&Canvas::modes[(int)kCanvasMode::Grid],
|
|
||||||
ortho_proj,
|
|
||||||
proj,
|
|
||||||
camera),
|
|
||||||
pp::panopainter::make_legacy_canvas_draw_merge_heightmap_draw(App::I->grid.get(), proj, camera),
|
|
||||||
pp::panopainter::make_legacy_canvas_draw_merge_current_modes_draw(
|
|
||||||
m_canvas->m_mode,
|
|
||||||
ortho_proj,
|
|
||||||
proj,
|
|
||||||
camera));
|
|
||||||
|
|
||||||
if (m_density != 1.f)
|
|
||||||
{
|
|
||||||
pp::panopainter::execute_legacy_canvas_draw_merge_display_resolve(
|
|
||||||
pp::panopainter::LegacyCanvasDrawMergeDisplayResolveUniforms {
|
|
||||||
.texture = {
|
|
||||||
.mvp = glm::ortho<float>(-1, 1, -1, 1),
|
|
||||||
.texture_slot = 0,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.unbind_resolve_framebuffer = [&] {
|
|
||||||
m_rtt.unbindFramebuffer();
|
|
||||||
},
|
|
||||||
.clear_color_buffer = [&] {
|
|
||||||
clear_node_canvas_color_buffer({ 1.f, 1.f, 1.f, 0.f });
|
|
||||||
},
|
|
||||||
.apply_viewport = [&] {
|
|
||||||
apply_node_canvas_viewport(c.x + App::I->off_x, c.y + App::I->off_y, c.z, c.w);
|
|
||||||
},
|
|
||||||
.bind_sampler = [&] {
|
|
||||||
m_sampler_nearest.bind(0);
|
|
||||||
},
|
|
||||||
.bind_resolve_texture = [&] {
|
|
||||||
set_active_texture_unit(0);
|
|
||||||
m_rtt.bindTexture();
|
|
||||||
},
|
|
||||||
.draw = [&] {
|
|
||||||
m_face_plane.draw_fill();
|
|
||||||
},
|
|
||||||
.unbind_resolve_texture = [&] {
|
|
||||||
m_rtt.unbindTexture();
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
scissor ? apply_node_canvas_capability(pp::renderer::gl::scissor_test_state(), true) : apply_node_canvas_capability(pp::renderer::gl::scissor_test_state(), false);
|
scissor ? apply_node_canvas_capability(pp::renderer::gl::scissor_test_state(), true) : apply_node_canvas_capability(pp::renderer::gl::scissor_test_state(), false);
|
||||||
blend ? apply_node_canvas_capability(pp::renderer::gl::blend_state(), true) : apply_node_canvas_capability(pp::renderer::gl::blend_state(), false);
|
blend ? apply_node_canvas_capability(pp::renderer::gl::blend_state(), true) : apply_node_canvas_capability(pp::renderer::gl::blend_state(), false);
|
||||||
|
|||||||
106
src/platform_windows/windows_bootstrap_helpers.cpp
Normal file
106
src/platform_windows/windows_bootstrap_helpers.cpp
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
#include "app.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "renderer_gl/opengl_capabilities.h"
|
||||||
|
|
||||||
|
#include <shellscalingapi.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#if __has_include(<renderdoc_app.h>)
|
||||||
|
#include <renderdoc_app.h>
|
||||||
|
#define USE_RENDERDOC
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_RENDERDOC
|
||||||
|
RENDERDOC_API_1_4_0* rdoc_api = NULL;
|
||||||
|
|
||||||
|
bool win32_renderdoc_init()
|
||||||
|
{
|
||||||
|
// At init, on windows
|
||||||
|
if (HMODULE mod = GetModuleHandleA("renderdoc.dll"))
|
||||||
|
{
|
||||||
|
pRENDERDOC_GetAPI RENDERDOC_GetAPI =
|
||||||
|
(pRENDERDOC_GetAPI)GetProcAddress(mod, "RENDERDOC_GetAPI");
|
||||||
|
return RENDERDOC_GetAPI(eRENDERDOC_API_Version_1_1_2, (void**)&rdoc_api);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void win32_renderdoc_frame_start()
|
||||||
|
{
|
||||||
|
if (rdoc_api)
|
||||||
|
rdoc_api->StartFrameCapture(NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void win32_renderdoc_frame_end()
|
||||||
|
{
|
||||||
|
if (rdoc_api)
|
||||||
|
rdoc_api->EndFrameCapture(NULL, NULL);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
void win32_renderdoc_frame_start() { }
|
||||||
|
void win32_renderdoc_frame_end() { }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
HRESULT(*GetDpiForMonitor_fn)(HMONITOR hmonitor, MONITOR_DPI_TYPE dpiType, UINT* dpiX, UINT* dpiY);
|
||||||
|
HRESULT(*SetProcessDpiAwareness_fn)(PROCESS_DPI_AWARENESS value);
|
||||||
|
|
||||||
|
void init_shcore_API()
|
||||||
|
{
|
||||||
|
HMODULE dll = LoadLibrary(L"Shcore.dll");
|
||||||
|
if (!dll)
|
||||||
|
{
|
||||||
|
LOG("cannot load Shcore.dll");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LOG("loaded Shcore.dll");
|
||||||
|
GetDpiForMonitor_fn = (decltype(GetDpiForMonitor_fn))GetProcAddress(dll, "GetDpiForMonitor");
|
||||||
|
SetProcessDpiAwareness_fn = (decltype(SetProcessDpiAwareness_fn))GetProcAddress(dll, "SetProcessDpiAwareness");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the last Win32 error, in string format. Returns an empty string if there is no error.
|
||||||
|
std::string GetLastErrorAsString()
|
||||||
|
{
|
||||||
|
DWORD errorMessageID = ::GetLastError();
|
||||||
|
if (errorMessageID == 0)
|
||||||
|
return std::string();
|
||||||
|
|
||||||
|
LPSTR messageBuffer = nullptr;
|
||||||
|
size_t size = FormatMessageA(
|
||||||
|
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||||
|
NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL);
|
||||||
|
|
||||||
|
std::string message(messageBuffer, size);
|
||||||
|
LocalFree(messageBuffer);
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL UnadjustWindowRectEx(LPRECT prc, DWORD dwStyle, BOOL fMenu, DWORD dwExStyle)
|
||||||
|
{
|
||||||
|
RECT rc;
|
||||||
|
SetRectEmpty(&rc);
|
||||||
|
BOOL fRc = AdjustWindowRectEx(&rc, dwStyle, fMenu, dwExStyle);
|
||||||
|
if (fRc) {
|
||||||
|
prc->left -= rc.left;
|
||||||
|
prc->top -= rc.top;
|
||||||
|
prc->right -= rc.right;
|
||||||
|
prc->bottom -= rc.bottom;
|
||||||
|
}
|
||||||
|
return fRc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _pre_call_callback(const char* name, void* funcptr, int len_args, ...)
|
||||||
|
{
|
||||||
|
assert(App::I->is_render_thread());
|
||||||
|
}
|
||||||
|
|
||||||
|
void _post_call_callback(const char* name, void* funcptr, int len_args, ...)
|
||||||
|
{
|
||||||
|
GLenum error_code;
|
||||||
|
error_code = glad_glGetError();
|
||||||
|
|
||||||
|
if (error_code != pp::renderer::gl::no_error_code())
|
||||||
|
{
|
||||||
|
LOG("ERROR %d in %s\n", error_code, name);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user