settings file and save/restore ui state
This commit is contained in:
@@ -368,6 +368,7 @@
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\rtt.cpp" />
|
||||
<ClCompile Include="src\serializer.cpp" />
|
||||
<ClCompile Include="src\settings.cpp" />
|
||||
<ClCompile Include="src\shader.cpp" />
|
||||
<ClCompile Include="src\shape.cpp" />
|
||||
<ClCompile Include="src\texture.cpp" />
|
||||
@@ -484,6 +485,7 @@
|
||||
<ClInclude Include="src\pch.h" />
|
||||
<ClInclude Include="src\rtt.h" />
|
||||
<ClInclude Include="src\serializer.h" />
|
||||
<ClInclude Include="src\settings.h" />
|
||||
<ClInclude Include="src\shader.h" />
|
||||
<ClInclude Include="src\shape.h" />
|
||||
<ClInclude Include="src\texture.h" />
|
||||
|
||||
@@ -345,6 +345,9 @@
|
||||
<ClCompile Include="src\node_panel_floating.cpp">
|
||||
<Filter>Source Files\ui</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\settings.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="src\app.h">
|
||||
@@ -572,6 +575,9 @@
|
||||
<ClInclude Include="src\node_panel_floating.h">
|
||||
<Filter>Header Files\ui</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\settings.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="PanoPainter.rc">
|
||||
|
||||
@@ -648,7 +648,7 @@
|
||||
<border height="30" color=".4" align="center" justify="center">
|
||||
<text text="Grids" color="1 1 1 1"/>
|
||||
</border>
|
||||
<border color=".4" pad="5" dir="col" width="100%">
|
||||
<border color=".4" pad="5" dir="col" width="100%" grow="1">
|
||||
|
||||
<node dir="row" margin="0 0 10 0">
|
||||
<node width="200" grow="1" margin="0 5 0 0">
|
||||
|
||||
16
src/app.cpp
16
src/app.cpp
@@ -8,6 +8,7 @@
|
||||
#ifdef __APPLE__
|
||||
#include <Foundation/Foundation.h>
|
||||
#endif
|
||||
#include "settings.h"
|
||||
|
||||
#ifdef __ANDROID__
|
||||
void android_async_lock(struct engine* engine);
|
||||
@@ -264,6 +265,10 @@ void App::initLog()
|
||||
//LogRemote::I.start();
|
||||
LogRemote::I.file_init();
|
||||
LOG("%s", g_version);
|
||||
|
||||
LOG("load preferences");
|
||||
if (!Settings::load())
|
||||
LOG("load preferences failed");
|
||||
}
|
||||
|
||||
int progress_callback_download(void *clientp, curl_off_t dltotal,
|
||||
@@ -439,6 +444,13 @@ void App::init()
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glBlendEquationSeparate(GL_FUNC_ADD, GL_MAX);
|
||||
|
||||
int run_counter = Settings::value<Serializer::Integer>("run_counter") + 1;
|
||||
Settings::set("run_counter", Serializer::Integer(run_counter));
|
||||
LOG("run_counter %d", run_counter);
|
||||
|
||||
if (!Settings::save())
|
||||
LOG("save preferences failed");
|
||||
|
||||
initShaders();
|
||||
initAssets();
|
||||
initLayout();
|
||||
@@ -537,7 +549,7 @@ void App::update(float dt)
|
||||
//glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
//if (!canvas->m_mouse_captured)
|
||||
#if _DEBUG && (_WIN32 || __OSX__)
|
||||
#if /*_DEBUG &&*/ (_WIN32 || __OSX__)
|
||||
reload_timer += dt;
|
||||
if (reload_timer > 1.0)
|
||||
{
|
||||
@@ -678,6 +690,8 @@ void App::update(float dt)
|
||||
void App::terminate()
|
||||
{
|
||||
LOG("App::terminate");
|
||||
ui_save();
|
||||
|
||||
NodeStrokePreview::terminate_renderer();
|
||||
rec_stop();
|
||||
|
||||
|
||||
@@ -206,5 +206,8 @@ public:
|
||||
std::string res_to_string(int res);
|
||||
void crash_test();
|
||||
|
||||
void ui_save();
|
||||
void ui_restore();
|
||||
|
||||
void cmd_convert(std::string pano_path, std::string out_path);
|
||||
};
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "node_progress_bar.h"
|
||||
#include "node_dialog_picker.h"
|
||||
#include "node_panel_floating.h"
|
||||
#include "settings.h"
|
||||
|
||||
void App::title_update()
|
||||
{
|
||||
@@ -511,7 +512,7 @@ void App::init_menu_file()
|
||||
};
|
||||
if (auto b = popup->find<NodeButtonCustom>("file-import"))
|
||||
b->on_click = [this, popup](Node*) {
|
||||
App::I.pick_file({ "JPG", "PNG", "ABR" }, [this](std::string path){
|
||||
pick_file({ "JPG", "PNG", "ABR" }, [this](std::string path){
|
||||
std::string name, base, ext;
|
||||
std::regex r(R"((.*)[\\/]([^\\/]+)\.(\w+)$)");
|
||||
std::smatch m;
|
||||
@@ -551,8 +552,8 @@ void App::init_menu_file()
|
||||
if (auto b = popup->find<NodeButtonCustom>("file-open"))
|
||||
b->on_click = [this, popup](Node*) {
|
||||
//dialog_open();
|
||||
App::I.pick_file({"ppi","PPI"}, [this](std::string path){
|
||||
App::I.open_document(path);
|
||||
pick_file({"ppi","PPI"}, [this](std::string path){
|
||||
open_document(path);
|
||||
});
|
||||
popup->mouse_release();
|
||||
popup->destroy();
|
||||
@@ -723,18 +724,18 @@ void App::init_menu_experimental()
|
||||
{
|
||||
if (auto text = popup_time->find<NodeText>("menu-label"))
|
||||
{
|
||||
text->set_text(App::I.rec_running ? "Stop Recording" : "Start Recording");
|
||||
text->set_text(rec_running ? "Stop Recording" : "Start Recording");
|
||||
}
|
||||
}
|
||||
|
||||
popup_time->find<NodeButtonCustom>("timelapse-start")->on_click = [this, popup_time, popup_exp](Node*) {
|
||||
App::I.rec_running ? App::I.rec_stop() : App::I.rec_start();
|
||||
rec_running ? rec_stop() : rec_start();
|
||||
popup_time->destroy();
|
||||
popup_exp->destroy();
|
||||
};
|
||||
|
||||
popup_time->find<NodeButtonCustom>("timelapse-clear")->on_click = [this, popup_time, popup_exp](Node*) {
|
||||
App::I.rec_clear();
|
||||
rec_clear();
|
||||
popup_time->destroy();
|
||||
popup_exp->destroy();
|
||||
};
|
||||
@@ -742,7 +743,7 @@ void App::init_menu_experimental()
|
||||
popup_time->find<NodeButtonCustom>("timelapse-export")->on_click = [this, popup_time, popup_exp](Node*) {
|
||||
popup_time->destroy();
|
||||
popup_exp->destroy();
|
||||
App::I.rec_export("");
|
||||
rec_export("");
|
||||
};
|
||||
}
|
||||
};
|
||||
@@ -783,6 +784,7 @@ void App::init_menu_experimental()
|
||||
if (visible(floating_presets.get()))
|
||||
return;
|
||||
auto fpanel = floatings_container->add_child<NodePanelFloating>();
|
||||
fpanel->m_class = NodePanelFloating::kClass::Presets;
|
||||
fpanel->SetHeight(300);
|
||||
fpanel->SetMinHeight(300);
|
||||
if (!floating_presets)
|
||||
@@ -811,6 +813,7 @@ void App::init_menu_experimental()
|
||||
if (visible(floating_color.get()))
|
||||
return;
|
||||
auto fpanel = floatings_container->add_child<NodePanelFloating>();
|
||||
fpanel->m_class = NodePanelFloating::kClass::Color;
|
||||
fpanel->SetHeight(300);
|
||||
fpanel->SetMinHeight(300);
|
||||
if (!floating_color)
|
||||
@@ -835,6 +838,7 @@ void App::init_menu_experimental()
|
||||
if (visible(floating_picker.get()))
|
||||
return;
|
||||
auto fpanel = floatings_container->add_child<NodePanelFloating>();
|
||||
fpanel->m_class = NodePanelFloating::kClass::ColorAdv;
|
||||
fpanel->SetHeight(300);
|
||||
fpanel->SetWidth(300);
|
||||
if (!floating_picker)
|
||||
@@ -856,21 +860,10 @@ void App::init_menu_experimental()
|
||||
popup_exp->destroy();
|
||||
};
|
||||
popup_time->find<NodeButtonCustom>("panel-layers")->on_click = [this, popup_time, popup_exp, visible](Node*) {
|
||||
//if (visible(floating_layers.get()))
|
||||
// return;
|
||||
//auto fpanel = floatings_container->add_child<NodePanelFloating>();
|
||||
//if (!floating_layers)
|
||||
//{
|
||||
// floating_layers = fpanel->m_container->add_child_ref<NodePanelLayer>();
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// fpanel->m_container->add_child(floating_layers);
|
||||
//}
|
||||
|
||||
if (visible(layers.get()))
|
||||
return;
|
||||
auto fpanel = floatings_container->add_child<NodePanelFloating>();
|
||||
fpanel->m_class = NodePanelFloating::kClass::Layers;
|
||||
fpanel->SetMinHeight(100);
|
||||
fpanel->SetHeight(300);
|
||||
fpanel->m_container->add_child(layers);
|
||||
@@ -887,10 +880,13 @@ void App::init_menu_experimental()
|
||||
if (visible(stroke.get()))
|
||||
return;
|
||||
auto fpanel = floatings_container->add_child<NodePanelFloating>();
|
||||
fpanel->m_class = NodePanelFloating::kClass::Brush;
|
||||
fpanel->m_container->add_child(stroke);
|
||||
fpanel->SetHeight(300);
|
||||
stroke->SetPositioning(YGPositionTypeRelative);
|
||||
stroke->SetPosition(0, 0);
|
||||
stroke->SetWidthP(100);
|
||||
stroke->SetHeightP(100);
|
||||
|
||||
popup_time->destroy();
|
||||
popup_exp->destroy();
|
||||
@@ -899,6 +895,7 @@ void App::init_menu_experimental()
|
||||
if (visible(grid.get()))
|
||||
return;
|
||||
auto fpanel = floatings_container->add_child<NodePanelFloating>();
|
||||
fpanel->m_class = NodePanelFloating::kClass::Grids;
|
||||
fpanel->m_container->add_child(grid);
|
||||
fpanel->SetHeight(300);
|
||||
grid->SetPositioning(YGPositionTypeRelative);
|
||||
@@ -914,11 +911,16 @@ void App::init_menu_experimental()
|
||||
|
||||
if (auto rtl_btn = popup_exp->find<NodeButtonCustom>("experimental-rtl"))
|
||||
{
|
||||
auto ui = main->find("central-row");
|
||||
NodeCheckBox* cb = rtl_btn->find<NodeCheckBox>("experimental-rtl-check");
|
||||
cb->set_value(ui->GetRTL() == YGDirectionRTL, false);
|
||||
|
||||
rtl_btn->on_click = [this, popup_exp, rtl_btn](Node* b)
|
||||
{
|
||||
NodeCheckBox* cb = rtl_btn->find<NodeCheckBox>("experimental-rtl-check");
|
||||
cb->set_value(!cb->checked, true);
|
||||
};
|
||||
|
||||
rtl_btn->find<NodeCheckBox>("experimental-rtl-check")->on_value_changed = [this, main](Node*, bool checked)
|
||||
{
|
||||
auto ui = main->find("central-row");
|
||||
@@ -928,25 +930,29 @@ void App::init_menu_experimental()
|
||||
|
||||
if (auto vr_btn = popup_exp->find<NodeButtonCustom>("experimental-vr"))
|
||||
{
|
||||
NodeCheckBox* cb = vr_btn->find<NodeCheckBox>("experimental-vr-check");
|
||||
cb->set_value(has_vr);
|
||||
|
||||
vr_btn->on_click = [this, popup_exp, vr_btn](Node* b)
|
||||
{
|
||||
NodeCheckBox* cb = vr_btn->find<NodeCheckBox>("experimental-vr-check");
|
||||
cb->set_value(!cb->checked, true);
|
||||
};
|
||||
|
||||
vr_btn->find<NodeCheckBox>("experimental-vr-check")->on_value_changed = [this, main](Node* target, bool checked)
|
||||
{
|
||||
if (checked)
|
||||
{
|
||||
if (!App::I.vr_start())
|
||||
if (!vr_start())
|
||||
{
|
||||
auto cb = static_cast<NodeCheckBox*>(target);
|
||||
cb->set_value(false);
|
||||
App::I.message_box("VR Failed", "Couldn't start Virtual Reality mode");
|
||||
message_box("VR Failed", "Couldn't start Virtual Reality mode");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
App::I.vr_stop();
|
||||
vr_stop();
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -1006,7 +1012,7 @@ void App::init_menu_about()
|
||||
{
|
||||
b->on_click = [this, popup](Node*) {
|
||||
LOG("crashing");
|
||||
App::I.crash_test();
|
||||
crash_test();
|
||||
popup->mouse_release();
|
||||
popup->destroy();
|
||||
};
|
||||
@@ -1038,7 +1044,7 @@ void App::init_menu_about()
|
||||
LOG("%lld ms", ms);
|
||||
static char str[256];
|
||||
sprintf(str, "Time %lld ms", ms);
|
||||
App::I.message_box("Performance test", str);
|
||||
message_box("Performance test", str);
|
||||
popup->mouse_release();
|
||||
popup->destroy();
|
||||
};
|
||||
@@ -1302,8 +1308,9 @@ void App::initLayout()
|
||||
//picker->SetHeightP(100);
|
||||
//color->find("title")->destroy();
|
||||
*/
|
||||
ui_restore();
|
||||
|
||||
App::I.redraw = true;
|
||||
redraw = true;
|
||||
};
|
||||
|
||||
LOG("initializing layout xml");
|
||||
@@ -1316,3 +1323,304 @@ void App::initLayout()
|
||||
layout.load("data/layout.xml");
|
||||
LOG("initializing layout completed");
|
||||
}
|
||||
|
||||
void App::ui_save()
|
||||
{
|
||||
Serializer::Descriptor d;
|
||||
d.class_id = "ui-state";
|
||||
|
||||
Serializer::List list_floatings;
|
||||
for (auto const& c : layout[main_id]->find("floatings")->m_children)
|
||||
{
|
||||
if (auto const& f = std::dynamic_pointer_cast<NodePanelFloating>(c))
|
||||
{
|
||||
auto fd = list_floatings.add<Serializer::Descriptor>();
|
||||
fd->class_id = "ui-flt";
|
||||
fd->set("pos", Serializer::Vec2(f->GetPosition()));
|
||||
fd->set("size", Serializer::Vec2(f->m_size));
|
||||
fd->set("class", Serializer::Integer((int)f->m_class));
|
||||
}
|
||||
}
|
||||
d.set("floatings", list_floatings);
|
||||
|
||||
Serializer::List list_drop_left;
|
||||
for (auto const& c : layout[main_id]->find("drop-left")->m_children)
|
||||
{
|
||||
if (auto const& f = std::dynamic_pointer_cast<NodePanelFloating>(c))
|
||||
{
|
||||
auto fd = list_drop_left.add<Serializer::Descriptor>();
|
||||
fd->class_id = "ui-dpl";
|
||||
fd->set("size", Serializer::Vec2(f->m_size));
|
||||
fd->set("class", Serializer::Integer((int)f->m_class));
|
||||
}
|
||||
}
|
||||
d.set("drop-left", list_drop_left);
|
||||
|
||||
Serializer::List list_drop_right;
|
||||
for (auto const& c : layout[main_id]->find("drop-right")->m_children)
|
||||
{
|
||||
if (auto const& f = std::dynamic_pointer_cast<NodePanelFloating>(c))
|
||||
{
|
||||
auto fd = list_drop_right.add<Serializer::Descriptor>();
|
||||
fd->class_id = "ui-dpr";
|
||||
fd->set("size", Serializer::Vec2(f->m_size));
|
||||
fd->set("class", Serializer::Integer((int)f->m_class));
|
||||
}
|
||||
}
|
||||
d.set("drop-right", list_drop_right);
|
||||
|
||||
Settings::set("ui", d);
|
||||
Settings::set("ui-rtl", Serializer::Integer(layout[main_id]->find("central-row")->GetRTL()));
|
||||
|
||||
#if _WIN32
|
||||
extern void win32_save_window_state();
|
||||
win32_save_window_state();
|
||||
#endif
|
||||
|
||||
Settings::save();
|
||||
}
|
||||
|
||||
void App::ui_restore()
|
||||
{
|
||||
if (Settings::has("ui-rtl"))
|
||||
layout[main_id]->find("central-row")->SetRTL((YGDirection)Settings::value<Serializer::Integer>("ui-rtl"));
|
||||
|
||||
if (!Settings::has("ui"))
|
||||
return;
|
||||
auto floatings = layout[main_id]->find_ref("floatings");
|
||||
auto drop_left = layout[main_id]->find_ref("drop-left");
|
||||
auto drop_right = layout[main_id]->find_ref("drop-right");
|
||||
auto d = Settings::get<Serializer::Descriptor>("ui");
|
||||
for (auto const& l : d->get<Serializer::List>("floatings")->items)
|
||||
{
|
||||
auto ld = std::static_pointer_cast<Serializer::Descriptor>(l);
|
||||
auto pos = ld->value<Serializer::Vec2>("pos");
|
||||
auto size = ld->value<Serializer::Vec2>("size");
|
||||
auto cls = static_cast<NodePanelFloating::kClass>(ld->value<Serializer::Integer>("class"));
|
||||
auto f = floatings->add_child<NodePanelFloating>();
|
||||
switch (cls)
|
||||
{
|
||||
case NodePanelFloating::kClass::Presets:
|
||||
{
|
||||
auto floating_presets = f->m_container->add_child<NodePanelBrushPreset>();
|
||||
floating_presets->SetHeightP(100);
|
||||
floating_presets->find("toolbar")->destroy();
|
||||
floating_presets->on_brush_changed = [this](Node* target, std::shared_ptr<Brush>& b) {
|
||||
auto c = Canvas::I->m_current_brush->m_tip_color;
|
||||
*Canvas::I->m_current_brush = *b;
|
||||
Canvas::I->m_current_brush->m_tip_color = c;
|
||||
Canvas::I->m_current_brush->load();
|
||||
brush_update();
|
||||
};
|
||||
break;
|
||||
}
|
||||
case NodePanelFloating::kClass::Color:
|
||||
{
|
||||
auto floating_color = f->m_container->add_child<NodePanelColor>();
|
||||
floating_color->SetHeightP(100);
|
||||
floating_color->find("title")->destroy();
|
||||
floating_color->on_color_changed = [this](Node* target, glm::vec4 color) {
|
||||
Canvas::I->m_current_brush->m_tip_color = color;
|
||||
brush_update();
|
||||
};
|
||||
break;
|
||||
}
|
||||
case NodePanelFloating::kClass::ColorAdv:
|
||||
{
|
||||
floating_picker = f->m_container->add_child_ref<NodeColorPicker>();
|
||||
floating_picker->m_autohide = false;
|
||||
floating_picker->on_color_change = [this](Node* target, glm::vec3 color) {
|
||||
Canvas::I->m_current_brush->m_tip_color = glm::vec4(color, 1.f);
|
||||
brush_update();
|
||||
};
|
||||
break;
|
||||
}
|
||||
case NodePanelFloating::kClass::Layers:
|
||||
f->m_container->add_child(layers);
|
||||
f->SetMinHeight(100);
|
||||
f->SetHeight(300);
|
||||
layers->SetPositioning(YGPositionTypeRelative);
|
||||
layers->SetPosition(0, 0);
|
||||
layers->SetWidthP(100);
|
||||
layers->SetHeightP(100);
|
||||
layers->SetFlexShrink(0);
|
||||
break;
|
||||
case NodePanelFloating::kClass::Brush:
|
||||
f->m_container->add_child(stroke);
|
||||
stroke->SetPositioning(YGPositionTypeRelative);
|
||||
stroke->SetPosition(0, 0);
|
||||
stroke->SetWidthP(100);
|
||||
stroke->SetHeightP(100);
|
||||
break;
|
||||
case NodePanelFloating::kClass::Grids:
|
||||
f->m_container->add_child(grid);
|
||||
grid->SetPositioning(YGPositionTypeRelative);
|
||||
grid->SetPosition(0, 0);
|
||||
grid->SetWidthP(100);
|
||||
grid->SetHeightP(100);
|
||||
break;
|
||||
case NodePanelFloating::kClass::Generic:
|
||||
default:
|
||||
f->m_container->add_child<Node>();
|
||||
break;
|
||||
}
|
||||
f->m_class = cls;
|
||||
f->SetSize(size);
|
||||
f->SetPosition(pos);
|
||||
f->SetPositioning(YGPositionTypeAbsolute);
|
||||
}
|
||||
|
||||
for (auto const& l : d->get<Serializer::List>("drop-left")->items)
|
||||
{
|
||||
auto ld = std::static_pointer_cast<Serializer::Descriptor>(l);
|
||||
auto size = ld->value<Serializer::Vec2>("size");
|
||||
auto cls = static_cast<NodePanelFloating::kClass>(ld->value<Serializer::Integer>("class"));
|
||||
auto f = drop_left->add_child<NodePanelFloating>();
|
||||
switch (cls)
|
||||
{
|
||||
case NodePanelFloating::kClass::Presets:
|
||||
{
|
||||
auto floating_presets = f->m_container->add_child<NodePanelBrushPreset>();
|
||||
floating_presets->SetHeightP(100);
|
||||
floating_presets->find("toolbar")->destroy();
|
||||
floating_presets->on_brush_changed = [this](Node* target, std::shared_ptr<Brush>& b) {
|
||||
auto c = Canvas::I->m_current_brush->m_tip_color;
|
||||
*Canvas::I->m_current_brush = *b;
|
||||
Canvas::I->m_current_brush->m_tip_color = c;
|
||||
Canvas::I->m_current_brush->load();
|
||||
brush_update();
|
||||
};
|
||||
break;
|
||||
}
|
||||
case NodePanelFloating::kClass::Color:
|
||||
{
|
||||
auto floating_color = f->m_container->add_child<NodePanelColor>();
|
||||
floating_color->SetHeightP(100);
|
||||
floating_color->find("title")->destroy();
|
||||
floating_color->on_color_changed = [this](Node* target, glm::vec4 color) {
|
||||
Canvas::I->m_current_brush->m_tip_color = color;
|
||||
brush_update();
|
||||
};
|
||||
break;
|
||||
}
|
||||
case NodePanelFloating::kClass::ColorAdv:
|
||||
{
|
||||
floating_picker = f->m_container->add_child_ref<NodeColorPicker>();
|
||||
floating_picker->m_autohide = false;
|
||||
floating_picker->on_color_change = [this](Node* target, glm::vec3 color) {
|
||||
Canvas::I->m_current_brush->m_tip_color = glm::vec4(color, 1.f);
|
||||
brush_update();
|
||||
};
|
||||
break;
|
||||
}
|
||||
case NodePanelFloating::kClass::Layers:
|
||||
f->m_container->add_child(layers);
|
||||
layers->SetPositioning(YGPositionTypeRelative);
|
||||
layers->SetPosition(0, 0);
|
||||
layers->SetWidthP(100);
|
||||
layers->SetHeightP(100);
|
||||
layers->SetFlexShrink(0);
|
||||
break;
|
||||
case NodePanelFloating::kClass::Brush:
|
||||
f->m_container->add_child(stroke);
|
||||
stroke->SetPositioning(YGPositionTypeRelative);
|
||||
stroke->SetPosition(0, 0);
|
||||
stroke->SetWidthP(100);
|
||||
stroke->SetHeightP(100);
|
||||
break;
|
||||
case NodePanelFloating::kClass::Grids:
|
||||
f->m_container->add_child(grid);
|
||||
grid->SetPositioning(YGPositionTypeRelative);
|
||||
grid->SetPosition(0, 0);
|
||||
grid->SetWidthP(100);
|
||||
grid->SetHeightP(100);
|
||||
break;
|
||||
case NodePanelFloating::kClass::Generic:
|
||||
default:
|
||||
f->m_container->add_child<Node>();
|
||||
break;
|
||||
}
|
||||
f->m_class = cls;
|
||||
f->m_dock = drop_left;
|
||||
f->SetPositioning(YGPositionTypeRelative);
|
||||
f->SetPosition(0, 0);
|
||||
f->SetSize(size);
|
||||
}
|
||||
|
||||
for (auto const& l : d->get<Serializer::List>("drop-right")->items)
|
||||
{
|
||||
auto ld = std::static_pointer_cast<Serializer::Descriptor>(l);
|
||||
auto size = ld->value<Serializer::Vec2>("size");
|
||||
auto cls = static_cast<NodePanelFloating::kClass>(ld->value<Serializer::Integer>("class"));
|
||||
auto f = drop_right->add_child<NodePanelFloating>();
|
||||
switch (cls)
|
||||
{
|
||||
case NodePanelFloating::kClass::Presets:
|
||||
{
|
||||
auto floating_presets = f->m_container->add_child<NodePanelBrushPreset>();
|
||||
floating_presets->SetHeightP(100);
|
||||
floating_presets->find("toolbar")->destroy();
|
||||
floating_presets->on_brush_changed = [this](Node* target, std::shared_ptr<Brush>& b) {
|
||||
auto c = Canvas::I->m_current_brush->m_tip_color;
|
||||
*Canvas::I->m_current_brush = *b;
|
||||
Canvas::I->m_current_brush->m_tip_color = c;
|
||||
Canvas::I->m_current_brush->load();
|
||||
brush_update();
|
||||
};
|
||||
break;
|
||||
}
|
||||
case NodePanelFloating::kClass::Color:
|
||||
{
|
||||
auto floating_color = f->m_container->add_child<NodePanelColor>();
|
||||
floating_color->SetHeightP(100);
|
||||
floating_color->find("title")->destroy();
|
||||
floating_color->on_color_changed = [this](Node* target, glm::vec4 color) {
|
||||
Canvas::I->m_current_brush->m_tip_color = color;
|
||||
brush_update();
|
||||
};
|
||||
break;
|
||||
}
|
||||
case NodePanelFloating::kClass::ColorAdv:
|
||||
{
|
||||
floating_picker = f->m_container->add_child_ref<NodeColorPicker>();
|
||||
floating_picker->m_autohide = false;
|
||||
floating_picker->on_color_change = [this](Node* target, glm::vec3 color) {
|
||||
Canvas::I->m_current_brush->m_tip_color = glm::vec4(color, 1.f);
|
||||
brush_update();
|
||||
};
|
||||
break;
|
||||
}
|
||||
case NodePanelFloating::kClass::Layers:
|
||||
f->m_container->add_child(layers);
|
||||
layers->SetPositioning(YGPositionTypeRelative);
|
||||
layers->SetPosition(0, 0);
|
||||
layers->SetWidthP(100);
|
||||
layers->SetHeightP(100);
|
||||
layers->SetFlexShrink(0);
|
||||
break;
|
||||
case NodePanelFloating::kClass::Brush:
|
||||
f->m_container->add_child(stroke);
|
||||
stroke->SetPositioning(YGPositionTypeRelative);
|
||||
stroke->SetPosition(0, 0);
|
||||
stroke->SetWidthP(100);
|
||||
stroke->SetHeightP(100);
|
||||
break;
|
||||
case NodePanelFloating::kClass::Grids:
|
||||
f->m_container->add_child(grid);
|
||||
grid->SetPositioning(YGPositionTypeRelative);
|
||||
grid->SetPosition(0, 0);
|
||||
grid->SetWidthP(100);
|
||||
grid->SetHeightP(100);
|
||||
break;
|
||||
case NodePanelFloating::kClass::Generic:
|
||||
default:
|
||||
f->m_container->add_child<Node>();
|
||||
break;
|
||||
}
|
||||
f->m_class = cls;
|
||||
f->m_dock = drop_right;
|
||||
f->SetPositioning(YGPositionTypeRelative);
|
||||
f->SetPosition(0, 0);
|
||||
f->SetSize(size);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#include "pch.h"
|
||||
#include "binary_stream.h"
|
||||
|
||||
|
||||
#include "asset.h"
|
||||
|
||||
BinaryStreamReader::~BinaryStreamReader()
|
||||
{
|
||||
@@ -17,6 +16,17 @@ void BinaryStreamReader::init(uint8_t* data_ptr, size_t size, ByteOrder byte_ord
|
||||
m_swap = byte_order == ByteOrder::Host ? false : byte_order != sys_order();
|
||||
}
|
||||
|
||||
bool BinaryStreamReader::load(const std::string& path, ByteOrder byte_order /*= ByteOrder::Host*/)
|
||||
{
|
||||
if (m_asset.open(path.c_str()))
|
||||
{
|
||||
m_asset.read_all();
|
||||
init(m_asset.m_data, m_asset.m_len, byte_order);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t BinaryStreamReader::pos()
|
||||
{
|
||||
return std::distance(m_ptr, m_cur);
|
||||
@@ -198,6 +208,17 @@ void BinaryStreamWriter::init(ByteOrder byte_order /*= ByteOrder::Host*/)
|
||||
m_swap = byte_order == ByteOrder::Host ? false : byte_order != sys_order();
|
||||
}
|
||||
|
||||
bool BinaryStreamWriter::save(const std::string& path) const
|
||||
{
|
||||
std::ofstream f(path, std::ios::binary);
|
||||
if (f.good())
|
||||
{
|
||||
f.write((char*)m_data.data(), m_data.size());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void BinaryStreamWriter::skip(size_t bytes, uint8_t fill /*= 0*/)
|
||||
{
|
||||
m_data.resize(m_data.size() + bytes);
|
||||
@@ -334,5 +355,6 @@ void BinaryStreamWriter::wrle(std::vector<uint8_t> data)
|
||||
|
||||
void BinaryStreamWriter::wkey_or_string(std::string s)
|
||||
{
|
||||
assert(s.size() > 0);
|
||||
wstring(s);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
#include <codecvt>
|
||||
#include "asset.h"
|
||||
|
||||
class BinaryStream
|
||||
{
|
||||
@@ -70,6 +71,7 @@ public:
|
||||
BinaryStreamReader() = default;
|
||||
~BinaryStreamReader();
|
||||
void init(uint8_t* data_ptr, size_t size, ByteOrder byte_order = ByteOrder::Host);
|
||||
bool load(const std::string& path, ByteOrder byte_order = ByteOrder::Host);
|
||||
size_t pos();
|
||||
void skip(size_t bytes);
|
||||
// snap to the next 4-alignment
|
||||
@@ -127,6 +129,7 @@ private:
|
||||
uint8_t *m_ptr = nullptr;
|
||||
uint8_t *m_cur = nullptr;
|
||||
size_t m_size = 0;
|
||||
Asset m_asset;
|
||||
};
|
||||
|
||||
class BinaryStreamWriter : public BinaryStream
|
||||
@@ -137,6 +140,7 @@ public:
|
||||
BinaryStreamWriter() = default;
|
||||
~BinaryStreamWriter() = default;
|
||||
void init(ByteOrder byte_order = ByteOrder::Host);
|
||||
bool save(const std::string& path) const;
|
||||
void skip(size_t bytes, uint8_t fill = 0);
|
||||
// snap to the next 4-alignment
|
||||
void snap();
|
||||
|
||||
35
src/main.cpp
35
src/main.cpp
@@ -16,6 +16,7 @@
|
||||
#include <deque>
|
||||
#include <chrono>
|
||||
#include "abr.h"
|
||||
#include "settings.h"
|
||||
|
||||
#define WM_USER_CLOSE (WM_USER + 1)
|
||||
|
||||
@@ -517,6 +518,15 @@ void win32_vr_stop()
|
||||
}
|
||||
}
|
||||
|
||||
void win32_save_window_state()
|
||||
{
|
||||
WINDOWPLACEMENT p;
|
||||
GetWindowPlacement(hWnd, &p);
|
||||
Settings::set("window-show-cmd", Serializer::Integer(p.showCmd));
|
||||
Settings::set("window-rect", Serializer::IVec4({ p.rcNormalPosition.left,
|
||||
p.rcNormalPosition.top, p.rcNormalPosition.right, p.rcNormalPosition.bottom }));
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
WNDCLASS wc;
|
||||
@@ -562,7 +572,6 @@ int main(int argc, char** argv)
|
||||
read_WMI_info();
|
||||
|
||||
App::I.create();
|
||||
RECT clientRect = { 0, 0, (int)App::I.width, (int)App::I.height };
|
||||
|
||||
// Inizialize data structures to zero
|
||||
memset(&wc, 0, sizeof(wc));
|
||||
@@ -588,8 +597,21 @@ int main(int argc, char** argv)
|
||||
GetDpiForMonitor(monitor, MDT_EFFECTIVE_DPI, &x, &y);
|
||||
App::I.zoom *= (float)x / 96.f;
|
||||
|
||||
AdjustWindowRect(&clientRect, WS_OVERLAPPEDWINDOW, false);
|
||||
hWnd = CreateWindow(wc.lpszClassName, L"PanoPainter", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
RECT clientRect = { 0, 0, (int)App::I.width, (int)App::I.height };
|
||||
POINT clientPos = { CW_USEDEFAULT, CW_USEDEFAULT };
|
||||
if (Settings::has("window-rect"))
|
||||
{
|
||||
auto wnd_rect = Settings::value<Serializer::IVec4>("window-rect");
|
||||
App::I.width = wnd_rect.z - wnd_rect.x;
|
||||
App::I.height = wnd_rect.w - wnd_rect.y;
|
||||
clientRect = { wnd_rect.x, wnd_rect.y, wnd_rect.z, wnd_rect.w };
|
||||
clientPos = { wnd_rect.x, wnd_rect.y };
|
||||
}
|
||||
else
|
||||
{
|
||||
AdjustWindowRect(&clientRect, WS_OVERLAPPEDWINDOW, false);
|
||||
}
|
||||
hWnd = CreateWindow(wc.lpszClassName, L"PanoPainter", WS_OVERLAPPEDWINDOW, clientPos.x, clientPos.y,
|
||||
(float)(clientRect.right - clientRect.left) * App::I.zoom,
|
||||
(float)(clientRect.bottom - clientRect.top) * App::I.zoom, 0, 0, hInst, 0);
|
||||
|
||||
@@ -651,7 +673,7 @@ int main(int argc, char** argv)
|
||||
wglDeleteContext(hRC);
|
||||
DestroyWindow(hWnd);
|
||||
|
||||
hWnd = CreateWindow(wc.lpszClassName, window_title, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
hWnd = CreateWindow(wc.lpszClassName, window_title, WS_OVERLAPPEDWINDOW, clientPos.x, clientPos.y,
|
||||
(float)(clientRect.right - clientRect.left) * App::I.zoom,
|
||||
(float)(clientRect.bottom - clientRect.top) * App::I.zoom, 0, 0, hInst, 0);
|
||||
|
||||
@@ -691,8 +713,11 @@ int main(int argc, char** argv)
|
||||
LOG("init app");
|
||||
App::I.init();
|
||||
|
||||
int show_cmd = SW_NORMAL;
|
||||
Settings::value<Serializer::Integer>("window-show-cmd", show_cmd);
|
||||
|
||||
LOG("show main window");
|
||||
ShowWindow(hWnd, SW_NORMAL);
|
||||
ShowWindow(hWnd, show_cmd);
|
||||
|
||||
if (!sandboxed)
|
||||
{
|
||||
|
||||
@@ -32,6 +32,15 @@ void NodePanelFloating::init_controls()
|
||||
m_button_minimize = find<NodeButton>("button-minimize");
|
||||
m_button_minimize->on_click = [this](Node*) {
|
||||
m_container->ToggleVisibility();
|
||||
if (m_container->m_display)
|
||||
{
|
||||
SetHeight(m_extended_size.y);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_extended_size.y = GetHeight();
|
||||
SetHeight(YGUndefined);
|
||||
}
|
||||
};
|
||||
m_button_close = find<NodeButton>("button-close");
|
||||
m_button_close->on_click = [this](Node*) {
|
||||
|
||||
@@ -6,7 +6,7 @@ class NodePanelFloating : public NodeBorder
|
||||
{
|
||||
enum class kDragAction : uint8_t { Move, Resize, Reheight } m_action;
|
||||
bool m_dragging = false;
|
||||
std::weak_ptr<Node> m_dock;
|
||||
glm::vec2 m_extended_size;
|
||||
glm::vec2 m_drag_start_pos;
|
||||
glm::vec2 m_drag_start_cur;
|
||||
NodeButton* m_button_minimize;
|
||||
@@ -15,8 +15,10 @@ class NodePanelFloating : public NodeBorder
|
||||
std::shared_ptr<NodeBorder> m_drop_placeholder;
|
||||
public:
|
||||
Node* m_container;
|
||||
std::weak_ptr<Node> m_dock;
|
||||
using this_class = NodePanelFloating;
|
||||
using parent = NodeBorder;
|
||||
enum class kClass : uint8_t { Presets, Color, ColorAdv, Layers, Brush, Grids, Generic } m_class = kClass::Generic;
|
||||
virtual Node* clone_instantiate() const override;
|
||||
virtual void clone_finalize(Node* dest) const override;
|
||||
virtual kEventResult handle_event(Event* e) override;
|
||||
|
||||
@@ -22,6 +22,9 @@ std::map<std::string /*key*/, std::function<Serializer::Type::Ref()>> Serializer
|
||||
{ "vec2", [] { return std::make_shared<Serializer::Vec2>(); } },
|
||||
{ "vec3", [] { return std::make_shared<Serializer::Vec3>(); } },
|
||||
{ "vec4", [] { return std::make_shared<Serializer::Vec4>(); } },
|
||||
{ "ive2", [] { return std::make_shared<Serializer::IVec2>(); } },
|
||||
{ "ive3", [] { return std::make_shared<Serializer::IVec3>(); } },
|
||||
{ "ive4", [] { return std::make_shared<Serializer::IVec4>(); } },
|
||||
{ "flt ", [] { return std::make_shared<Serializer::Float>(); } },
|
||||
{ "cstr", [] { return std::make_shared<Serializer::CString>(); } },
|
||||
};
|
||||
|
||||
105
src/serializer.h
105
src/serializer.h
@@ -70,7 +70,17 @@ public:
|
||||
{
|
||||
w.wi32((int)items.size());
|
||||
for (auto& i : items)
|
||||
{
|
||||
w.wstring_raw(i->type_key());
|
||||
i->write(w);
|
||||
}
|
||||
}
|
||||
template <typename T>
|
||||
std::shared_ptr<T> add()
|
||||
{
|
||||
auto ptr = std::make_shared<T>();
|
||||
items.emplace_back(ptr);
|
||||
return ptr;
|
||||
}
|
||||
};
|
||||
struct Double : public Type
|
||||
@@ -263,6 +273,81 @@ public:
|
||||
w.wflt(value.w);
|
||||
}
|
||||
};
|
||||
struct IVec2 : public Type
|
||||
{
|
||||
using native_type = glm::ivec2;
|
||||
glm::ivec2 value;
|
||||
IVec2() = default;
|
||||
IVec2(glm::ivec2 v) : value(v) { }
|
||||
virtual std::string type_key() const override { return "ive2"; }
|
||||
virtual std::string str(int indent, const std::string& prefix) const override
|
||||
{
|
||||
return std::string(indent, '-') + prefix + fmt::format("ivec2: {} {}", value.x, value.y);
|
||||
}
|
||||
virtual bool read(BinaryStreamReader& r) override
|
||||
{
|
||||
value.x = r.ri32();
|
||||
value.y = r.ri32();
|
||||
return true;
|
||||
}
|
||||
virtual void write(BinaryStreamWriter& w) const override
|
||||
{
|
||||
w.wi32(value.x);
|
||||
w.wi32(value.y);
|
||||
}
|
||||
};
|
||||
struct IVec3 : public Type
|
||||
{
|
||||
using native_type = glm::ivec3;
|
||||
glm::ivec3 value;
|
||||
IVec3() = default;
|
||||
IVec3(glm::ivec3 v) : value(v) { }
|
||||
virtual std::string type_key() const override { return "ive3"; }
|
||||
virtual std::string str(int indent, const std::string& prefix) const override
|
||||
{
|
||||
return std::string(indent, '-') + prefix + fmt::format("ivec3: {} {} {}", value.x, value.y, value.z);
|
||||
}
|
||||
virtual bool read(BinaryStreamReader& r) override
|
||||
{
|
||||
value.x = r.ri32();
|
||||
value.y = r.ri32();
|
||||
value.z = r.ri32();
|
||||
return true;
|
||||
}
|
||||
virtual void write(BinaryStreamWriter& w) const override
|
||||
{
|
||||
w.wu32(value.x);
|
||||
w.wu32(value.y);
|
||||
w.wu32(value.z);
|
||||
}
|
||||
};
|
||||
struct IVec4 : public Type
|
||||
{
|
||||
using native_type = glm::ivec4;
|
||||
glm::ivec4 value;
|
||||
IVec4() = default;
|
||||
IVec4(glm::ivec4 v) : value(v) { }
|
||||
virtual std::string type_key() const override { return "ive4"; }
|
||||
virtual std::string str(int indent, const std::string& prefix) const override
|
||||
{
|
||||
return std::string(indent, '-') + prefix + fmt::format("ivec4: {} {} {} {}", value.x, value.y, value.z, value.w);
|
||||
}
|
||||
virtual bool read(BinaryStreamReader& r) override
|
||||
{
|
||||
value.x = r.ri32();
|
||||
value.y = r.ri32();
|
||||
value.z = r.ri32();
|
||||
value.w = r.ri32();
|
||||
return true;
|
||||
}
|
||||
virtual void write(BinaryStreamWriter& w) const override
|
||||
{
|
||||
w.wi32(value.x);
|
||||
w.wi32(value.y);
|
||||
w.wi32(value.z);
|
||||
w.wi32(value.w);
|
||||
}
|
||||
};
|
||||
struct Enum : public Type
|
||||
{
|
||||
std::string type;
|
||||
@@ -352,7 +437,7 @@ public:
|
||||
struct Descriptor : public Type
|
||||
{
|
||||
std::wstring name;
|
||||
std::string class_id;
|
||||
std::string class_id = "desc";
|
||||
Type::Map props;
|
||||
Descriptor() = default;
|
||||
virtual std::string type_key() const override { return "Objc"; }
|
||||
@@ -372,19 +457,33 @@ public:
|
||||
{
|
||||
return has(key) ? std::dynamic_pointer_cast<T>(props.at(key)) : nullptr;
|
||||
}
|
||||
template<typename T> std::shared_ptr<T> set(const std::string& key, const T value)
|
||||
{
|
||||
if (auto ptr = get<T>(key))
|
||||
{
|
||||
*ptr = value;
|
||||
return ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
ptr = std::make_shared<T>(value);
|
||||
props[key] = ptr;
|
||||
return ptr;
|
||||
}
|
||||
}
|
||||
template<typename T> auto value(const std::string& key) const
|
||||
{
|
||||
if (auto v = get<T>(key))
|
||||
return v->value;
|
||||
return decltype(T::value){};
|
||||
}
|
||||
template<typename T, typename D> auto value_or(const std::string& key, const D val) const
|
||||
template<typename T, typename D = decltype(T::value)> auto value_or(const std::string& key, const D val) const
|
||||
{
|
||||
if (auto v = get<T>(key))
|
||||
return v->value;
|
||||
return val;
|
||||
}
|
||||
template<typename T, typename D> void value(const std::string& key, D& dest) const
|
||||
template<typename T, typename D = decltype(T::value)> void value(const std::string& key, D& dest) const
|
||||
{
|
||||
if (auto v = get<T>(key))
|
||||
dest = static_cast<D>(v->value);
|
||||
|
||||
26
src/settings.cpp
Normal file
26
src/settings.cpp
Normal file
@@ -0,0 +1,26 @@
|
||||
#include "pch.h"
|
||||
#include "settings.h"
|
||||
#include "app.h"
|
||||
|
||||
Settings Settings::I;
|
||||
|
||||
bool Settings::load()
|
||||
{
|
||||
auto path = App::I.data_path + "/settings/pref.bin";
|
||||
BinaryStreamReader sr;
|
||||
if (sr.load(path))
|
||||
{
|
||||
I.props.clear();
|
||||
return I.read(sr);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Settings::save()
|
||||
{
|
||||
auto path = App::I.data_path + "/settings/pref.bin";
|
||||
BinaryStreamWriter sw;
|
||||
sw.init();
|
||||
I.write(sw);
|
||||
return sw.save(path);
|
||||
}
|
||||
35
src/settings.h
Normal file
35
src/settings.h
Normal file
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
#include "serializer.h"
|
||||
|
||||
class Settings : public Serializer::Descriptor
|
||||
{
|
||||
public:
|
||||
Settings() { class_id = "pref"; }
|
||||
static Settings I;
|
||||
static bool load();
|
||||
static bool save();
|
||||
static bool has(const std::string& key)
|
||||
{
|
||||
return I.Descriptor::has(key);
|
||||
}
|
||||
template <typename T>
|
||||
static void set(const std::string& key, const T value)
|
||||
{
|
||||
I.Descriptor::set(key, value);
|
||||
}
|
||||
template <typename T>
|
||||
static std::shared_ptr<T> get(const std::string& key)
|
||||
{
|
||||
return I.Descriptor::get<T>(key);
|
||||
}
|
||||
template <typename T, typename D = decltype(T::value)>
|
||||
static void value(const std::string& key, D& dest)
|
||||
{
|
||||
I.Descriptor::value<T, D>(key, dest);
|
||||
}
|
||||
template <typename T>
|
||||
static auto value(const std::string& key)
|
||||
{
|
||||
return I.Descriptor::value<T>(key);
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user