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

@@ -1,11 +1,6 @@
#include "pch.h"
#include "app.h"
#include "node_panel_grid.h"
#include "node_icon.h"
#include "node_dialog_open.h"
#include "node_text.h"
#include "node_progress_bar.h"
#include "node_dialog_picker.h"
#include "node_panel_floating.h"
#include "app_core/about_menu.h"
#include "app_core/app_preferences.h"
@@ -18,10 +13,6 @@
#include "legacy_document_layer_services.h"
#include "legacy_preference_storage.h"
#include "font.h"
#include "node_remote_page.h"
#include "node_shorcuts.h"
#include <vector>
namespace pp::panopainter {
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_layer_menu(App& app);
void bind_legacy_tools_menu(App& app);
void init_layout_bootstrap(App& app);
}
namespace {
@@ -120,137 +112,7 @@ void App::init_menu_layer()
void App::initLayout()
{
LOG("initializing layout statics");
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");
pp::panopainter::init_layout_bootstrap(*this);
}
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 <
typename NodeCanvasT,
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(
const LegacyCanvasDrawMergePlaneSetupUniforms& uniforms,
const LegacyCanvasDrawMergePlaneSetupExecution& execution)

View File

@@ -16,7 +16,6 @@
#include "platform_windows/windows_vr_shell.h"
#include "../resource.h"
#include <WbemCli.h>
#include "wacom.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
void init_vk_map()
{
@@ -329,7 +136,7 @@ int main(int argc, char** argv)
pp::platform::windows::setup_exception_handler();
read_WMI_info();
pp::platform::windows::read_WMI_info();
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 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;
if (auto slider = root()->find<NodeSliderH>("pitch-slider"))
pitch = (slider->get_value() - 0.5) * glm::half_pi<float>();
@@ -597,123 +592,81 @@ void NodeCanvas::draw()
if (auto slider = root()->find<NodeSliderH>("roll-slider"))
roll = (slider->get_value() - 0.5) * glm::half_pi<float>();
// pre computed helpers
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);
}
pp::panopainter::prepare_legacy_node_canvas_draw_setup(*this, box, c, proj, camera);
// NOTE: draw_merge has been disabled for worst performance
bool draw_merged = !(m_canvas->m_current_mode == kCanvasMode::Camera);
draw_merged = false;
if (draw_merged)
{
pp::panopainter::execute_legacy_canvas_draw_merge_background_setup(
{
.draw_merged = true,
},
{
.disable_blend = [&] {
apply_node_canvas_capability(pp::renderer::gl::blend_state(), false);
pp::panopainter::execute_legacy_canvas_draw_node_canvas_shell(
m_density != 1.f,
draw_merged,
[&] {
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());
},
[&] {
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);
},
[&] {
pp::panopainter::execute_legacy_canvas_draw_merged_pass(
*this,
proj,
camera,
[&](auto state, bool enabled) {
apply_node_canvas_capability(state, enabled);
},
.draw_checkerboard_plane = pp::panopainter::make_legacy_canvas_draw_merge_background_checkerboard_plane(
proj,
camera,
m_canvas->m_layers.size() + 500.f,
m_canvas->m_plane_transform,
[&] {
m_face_plane.draw_fill();
}),
});
[](int unit) {
set_active_texture_unit(unit);
},
[&] {
m_face_plane.draw_fill();
});
},
[&] {
const auto blend_gate = node_canvas_blend_gate_plan(
m_cache_rtt.getWidth(),
m_cache_rtt.getHeight(),
m_canvas->m_layers,
m_canvas->m_current_stroke ? m_canvas->m_current_stroke->m_brush.get() : nullptr);
const bool use_blend = blend_gate.shader_blend;
const bool copy_blend_destination = use_blend && !blend_gate.reads_destination_color;
const auto layer_orientation = glm::eulerAngleYXZ(yaw, pitch, roll);
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(
m_cache_rtt.getWidth(),
m_cache_rtt.getHeight(),
m_canvas->m_layers,
m_canvas->m_current_stroke ? m_canvas->m_current_stroke->m_brush.get() : nullptr);
const bool use_blend = blend_gate.shader_blend;
const bool copy_blend_destination = use_blend && !blend_gate.reads_destination_color;
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_unmerged_node_canvas_pass(
*this,
use_blend,
proj,
camera,
layer_orientation,
c,
[&](int x, int y, int width, int height) {
apply_node_canvas_viewport(x, y, width, height);
},
[&](auto state, bool enabled) {
apply_node_canvas_capability(state, enabled);
},
[&] {
m_face_plane.draw_fill();
},
[&] {
m_sampler.bind(0);
set_active_texture_unit(0);
},
[&](size_t layer_index, int plane_index, const glm::mat4& plane_mvp_z) {
return make_node_canvas_layer_path_execution(
*this,
layer_index,
plane_index,
plane_mvp_z,
b.get(),
copy_blend_destination,
m_canvas->m_cam_fov < 20.f);
},
[&] {
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) {
LOG("NodeCanvas onion frame range failed: %s", message);
});
}
pp::panopainter::execute_legacy_canvas_draw_node_canvas_unmerged_pass(
*this,
use_blend,
copy_blend_destination,
proj,
camera,
layer_orientation,
c,
[&](int x, int y, int width, int height) {
apply_node_canvas_viewport(x, y, width, height);
},
[&](auto state, bool enabled) {
apply_node_canvas_capability(state, enabled);
},
[&] {
m_sampler.bind(0);
set_active_texture_unit(0);
},
[&](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(
*this,
layer_index,
plane_index,
plane_mvp_z,
brush,
copy_blend_destination,
use_nearest_sampler);
},
[&](const char* message) {
LOG("NodeCanvas onion frame range failed: %s", message);
});
});
execute_node_canvas_draw_merge_tail(*this, ortho_proj, proj, camera, c);

View File

@@ -13,6 +13,7 @@
#include <cstdlib>
#include <ctime>
#include <iomanip>
#include <WbemCli.h>
#include <sstream>
#include <shellscalingapi.h>
#include <string>
@@ -162,6 +163,198 @@ void setup_exception_handler()
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()
{
auto startup = MainWindowStartupState {};

View File

@@ -20,6 +20,7 @@ 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, ...);
int read_WMI_info();
struct MainWindowStartupState
{