Extract layout bootstrap and thin NodeCanvas startup shells

This commit is contained in:
2026-06-16 17:57:17 +02:00
parent 0441dc4077
commit 1442c13dd7
10 changed files with 595 additions and 458 deletions

View File

@@ -97,6 +97,7 @@ set(PP_PANOPAINTER_APP_SOURCES
src/app_dialogs_info_openers.cpp src/app_dialogs_info_openers.cpp
src/app_events.cpp src/app_events.cpp
src/app_layout.cpp src/app_layout.cpp
src/app_layout_bootstrap.cpp
src/app_layout_brush.cpp src/app_layout_brush.cpp
src/app_layout_draw_toolbar.cpp src/app_layout_draw_toolbar.cpp
src/app_layout_ui_state.cpp src/app_layout_ui_state.cpp

View File

@@ -80,13 +80,13 @@ What is still carrying too much live ownership:
Current hotspot files: Current hotspot files:
- `src/canvas.cpp`: 2645 lines - `src/canvas.cpp`: 2645 lines
- `src/app_layout.cpp`: 229 lines - `src/app_layout.cpp`: 125 lines
- `src/canvas_modes.cpp`: 1798 lines - `src/canvas_modes.cpp`: 1798 lines
- `src/node.cpp`: 1594 lines - `src/node.cpp`: 1594 lines
- `src/main.cpp`: 390 lines - `src/main.cpp`: 271 lines
- `src/node_panel_brush.cpp`: 1197 lines - `src/node_panel_brush.cpp`: 1197 lines
- `src/node_stroke_preview.cpp`: 890 lines - `src/node_stroke_preview.cpp`: 890 lines
- `src/node_canvas.cpp`: 831 lines - `src/node_canvas.cpp`: 852 lines
- `src/app.cpp`: 502 lines - `src/app.cpp`: 502 lines
- `src/app_dialogs.cpp`: 142 lines - `src/app_dialogs.cpp`: 142 lines
@@ -135,7 +135,14 @@ Current architecture mismatches that must be treated as real blockers:
`execute_legacy_canvas_draw_unmerged_node_canvas_shell(...)`, while the `execute_legacy_canvas_draw_unmerged_node_canvas_shell(...)`, while the
broader unmerged cache/viewport/background/composite pass setup now also broader unmerged cache/viewport/background/composite pass setup now also
routes through routes through
`execute_legacy_canvas_draw_unmerged_node_canvas_pass(...)`. `execute_legacy_canvas_draw_unmerged_node_canvas_pass(...)`, while
`NodeCanvas::draw()` setup, merged-pass shell, and unmerged-pass shell now
also route through `prepare_legacy_node_canvas_draw_setup(...)`,
`execute_legacy_canvas_draw_node_canvas_shell(...)`,
`execute_legacy_canvas_draw_merged_pass(...)`, and
`execute_legacy_canvas_draw_node_canvas_unmerged_pass(...)`, which
materially shortens the live `NodeCanvas::draw()` body even though the file
itself is still large.
- `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
@@ -154,8 +161,9 @@ Current architecture mismatches that must be treated as real blockers:
persisted floating/docked panel-state ownership now also live in persisted floating/docked panel-state ownership now also live in
`src/app_layout_ui_state.cpp`, while draw-toolbar binding now also lives in `src/app_layout_ui_state.cpp`, while draw-toolbar binding now also lives in
`src/app_layout_draw_toolbar.cpp`, while brush-refresh now also lives in `src/app_layout_draw_toolbar.cpp`, while brush-refresh now also lives in
`src/app_layout_brush.cpp`, and `src/app_layout.cpp` is now mostly `src/app_layout_brush.cpp`, while layout bootstrap plus reload/load
layout/bootstrap composition, while the continuation wiring now also lives in `src/app_layout_bootstrap.cpp`, and
`src/app_layout.cpp` is now mostly thin call-through entrypoints, while the
informational overlay opener family now also lives in informational overlay opener family now also lives in
`src/app_dialogs_info_openers.cpp` and the corresponding `App::dialog_*` `src/app_dialogs_info_openers.cpp` and the corresponding `App::dialog_*`
entrypoints are thinner, while the export/video/PPBR dialog family now also entrypoints are thinner, while the export/video/PPBR dialog family now also
@@ -193,8 +201,9 @@ Current architecture mismatches that must be treated as real blockers:
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, `src/main.cpp`, while RenderDoc startup/frame capture, SHCore DPI bootstrap,
Win32 error-string conversion, and the GL debug pre/post callbacks now also Win32 error-string conversion, the GL debug pre/post callbacks, and the WMI
live in `src/platform_windows/windows_bootstrap_helpers.cpp` instead of startup probe now also live in
`src/platform_windows/windows_bootstrap_helpers.cpp` instead of
`src/main.cpp`, while Win32 lifecycle running-state, close/shutdown `src/main.cpp`, while Win32 lifecycle running-state, close/shutdown
sequencing, FPS title update/wakeup posting, stylus frame update, window sequencing, FPS title update/wakeup posting, stylus frame update, window
preference save, and VR lifecycle wrappers now also live in preference save, and VR lifecycle wrappers now also live in

View File

@@ -235,6 +235,13 @@ Current slice:
`execute_legacy_canvas_draw_unmerged_node_canvas_pass(...)`, which removes `execute_legacy_canvas_draw_unmerged_node_canvas_pass(...)`, which removes
another coherent outer-shell block even though the broader node draw loop another coherent outer-shell block even though the broader node draw loop
still lives in `src/node_canvas.cpp`. still lives in `src/node_canvas.cpp`.
- `NodeCanvas::draw()` setup, merged-pass shell, and unmerged-pass shell now
also route through `prepare_legacy_node_canvas_draw_setup(...)`,
`execute_legacy_canvas_draw_node_canvas_shell(...)`,
`execute_legacy_canvas_draw_merged_pass(...)`, and
`execute_legacy_canvas_draw_node_canvas_unmerged_pass(...)`, which
materially shortens the live `NodeCanvas::draw()` body even though the file
itself is still large.
Write scope: Write scope:
- `src/node_stroke_preview.cpp` - `src/node_stroke_preview.cpp`
@@ -313,7 +320,7 @@ targets look like helpers under one old monolith.
Status: In Progress Status: In Progress
Why now: Why now:
`src/app_layout.cpp` is still a 229-line mixed file that builds menus, `src/app_layout.cpp` is still a 125-line mixed file that builds menus,
attaches callbacks, computes planner inputs, and mutates UI state directly. attaches callbacks, computes planner inputs, and mutates UI state directly.
Current slice: Current slice:
@@ -348,6 +355,9 @@ Current slice:
layout/bootstrap composition. layout/bootstrap composition.
- Brush-refresh now also lives in `src/app_layout_brush.cpp`, and - Brush-refresh now also lives in `src/app_layout_brush.cpp`, and
`src/app_layout.cpp` is down to the remaining layout/bootstrap composition. `src/app_layout.cpp` is down to the remaining layout/bootstrap composition.
- Layout bootstrap plus reload/load continuation wiring now also lives in
`src/app_layout_bootstrap.cpp`, and `src/app_layout.cpp` is down to thin
call-through entrypoints plus the remaining local helper pocket.
Write scope: Write scope:
- `src/app_layout.cpp` - `src/app_layout.cpp`
@@ -505,6 +515,9 @@ Current slice:
conversion, `UnadjustWindowRectEx`, and GL debug pre/post callbacks now also conversion, `UnadjustWindowRectEx`, and GL debug pre/post callbacks now also
live in `src/platform_windows/windows_bootstrap_helpers.cpp` instead of live in `src/platform_windows/windows_bootstrap_helpers.cpp` instead of
`src/main.cpp` `src/main.cpp`
- the WMI startup probe now also lives in
`src/platform_windows/windows_bootstrap_helpers.cpp` instead of
`src/main.cpp`
- Win32 lifecycle running-state, close/shutdown handling, FPS title update and - Win32 lifecycle running-state, close/shutdown handling, FPS title update and
wakeup posting, stylus frame update, window preference save, and VR wakeup posting, stylus frame update, window preference save, and VR
lifecycle wrappers now also live in lifecycle wrappers now also live in

View File

@@ -1,11 +1,6 @@
#include "pch.h" #include "pch.h"
#include "app.h" #include "app.h"
#include "node_panel_grid.h"
#include "node_icon.h"
#include "node_dialog_open.h"
#include "node_text.h" #include "node_text.h"
#include "node_progress_bar.h"
#include "node_dialog_picker.h"
#include "node_panel_floating.h" #include "node_panel_floating.h"
#include "app_core/about_menu.h" #include "app_core/about_menu.h"
#include "app_core/app_preferences.h" #include "app_core/app_preferences.h"
@@ -18,10 +13,6 @@
#include "legacy_document_layer_services.h" #include "legacy_document_layer_services.h"
#include "legacy_preference_storage.h" #include "legacy_preference_storage.h"
#include "font.h" #include "font.h"
#include "node_remote_page.h"
#include "node_shorcuts.h"
#include <vector>
namespace pp::panopainter { namespace pp::panopainter {
void bind_legacy_main_toolbar(App& app); void bind_legacy_main_toolbar(App& app);
@@ -30,6 +21,7 @@ void bind_legacy_edit_menu(App& app);
void bind_legacy_about_menu(App& app); void bind_legacy_about_menu(App& app);
void bind_legacy_layer_menu(App& app); void bind_legacy_layer_menu(App& app);
void bind_legacy_tools_menu(App& app); void bind_legacy_tools_menu(App& app);
void init_layout_bootstrap(App& app);
} }
namespace { namespace {
@@ -120,137 +112,7 @@ void App::init_menu_layer()
void App::initLayout() void App::initLayout()
{ {
LOG("initializing layout statics"); pp::panopainter::init_layout_bootstrap(*this);
NodeBorder::static_init();
NodeImage::static_init();
NodeIcon::static_init();
NodeStrokePreview::static_init();
static std::vector<std::shared_ptr<Layer>> saved_layers;
layout.on_reloading = [&] {
saved_layers = std::move(Canvas::I->m_layers);
ui_save();
NodeStrokePreview::empty_queue();
};
layout.on_loaded = [&] (bool reloaded) {
LOG("initializing layout updating after load %d x %d zoom %f", (int)width, (int)height, zoom);
layout[main_id]->update(width, height, zoom);
LOG("initializing layout components");
init_sidebar();
if (reloaded)
{
for (const auto& l : saved_layers)
layers->add_layer(l->m_name.c_str(), false, true, l);
}
else
{
layers->add_layer("Default", false, true);
Canvas::I->m_unsaved = false;
}
init_toolbar_draw();
init_toolbar_main();
init_menu_file();
init_menu_edit();
init_menu_layer();
init_menu_tools();
init_menu_about();
// set version string
if (auto* version_label = layout[main_id]->find<NodeText>("version"))
{
version_label->set_text(g_version);
}
const auto renderer_features = ShaderManager::render_device_features();
const auto renderer_diagnostics = pp::app::plan_renderer_diagnostics({
.framebuffer_fetch = renderer_features.framebuffer_fetch,
.float32_render_targets = renderer_features.float32_render_targets,
.float32_linear_filtering = renderer_features.float32_linear_filtering,
.float16_render_targets = renderer_features.float16_render_targets,
});
if (auto x = layout[main_id]->find<NodeBorder>("ext-fbf"))
{
x->m_color = renderer_diagnostics.framebuffer_fetch.supported ?
glm::vec4(0, 1, 0, 1) :
glm::vec4(1, 0, 0, 1);
}
if (auto x = layout[main_id]->find<NodeBorder>("ext-flt"))
{
if (renderer_diagnostics.floating_point_targets.supported)
{
if (auto t = x->find<NodeText>("ext-flt-text"))
{
t->set_text(std::string(renderer_diagnostics.floating_point_targets.label));
}
x->m_color = glm::vec4(0, 1, 0, 1);
}
else
{
x->m_color = glm::vec4(1, 0, 0, 1);
}
}
dialog_whatsnew(false);
brush_update(true, true);
// hacky thing to make the toolbar buttons not steal events when moving cursor fast
if (auto* toolbar = layout[main_id]->find<Node>("toolbar"))
toolbar->m_flood_events = true;
NodeImage* n = new NodeImage;
n->m_path = "data/ui/p-black.png";
n->m_tex_id = const_hash("data/ui/p-black.png");
n->SetSize(30, 45);
n->create();
NodeButtonCustom* butt = new NodeButtonCustom;
butt->create();
butt->add_child(n);
butt->SetPositioning(YGPositionTypeAbsolute);
butt->set_color({ 0, 0, 0, 0 });
//n->SetPosition(100, 100);
YGNodeStyleSetPosition(butt->y_node, YGEdgeBottom, 8);
YGNodeStyleSetPosition(butt->y_node, YGEdgeLeft, 10);
//butt->SetSize(30, 45);
layout[main_id]->add_child(butt);
butt->on_click = [this](Node*){
toggle_ui();
};
ui_restore();
redraw = true;
};
LOG("initializing layout xml");
if (layout.m_loaded)
{
LOG("restore layout");
layout.restore_context();
}
else
layout.load("data/layout.xml");
LOG("initializing layout completed");
LOG("initializing layout designer xml");
layout_designer.on_loaded = [&](bool reloaded) {
layout_designer.create();
//layout_designer[main_id]->add_child(layout_designer.instantiate("shortcuts"));
auto p = layout_designer[main_id]->add_child<NodeShortcuts>();
//p->SetPosition(300, 300);
//p->SetSize(600, 400);
//p->m_container->add_child<NodePanelAnimation>();
};
//layout_designer.load("data/dialogs/shortcuts.xml");
} }
void App::set_ui_scale(float scale) void App::set_ui_scale(float scale)

View File

@@ -0,0 +1,148 @@
#include "pch.h"
#include "app.h"
#include "node_border.h"
#include "node_button_custom.h"
#include "node_icon.h"
#include "node_image.h"
#include "node_shorcuts.h"
#include "node_stroke_preview.h"
#include "node_text.h"
#include "app_core/app_status.h"
#include <vector>
namespace {
std::vector<std::shared_ptr<Layer>> saved_layers;
void capture_layout_reload_state(App& app)
{
saved_layers = std::move(Canvas::I->m_layers);
app.ui_save();
NodeStrokePreview::empty_queue();
}
void apply_layout_loaded_state(App& app, bool reloaded)
{
LOG("initializing layout updating after load %d x %d zoom %f", (int)app.width, (int)app.height, app.zoom);
app.layout[app.main_id]->update(app.width, app.height, app.zoom);
LOG("initializing layout components");
app.init_sidebar();
if (reloaded) {
for (const auto& layer : saved_layers)
app.layers->add_layer(layer->m_name.c_str(), false, true, layer);
} else {
app.layers->add_layer("Default", false, true);
Canvas::I->m_unsaved = false;
}
app.init_toolbar_draw();
app.init_toolbar_main();
app.init_menu_file();
app.init_menu_edit();
app.init_menu_layer();
app.init_menu_tools();
app.init_menu_about();
if (auto* version_label = app.layout[app.main_id]->find<NodeText>("version")) {
version_label->set_text(g_version);
}
const auto renderer_features = ShaderManager::render_device_features();
const auto renderer_diagnostics = pp::app::plan_renderer_diagnostics({
.framebuffer_fetch = renderer_features.framebuffer_fetch,
.float32_render_targets = renderer_features.float32_render_targets,
.float32_linear_filtering = renderer_features.float32_linear_filtering,
.float16_render_targets = renderer_features.float16_render_targets,
});
if (auto* indicator = app.layout[app.main_id]->find<NodeBorder>("ext-fbf")) {
indicator->m_color = renderer_diagnostics.framebuffer_fetch.supported
? glm::vec4(0, 1, 0, 1)
: glm::vec4(1, 0, 0, 1);
}
if (auto* indicator = app.layout[app.main_id]->find<NodeBorder>("ext-flt")) {
if (renderer_diagnostics.floating_point_targets.supported) {
if (auto* text = indicator->find<NodeText>("ext-flt-text"))
text->set_text(std::string(renderer_diagnostics.floating_point_targets.label));
indicator->m_color = glm::vec4(0, 1, 0, 1);
} else {
indicator->m_color = glm::vec4(1, 0, 0, 1);
}
}
app.dialog_whatsnew(false);
app.brush_update(true, true);
if (auto* toolbar = app.layout[app.main_id]->find<Node>("toolbar"))
toolbar->m_flood_events = true;
auto* toggle_button = new NodeImage;
toggle_button->m_path = "data/ui/p-black.png";
toggle_button->m_tex_id = const_hash("data/ui/p-black.png");
toggle_button->SetSize(30, 45);
toggle_button->create();
auto* button = new NodeButtonCustom;
button->create();
button->add_child(toggle_button);
button->SetPositioning(YGPositionTypeAbsolute);
button->set_color({ 0, 0, 0, 0 });
YGNodeStyleSetPosition(button->y_node, YGEdgeBottom, 8);
YGNodeStyleSetPosition(button->y_node, YGEdgeLeft, 10);
app.layout[app.main_id]->add_child(button);
button->on_click = [&app](Node*) {
app.toggle_ui();
};
app.ui_restore();
app.redraw = true;
}
void init_layout_designer(App& app)
{
app.layout_designer.on_loaded = [&app](bool) {
app.layout_designer.create();
auto* shortcuts = app.layout_designer[app.main_id]->add_child<NodeShortcuts>();
(void)shortcuts;
};
}
} // namespace
namespace pp::panopainter {
void init_layout_bootstrap(App& app)
{
LOG("initializing layout statics");
NodeBorder::static_init();
NodeImage::static_init();
NodeIcon::static_init();
NodeStrokePreview::static_init();
app.layout.on_reloading = [&app] {
capture_layout_reload_state(app);
};
app.layout.on_loaded = [&app](bool reloaded) {
apply_layout_loaded_state(app, reloaded);
};
LOG("initializing layout xml");
if (app.layout.m_loaded) {
LOG("restore layout");
app.layout.restore_context();
} else {
app.layout.load("data/layout.xml");
}
LOG("initializing layout completed");
LOG("initializing layout designer xml");
init_layout_designer(app);
}
} // namespace pp::panopainter

View File

@@ -1112,6 +1112,99 @@ inline void execute_legacy_canvas_draw_unmerged_node_canvas_shell(
} }
} }
template <
typename PrepareDensityRenderTarget,
typename PrepareStandardRenderTarget,
typename DrawMergedPass,
typename DrawUnmergedPass>
inline void execute_legacy_canvas_draw_node_canvas_shell(
bool use_density_render_target,
bool draw_merged,
PrepareDensityRenderTarget&& prepare_density_render_target,
PrepareStandardRenderTarget&& prepare_standard_render_target,
DrawMergedPass&& draw_merged_pass,
DrawUnmergedPass&& draw_unmerged_pass)
{
if (use_density_render_target) {
prepare_density_render_target();
} else {
prepare_standard_render_target();
}
if (draw_merged) {
draw_merged_pass();
return;
}
draw_unmerged_pass();
}
template <typename NodeCanvasT>
inline void prepare_legacy_node_canvas_draw_setup(
NodeCanvasT& node_canvas,
const glm::vec4& box,
const glm::ivec4& c,
const glm::mat4& proj,
const glm::mat4& camera)
{
node_canvas.m_canvas->m_mv = camera;
node_canvas.m_canvas->m_proj = proj;
node_canvas.m_canvas->m_box = box;
node_canvas.m_canvas->m_vp = c;
for (int plane_index = 0; plane_index < 6; plane_index++) {
node_canvas.m_canvas->m_plane_unproject[plane_index] =
glm::inverse(node_canvas.m_canvas->m_proj * node_canvas.m_canvas->m_mv * node_canvas.m_canvas->m_plane_transform[plane_index]);
node_canvas.m_canvas->m_plane_dir[plane_index] =
-(node_canvas.m_canvas->m_plane_transform[plane_index] * glm::vec4(node_canvas.m_canvas->m_plane_origin[plane_index], 1));
node_canvas.m_canvas->m_plane_shape[plane_index] =
node_canvas.m_canvas->face_to_shape2D(plane_index);
}
}
template <
typename NodeCanvasT,
typename ApplyCapability,
typename SetActiveTextureUnit,
typename DrawFacePlane>
inline void execute_legacy_canvas_draw_merged_pass(
NodeCanvasT& node_canvas,
const glm::mat4& proj,
const glm::mat4& camera,
ApplyCapability&& apply_node_canvas_capability,
SetActiveTextureUnit&& set_active_texture_unit,
DrawFacePlane&& draw_face_plane)
{
execute_legacy_canvas_draw_merge_background_setup(
{
.draw_merged = true,
},
{
.disable_blend = [&] {
apply_node_canvas_capability(pp::renderer::gl::blend_state(), false);
},
.draw_checkerboard_plane = make_legacy_canvas_draw_merge_background_checkerboard_plane(
proj,
camera,
node_canvas.m_canvas->m_layers.size() + 500.f,
node_canvas.m_canvas->m_plane_transform,
std::forward<DrawFacePlane>(draw_face_plane)),
});
const auto draw_merged_texture_plane = make_legacy_canvas_draw_merge_layer_texture_draw(
&node_canvas.m_canvas->m_layers_merge,
&node_canvas.m_sampler,
&node_canvas.m_face_plane,
std::forward<SetActiveTextureUnit>(set_active_texture_unit),
proj,
camera,
node_canvas.m_canvas->m_plane_transform);
for (int plane_index = 0; plane_index < 6; plane_index++) {
draw_merged_texture_plane(plane_index);
}
}
template < template <
typename NodeCanvasT, typename NodeCanvasT,
typename ApplyViewport, typename ApplyViewport,
@@ -1219,6 +1312,63 @@ inline void execute_legacy_canvas_draw_unmerged_node_canvas_pass(
}); });
} }
template <
typename NodeCanvasT,
typename ApplyViewport,
typename ApplyCapability,
typename SetSampler,
typename MakeLayerPathExecution,
typename LogOnionRangeFailure>
inline void execute_legacy_canvas_draw_node_canvas_unmerged_pass(
NodeCanvasT& node_canvas,
bool use_blend,
bool copy_blend_destination,
const glm::mat4& proj,
const glm::mat4& camera,
const glm::mat4& layer_orientation,
const glm::ivec4& c,
ApplyViewport&& apply_node_canvas_viewport,
ApplyCapability&& apply_node_canvas_capability,
SetSampler&& set_sampler,
MakeLayerPathExecution&& make_layer_path_execution,
LogOnionRangeFailure&& log_onion_range_failure)
{
const auto& brush = node_canvas.m_canvas->m_current_stroke->m_brush;
execute_legacy_canvas_draw_unmerged_node_canvas_pass(
node_canvas,
use_blend,
proj,
camera,
layer_orientation,
c,
std::forward<ApplyViewport>(apply_node_canvas_viewport),
std::forward<ApplyCapability>(apply_node_canvas_capability),
[&] {
node_canvas.m_face_plane.draw_fill();
},
std::forward<SetSampler>(set_sampler),
[&](size_t layer_index, int plane_index, const glm::mat4& plane_mvp_z) {
return make_layer_path_execution(
layer_index,
plane_index,
plane_mvp_z,
brush.get(),
copy_blend_destination,
node_canvas.m_canvas->m_cam_fov < 20.f);
},
[&] {
return make_legacy_canvas_draw_merge_cache_to_screen_checkerboard_plane(
proj,
camera,
node_canvas.m_canvas->m_layers.size() + 500.f,
node_canvas.m_canvas->m_plane_transform,
[&] {
node_canvas.m_face_plane.draw_fill();
});
},
std::forward<LogOnionRangeFailure>(log_onion_range_failure));
}
inline void execute_legacy_canvas_draw_merge_plane_setup( inline void execute_legacy_canvas_draw_merge_plane_setup(
const LegacyCanvasDrawMergePlaneSetupUniforms& uniforms, const LegacyCanvasDrawMergePlaneSetupUniforms& uniforms,
const LegacyCanvasDrawMergePlaneSetupExecution& execution) const LegacyCanvasDrawMergePlaneSetupExecution& execution)

View File

@@ -16,7 +16,6 @@
#include "platform_windows/windows_vr_shell.h" #include "platform_windows/windows_vr_shell.h"
#include "../resource.h" #include "../resource.h"
#include <WbemCli.h>
#include "wacom.h" #include "wacom.h"
#include "abr.h" #include "abr.h"
@@ -75,198 +74,6 @@ void win32_update_fps(int frames)
})); }));
} }
int read_WMI_info()
{
// see: http://win32easy.blogspot.co.uk/2011/03/wmi-in-c-query-everyting-from-your-os.html
HRESULT hRes = CoInitializeEx(NULL, COINIT_MULTITHREADED);
if (FAILED(hRes))
{
LOG("Unable to launch COM: %x", hRes);
return 1;
}
if ((FAILED(hRes = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_CONNECT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, 0))))
{
LOG("Unable to initialize security: %x", hRes);
return 1;
}
IWbemLocator* pLocator = NULL;
if (FAILED(hRes = CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_ALL, IID_PPV_ARGS(&pLocator))))
{
LOG("Unable to create a WbemLocator: %x", hRes);
return 1;
}
IWbemServices* pService = NULL;
if (FAILED(hRes = pLocator->ConnectServer(BSTR(L"root\\CIMV2"), NULL, NULL, NULL, WBEM_FLAG_CONNECT_USE_MAX_WAIT, NULL, NULL, &pService)))
{
pLocator->Release();
LOG("Unable to connect to \"CIMV2\": %x", hRes);
return 1;
}
auto log_field = [](const wchar_t* section, IWbemClassObject* clsObj, const wchar_t* field) {
VARIANT vRet;
CIMTYPE pType;
VariantInit(&vRet);
if (SUCCEEDED(clsObj->Get(field, 0, &vRet, &pType, NULL)))
{
if (pType == CIM_STRING && pType != CIM_EMPTY && pType != CIM_ILLEGAL)
{
LOGW(L"%s %s: %s", section, field, vRet.bstrVal);
}
else if (pType == CIM_UINT32 && pType != CIM_EMPTY && pType != CIM_ILLEGAL)
{
LOGW(L"%s %s: %d", section, field, vRet.uintVal);
}
VariantClear(&vRet);
}
};
auto get_int = [](IWbemClassObject* clsObj, const wchar_t* field) {
VARIANT vRet;
CIMTYPE pType;
VariantInit(&vRet);
int ret = 0;
if (SUCCEEDED(clsObj->Get(field, 0, &vRet, &pType, NULL)))
{
if (pType == CIM_UINT32 && pType != CIM_EMPTY && pType != CIM_ILLEGAL)
ret = vRet.uintVal;
VariantClear(&vRet);
}
return ret;
};
// GET DEVICE INFO
{
IEnumWbemClassObject* pEnumerator = NULL;
if (FAILED(hRes = pService->ExecQuery(BSTR(L"WQL"), BSTR(L"SELECT * FROM Win32_ComputerSystem"), WBEM_FLAG_FORWARD_ONLY, NULL, &pEnumerator)))
{
pLocator->Release();
pService->Release();
LOG("Unable to retrive desktop monitors: %x", hRes);
return 1;
}
IWbemClassObject* clsObj = NULL;
int numElems;
while ((hRes = pEnumerator->Next(WBEM_INFINITE, 1, &clsObj, (ULONG*)&numElems)) != WBEM_S_FALSE)
{
if (FAILED(hRes))
break;
log_field(L"Machine", clsObj, L"Name");
log_field(L"Machine", clsObj, L"Model");
log_field(L"Machine", clsObj, L"Manufacturer");
clsObj->Release();
}
pEnumerator->Release();
}
// GET OS INFO
{
IEnumWbemClassObject* pEnumerator = NULL;
if (FAILED(hRes = pService->ExecQuery(BSTR(L"WQL"), BSTR(L"SELECT * FROM Win32_OperatingSystem"), WBEM_FLAG_FORWARD_ONLY, NULL, &pEnumerator)))
{
pLocator->Release();
pService->Release();
LOG("Unable to retrive desktop monitors: %x", hRes);
return 1;
}
IWbemClassObject* clsObj = NULL;
int numElems;
while ((hRes = pEnumerator->Next(WBEM_INFINITE, 1, &clsObj, (ULONG*)&numElems)) != WBEM_S_FALSE)
{
if (FAILED(hRes))
break;
log_field(L"OS", clsObj, L"Name");
log_field(L"OS", clsObj, L"Version");
log_field(L"OS", clsObj, L"Locale");
log_field(L"OS", clsObj, L"OSProductSuite");
log_field(L"OS", clsObj, L"Manufacturer");
log_field(L"OS", clsObj, L"Description");
clsObj->Release();
}
pEnumerator->Release();
}
pService->Release();
pService = NULL;
if (FAILED(hRes = pLocator->ConnectServer(BSTR(L"root\\Microsoft\\Windows\\DeviceGuard"), NULL, NULL, NULL, WBEM_FLAG_CONNECT_USE_MAX_WAIT, NULL, NULL, &pService)))
{
pLocator->Release();
LOG("Unable to connect to \"DeviceGuard\": %x", hRes);
return 1;
}
// GET DEVICE GUARD
{
IEnumWbemClassObject* pEnumerator = NULL;
if (FAILED(hRes = pService->ExecQuery(BSTR(L"WQL"), BSTR(L"SELECT * FROM Win32_DeviceGuard"), WBEM_FLAG_FORWARD_ONLY, NULL, &pEnumerator)))
{
pLocator->Release();
pService->Release();
LOG("Unable to retrive desktop monitors: %x", hRes);
return 1;
}
IWbemClassObject* clsObj = NULL;
int numElems;
while ((hRes = pEnumerator->Next(WBEM_INFINITE, 1, &clsObj, (ULONG*)&numElems)) != WBEM_S_FALSE)
{
if (FAILED(hRes))
break;
if (get_int(clsObj, L"CodeIntegrityPolicyEnforcementStatus") > 0)
{
LOG("SANDBOX DETECTED");
retained_state().sandboxed = true;
}
SAFEARRAY *psaNames = NULL;
if (SUCCEEDED(clsObj->GetNames(0, WBEM_FLAG_ALWAYS | WBEM_FLAG_NONSYSTEM_ONLY, 0, &psaNames)))
{
// Get the number of properties.
long lLower, lUpper;
BSTR PropName = NULL;
SafeArrayGetLBound(psaNames, 1, &lLower);
SafeArrayGetUBound(psaNames, 1, &lUpper);
for (long i = lLower; i <= lUpper; i++)
{
// Get this property.
SafeArrayGetElement(psaNames, &i, &PropName);
LOGW(L"Prop: %s", PropName);
log_field(L"DeviceGuard", clsObj, PropName);
SysFreeString(PropName);
}
SafeArrayDestroy(psaNames);
}
clsObj->Release();
}
pEnumerator->Release();
}
pLocator->Release();
CoUninitialize();
return 0;
}
// create a reverse map from kKey to VK_XXX // create a reverse map from kKey to VK_XXX
void init_vk_map() void init_vk_map()
{ {
@@ -329,7 +136,7 @@ int main(int argc, char** argv)
pp::platform::windows::setup_exception_handler(); pp::platform::windows::setup_exception_handler();
read_WMI_info(); pp::platform::windows::read_WMI_info();
App::I->create(); App::I->create();

View File

@@ -582,11 +582,6 @@ void NodeCanvas::draw()
glm::mat4 proj = glm::perspective(glm::radians(m_canvas->m_cam_fov), box.z / box.w, 0.001f, 1000.f); glm::mat4 proj = glm::perspective(glm::radians(m_canvas->m_cam_fov), box.z / box.w, 0.001f, 1000.f);
glm::mat4 camera = glm::translate(m_canvas->m_cam_pos) * m_canvas->m_cam_rot; glm::mat4 camera = glm::translate(m_canvas->m_cam_pos) * m_canvas->m_cam_rot;
m_canvas->m_mv = camera;
m_canvas->m_proj = proj;
m_canvas->m_box = box;
m_canvas->m_vp = c;
float pitch = 0; float pitch = 0;
if (auto slider = root()->find<NodeSliderH>("pitch-slider")) if (auto slider = root()->find<NodeSliderH>("pitch-slider"))
pitch = (slider->get_value() - 0.5) * glm::half_pi<float>(); pitch = (slider->get_value() - 0.5) * glm::half_pi<float>();
@@ -597,69 +592,40 @@ void NodeCanvas::draw()
if (auto slider = root()->find<NodeSliderH>("roll-slider")) if (auto slider = root()->find<NodeSliderH>("roll-slider"))
roll = (slider->get_value() - 0.5) * glm::half_pi<float>(); roll = (slider->get_value() - 0.5) * glm::half_pi<float>();
// pre computed helpers pp::panopainter::prepare_legacy_node_canvas_draw_setup(*this, box, c, proj, camera);
for (int plane_index = 0; plane_index < 6; plane_index++)
{
//glm::mat4 plane_camera = glm::lookAt(m_canvas->m_plane_origin[plane_index], m_canvas->m_plane_normal[plane_index], m_canvas->m_plane_tangent[plane_index]);
m_canvas->m_plane_unproject[plane_index] = glm::inverse(m_canvas->m_proj * m_canvas->m_mv * m_canvas->m_plane_transform[plane_index]);
m_canvas->m_plane_dir[plane_index] = -(m_canvas->m_plane_transform[plane_index] * glm::vec4(m_canvas->m_plane_origin[plane_index], 1));
// face is the 2d shape of the cube plane i projected onto the window space
m_canvas->m_plane_shape[plane_index] = m_canvas->face_to_shape2D(plane_index);
}
if (m_density != 1.f)
{
m_rtt.bindFramebuffer();
clear_node_canvas_color_buffer({ 1.f, 1.f, 0.f, 0.f });
apply_node_canvas_viewport(0, 0, m_rtt.getWidth(), m_rtt.getHeight());
}
else
{
clear_node_canvas_color_buffer({ 1.f, 1.f, 1.f, 0.f });
apply_node_canvas_viewport(c.x + App::I->off_x, c.y + App::I->off_y, c.z, c.w);
}
// NOTE: draw_merge has been disabled for worst performance // NOTE: draw_merge has been disabled for worst performance
bool draw_merged = !(m_canvas->m_current_mode == kCanvasMode::Camera); bool draw_merged = !(m_canvas->m_current_mode == kCanvasMode::Camera);
draw_merged = false; draw_merged = false;
if (draw_merged) pp::panopainter::execute_legacy_canvas_draw_node_canvas_shell(
{ m_density != 1.f,
pp::panopainter::execute_legacy_canvas_draw_merge_background_setup( draw_merged,
{ [&] {
.draw_merged = true, m_rtt.bindFramebuffer();
clear_node_canvas_color_buffer({ 1.f, 1.f, 0.f, 0.f });
apply_node_canvas_viewport(0, 0, m_rtt.getWidth(), m_rtt.getHeight());
}, },
{ [&] {
.disable_blend = [&] { clear_node_canvas_color_buffer({ 1.f, 1.f, 1.f, 0.f });
apply_node_canvas_capability(pp::renderer::gl::blend_state(), false); apply_node_canvas_viewport(c.x + App::I->off_x, c.y + App::I->off_y, c.z, c.w);
}, },
.draw_checkerboard_plane = pp::panopainter::make_legacy_canvas_draw_merge_background_checkerboard_plane( [&] {
pp::panopainter::execute_legacy_canvas_draw_merged_pass(
*this,
proj, proj,
camera, camera,
m_canvas->m_layers.size() + 500.f, [&](auto state, bool enabled) {
m_canvas->m_plane_transform, apply_node_canvas_capability(state, enabled);
},
[](int unit) {
set_active_texture_unit(unit);
},
[&] { [&] {
m_face_plane.draw_fill(); m_face_plane.draw_fill();
}),
}); });
},
const auto draw_merged_texture_plane = pp::panopainter::make_legacy_canvas_draw_merge_layer_texture_draw( [&] {
&m_canvas->m_layers_merge,
&m_sampler,
&m_face_plane,
set_active_texture_unit,
proj,
camera,
m_canvas->m_plane_transform);
for (int plane_index = 0; plane_index < 6; plane_index++)
{
draw_merged_texture_plane(plane_index);
}
}
else
{
const auto blend_gate = node_canvas_blend_gate_plan( const auto blend_gate = node_canvas_blend_gate_plan(
m_cache_rtt.getWidth(), m_cache_rtt.getWidth(),
m_cache_rtt.getHeight(), m_cache_rtt.getHeight(),
@@ -669,10 +635,10 @@ void NodeCanvas::draw()
const bool copy_blend_destination = use_blend && !blend_gate.reads_destination_color; const bool copy_blend_destination = use_blend && !blend_gate.reads_destination_color;
const auto layer_orientation = glm::eulerAngleYXZ(yaw, pitch, roll); const auto layer_orientation = glm::eulerAngleYXZ(yaw, pitch, roll);
const auto& b = m_canvas->m_current_stroke->m_brush; pp::panopainter::execute_legacy_canvas_draw_node_canvas_unmerged_pass(
pp::panopainter::execute_legacy_canvas_draw_unmerged_node_canvas_pass(
*this, *this,
use_blend, use_blend,
copy_blend_destination,
proj, proj,
camera, camera,
layer_orientation, layer_orientation,
@@ -683,37 +649,24 @@ void NodeCanvas::draw()
[&](auto state, bool enabled) { [&](auto state, bool enabled) {
apply_node_canvas_capability(state, enabled); apply_node_canvas_capability(state, enabled);
}, },
[&] {
m_face_plane.draw_fill();
},
[&] { [&] {
m_sampler.bind(0); m_sampler.bind(0);
set_active_texture_unit(0); set_active_texture_unit(0);
}, },
[&](size_t layer_index, int plane_index, const glm::mat4& plane_mvp_z) { [&](size_t layer_index, int plane_index, const glm::mat4& plane_mvp_z, const Brush* brush, bool copy_blend_destination, bool use_nearest_sampler) {
return make_node_canvas_layer_path_execution( return make_node_canvas_layer_path_execution(
*this, *this,
layer_index, layer_index,
plane_index, plane_index,
plane_mvp_z, plane_mvp_z,
b.get(), brush,
copy_blend_destination, copy_blend_destination,
m_canvas->m_cam_fov < 20.f); use_nearest_sampler);
},
[&] {
return pp::panopainter::make_legacy_canvas_draw_merge_cache_to_screen_checkerboard_plane(
proj,
camera,
m_canvas->m_layers.size() + 500.f,
m_canvas->m_plane_transform,
[&] {
m_face_plane.draw_fill();
});
}, },
[&](const char* message) { [&](const char* message) {
LOG("NodeCanvas onion frame range failed: %s", message); LOG("NodeCanvas onion frame range failed: %s", message);
}); });
} });
execute_node_canvas_draw_merge_tail(*this, ortho_proj, proj, camera, c); execute_node_canvas_draw_merge_tail(*this, ortho_proj, proj, camera, c);

View File

@@ -13,6 +13,7 @@
#include <cstdlib> #include <cstdlib>
#include <ctime> #include <ctime>
#include <iomanip> #include <iomanip>
#include <WbemCli.h>
#include <sstream> #include <sstream>
#include <shellscalingapi.h> #include <shellscalingapi.h>
#include <string> #include <string>
@@ -162,6 +163,198 @@ void setup_exception_handler()
BT_SetTerminate(); BT_SetTerminate();
} }
int read_WMI_info()
{
// see: http://win32easy.blogspot.co.uk/2011/03/wmi-in-c-query-everyting-from-your-os.html
HRESULT hRes = CoInitializeEx(NULL, COINIT_MULTITHREADED);
if (FAILED(hRes))
{
LOG("Unable to launch COM: %x", hRes);
return 1;
}
if ((FAILED(hRes = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_CONNECT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, 0))))
{
LOG("Unable to initialize security: %x", hRes);
return 1;
}
IWbemLocator* pLocator = NULL;
if (FAILED(hRes = CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_ALL, IID_PPV_ARGS(&pLocator))))
{
LOG("Unable to create a WbemLocator: %x", hRes);
return 1;
}
IWbemServices* pService = NULL;
if (FAILED(hRes = pLocator->ConnectServer(BSTR(L"root\\CIMV2"), NULL, NULL, NULL, WBEM_FLAG_CONNECT_USE_MAX_WAIT, NULL, NULL, &pService)))
{
pLocator->Release();
LOG("Unable to connect to \"CIMV2\": %x", hRes);
return 1;
}
auto log_field = [](const wchar_t* section, IWbemClassObject* clsObj, const wchar_t* field) {
VARIANT vRet;
CIMTYPE pType;
VariantInit(&vRet);
if (SUCCEEDED(clsObj->Get(field, 0, &vRet, &pType, NULL)))
{
if (pType == CIM_STRING && pType != CIM_EMPTY && pType != CIM_ILLEGAL)
{
LOGW(L"%s %s: %s", section, field, vRet.bstrVal);
}
else if (pType == CIM_UINT32 && pType != CIM_EMPTY && pType != CIM_ILLEGAL)
{
LOGW(L"%s %s: %d", section, field, vRet.uintVal);
}
VariantClear(&vRet);
}
};
auto get_int = [](IWbemClassObject* clsObj, const wchar_t* field) {
VARIANT vRet;
CIMTYPE pType;
VariantInit(&vRet);
int ret = 0;
if (SUCCEEDED(clsObj->Get(field, 0, &vRet, &pType, NULL)))
{
if (pType == CIM_UINT32 && pType != CIM_EMPTY && pType != CIM_ILLEGAL)
ret = vRet.uintVal;
VariantClear(&vRet);
}
return ret;
};
// GET DEVICE INFO
{
IEnumWbemClassObject* pEnumerator = NULL;
if (FAILED(hRes = pService->ExecQuery(BSTR(L"WQL"), BSTR(L"SELECT * FROM Win32_ComputerSystem"), WBEM_FLAG_FORWARD_ONLY, NULL, &pEnumerator)))
{
pLocator->Release();
pService->Release();
LOG("Unable to retrive desktop monitors: %x", hRes);
return 1;
}
IWbemClassObject* clsObj = NULL;
int numElems;
while ((hRes = pEnumerator->Next(WBEM_INFINITE, 1, &clsObj, (ULONG*)&numElems)) != WBEM_S_FALSE)
{
if (FAILED(hRes))
break;
log_field(L"Machine", clsObj, L"Name");
log_field(L"Machine", clsObj, L"Model");
log_field(L"Machine", clsObj, L"Manufacturer");
clsObj->Release();
}
pEnumerator->Release();
}
// GET OS INFO
{
IEnumWbemClassObject* pEnumerator = NULL;
if (FAILED(hRes = pService->ExecQuery(BSTR(L"WQL"), BSTR(L"SELECT * FROM Win32_OperatingSystem"), WBEM_FLAG_FORWARD_ONLY, NULL, &pEnumerator)))
{
pLocator->Release();
pService->Release();
LOG("Unable to retrive desktop monitors: %x", hRes);
return 1;
}
IWbemClassObject* clsObj = NULL;
int numElems;
while ((hRes = pEnumerator->Next(WBEM_INFINITE, 1, &clsObj, (ULONG*)&numElems)) != WBEM_S_FALSE)
{
if (FAILED(hRes))
break;
log_field(L"OS", clsObj, L"Name");
log_field(L"OS", clsObj, L"Version");
log_field(L"OS", clsObj, L"Locale");
log_field(L"OS", clsObj, L"OSProductSuite");
log_field(L"OS", clsObj, L"Manufacturer");
log_field(L"OS", clsObj, L"Description");
clsObj->Release();
}
pEnumerator->Release();
}
pService->Release();
pService = NULL;
if (FAILED(hRes = pLocator->ConnectServer(BSTR(L"root\\Microsoft\\Windows\\DeviceGuard"), NULL, NULL, NULL, WBEM_FLAG_CONNECT_USE_MAX_WAIT, NULL, NULL, &pService)))
{
pLocator->Release();
LOG("Unable to connect to \"DeviceGuard\": %x", hRes);
return 1;
}
// GET DEVICE GUARD
{
IEnumWbemClassObject* pEnumerator = NULL;
if (FAILED(hRes = pService->ExecQuery(BSTR(L"WQL"), BSTR(L"SELECT * FROM Win32_DeviceGuard"), WBEM_FLAG_FORWARD_ONLY, NULL, &pEnumerator)))
{
pLocator->Release();
pService->Release();
LOG("Unable to retrive desktop monitors: %x", hRes);
return 1;
}
IWbemClassObject* clsObj = NULL;
int numElems;
while ((hRes = pEnumerator->Next(WBEM_INFINITE, 1, &clsObj, (ULONG*)&numElems)) != WBEM_S_FALSE)
{
if (FAILED(hRes))
break;
if (get_int(clsObj, L"CodeIntegrityPolicyEnforcementStatus") > 0)
{
LOG("SANDBOX DETECTED");
retained_state().sandboxed = true;
}
SAFEARRAY *psaNames = NULL;
if (SUCCEEDED(clsObj->GetNames(0, WBEM_FLAG_ALWAYS | WBEM_FLAG_NONSYSTEM_ONLY, 0, &psaNames)))
{
// Get the number of properties.
long lLower, lUpper;
BSTR PropName = NULL;
SafeArrayGetLBound(psaNames, 1, &lLower);
SafeArrayGetUBound(psaNames, 1, &lUpper);
for (long i = lLower; i <= lUpper; i++)
{
// Get this property.
SafeArrayGetElement(psaNames, &i, &PropName);
LOGW(L"Prop: %s", PropName);
log_field(L"DeviceGuard", clsObj, PropName);
SysFreeString(PropName);
}
SafeArrayDestroy(psaNames);
}
clsObj->Release();
}
pEnumerator->Release();
}
pLocator->Release();
CoUninitialize();
return 0;
}
MainWindowStartupState initialize_main_window_startup_state() MainWindowStartupState initialize_main_window_startup_state()
{ {
auto startup = MainWindowStartupState {}; auto startup = MainWindowStartupState {};

View File

@@ -20,6 +20,7 @@ void init_shcore_API();
std::string GetLastErrorAsString(); std::string GetLastErrorAsString();
void _pre_call_callback(const char* name, void* funcptr, int len_args, ...); void _pre_call_callback(const char* name, void* funcptr, int len_args, ...);
void _post_call_callback(const char* name, void* funcptr, int len_args, ...); void _post_call_callback(const char* name, void* funcptr, int len_args, ...);
int read_WMI_info();
struct MainWindowStartupState struct MainWindowStartupState
{ {