add export layers, export png, import brush padding
This commit is contained in:
@@ -835,23 +835,23 @@ Here's a list of what's available in this release.
|
|||||||
<!--popup menu-->
|
<!--popup menu-->
|
||||||
<layout id="popup-menu">
|
<layout id="popup-menu">
|
||||||
<popup-menu positioning="absolute" position="100 100" width="150" thickness="1" border-color=".1" color=".4 .4 .4 .8" dir="col">
|
<popup-menu positioning="absolute" position="100 100" width="150" thickness="1" border-color=".1" color=".4 .4 .4 .8" dir="col">
|
||||||
<button-custom text="Menu" height="30" align="center" color=".2" pad="0 0 0 10" dir="row">
|
<button-custom height="30" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||||
<icon icon="camera" width="20"/>
|
<icon icon="camera" width="20"/>
|
||||||
<text text="Snapshot" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
<text text="Snapshot" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||||
</button-custom>
|
</button-custom>
|
||||||
<button-custom text="Menu" height="30" align="center" color=".2" pad="0 0 0 10" dir="row">
|
<button-custom height="30" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||||
<icon icon="layers" width="20"/>
|
<icon icon="layers" width="20"/>
|
||||||
<text text="Layers" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
<text text="Layers" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||||
</button-custom>
|
</button-custom>
|
||||||
<button-custom text="Menu" height="30" align="center" color=".2" pad="0 0 0 10" dir="row">
|
<button-custom height="30" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||||
<icon icon="page_white" width="20"/>
|
<icon icon="page_white" width="20"/>
|
||||||
<text text="New Layer" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
<text text="New Layer" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||||
</button-custom>
|
</button-custom>
|
||||||
<button-custom text="Menu" height="30" align="center" color=".2" pad="0 0 0 10" dir="row">
|
<button-custom height="30" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||||
<icon icon="page_white_paste" width="20"/>
|
<icon icon="page_white_paste" width="20"/>
|
||||||
<text text="Paste" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
<text text="Paste" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||||
</button-custom>
|
</button-custom>
|
||||||
<button-custom text="Menu" height="30" align="center" color=".2" pad="0 0 0 10" dir="row">
|
<button-custom height="30" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||||
<icon icon="page_white_stack" width="20"/>
|
<icon icon="page_white_stack" width="20"/>
|
||||||
<text text="Copy" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
<text text="Copy" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||||
</button-custom>
|
</button-custom>
|
||||||
@@ -875,7 +875,7 @@ Here's a list of what's available in this release.
|
|||||||
</node>
|
</node>
|
||||||
</button-custom>
|
</button-custom>
|
||||||
-->
|
-->
|
||||||
<button-custom id="file-newdoc" text="Menu" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
<button-custom id="file-newdoc" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||||
<icon icon="page_add" width="20"/>
|
<icon icon="page_add" width="20"/>
|
||||||
<text text="New Pano" grow="1" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
<text text="New Pano" grow="1" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||||
<text text="Ctrl-N" color=".4" justify="flex-end" margin="0 10 0 10" font-face="arial" font-size="11"/>
|
<text text="Ctrl-N" color=".4" justify="flex-end" margin="0 10 0 10" font-face="arial" font-size="11"/>
|
||||||
@@ -885,80 +885,97 @@ Here's a list of what's available in this release.
|
|||||||
<text text="Import" grow="1" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
<text text="Import" grow="1" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||||
</button-custom>
|
</button-custom>
|
||||||
<!--
|
<!--
|
||||||
<button-custom id="file-open" text="Menu" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
<button-custom id="file-open" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||||
<icon icon="page_add" width="20"/>
|
<icon icon="page_add" width="20"/>
|
||||||
<text text="Open" grow="1" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
<text text="Open" grow="1" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||||
</button-custom>
|
</button-custom>
|
||||||
-->
|
-->
|
||||||
<button-custom id="file-browse" text="Menu" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
<button-custom id="file-browse" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||||
<icon icon="images" width="20"/>
|
<icon icon="images" width="20"/>
|
||||||
<text text="Browse" grow="1" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
<text text="Browse" grow="1" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||||
<text text="Ctrl-Shift-O" color=".4" justify="flex-end" margin="0 10 0 10" font-face="arial" font-size="11"/>
|
<text text="Ctrl-Shift-O" color=".4" justify="flex-end" margin="0 10 0 10" font-face="arial" font-size="11"/>
|
||||||
</button-custom>
|
</button-custom>
|
||||||
<button-custom id="file-open" os="osx,win" text="Menu" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
<button-custom id="file-open" os="osx,win" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||||
<icon icon="image" width="20"/>
|
<icon icon="image" width="20"/>
|
||||||
<text text="Open Path" grow="1" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
<text text="Open Path" grow="1" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||||
<text text="Ctrl-O" color=".4" justify="flex-end" margin="0 10 0 10" font-face="arial" font-size="11"/>
|
<text text="Ctrl-O" color=".4" justify="flex-end" margin="0 10 0 10" font-face="arial" font-size="11"/>
|
||||||
</button-custom>
|
</button-custom>
|
||||||
<button-custom id="file-save" text="Menu" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
<button-custom id="file-save" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||||
<icon icon="disk" width="20"/>
|
<icon icon="disk" width="20"/>
|
||||||
<text text="Save" grow="1" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
<text text="Save" grow="1" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||||
<text text="Ctrl-S" color=".4" justify="flex-end" margin="0 10 0 10" font-face="arial" font-size="11"/>
|
<text text="Ctrl-S" color=".4" justify="flex-end" margin="0 10 0 10" font-face="arial" font-size="11"/>
|
||||||
</button-custom>
|
</button-custom>
|
||||||
<button-custom id="file-save-as" text="Menu" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
<button-custom id="file-save-as" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||||
<icon icon="disk_multiple" width="20"/>
|
<icon icon="disk_multiple" width="20"/>
|
||||||
<text text="Save As.." grow="1" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
<text text="Save As.." grow="1" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||||
</button-custom>
|
</button-custom>
|
||||||
<button-custom id="file-save-ver" text="Menu" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
<button-custom id="file-save-ver" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||||
<icon icon="disk_multiple" width="20"/>
|
<icon icon="disk_multiple" width="20"/>
|
||||||
<text text="Save Version" grow="1" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
<text text="Save Version" grow="1" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||||
<text text="Ctrl-Shift-S" color=".4" justify="flex-end" margin="0 10 0 10" font-face="arial" font-size="11"/>
|
<text text="Ctrl-Shift-S" color=".4" justify="flex-end" margin="0 10 0 10" font-face="arial" font-size="11"/>
|
||||||
</button-custom>
|
</button-custom>
|
||||||
<button-custom id="file-export" text="Menu" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
<node dir="row">
|
||||||
|
<button-custom id="file-export" height="40" align="center" color=".2" pad="0 0 0 10" dir="row" grow="1">
|
||||||
<icon icon="picture_go" width="20"/>
|
<icon icon="picture_go" width="20"/>
|
||||||
<text text="Export JPG" grow="1" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
<text text="Export JPG" grow="1" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||||
</button-custom>
|
</button-custom>
|
||||||
<button-custom id="file-share" os="osx,ios" text="Menu" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
<button-custom id="file-export-tick" height="40" width="40" align="center" justify="center" color=".2" dir="row">
|
||||||
|
<icon icon="resultset_next" width="20"/>
|
||||||
|
</button-custom>
|
||||||
|
</node>
|
||||||
|
<button-custom id="file-share" os="osx,ios" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||||
<icon icon="picture_go" width="20"/>
|
<icon icon="picture_go" width="20"/>
|
||||||
<text text="Share" grow="1" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
<text text="Share" grow="1" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||||
</button-custom>
|
</button-custom>
|
||||||
<button-custom id="file-resize" text="Menu" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
<button-custom id="file-resize" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||||
<icon icon="arrow_out" width="20"/>
|
<icon icon="arrow_out" width="20"/>
|
||||||
<text text="Resize Document" grow="1" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
<text text="Resize Document" grow="1" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||||
</button-custom>
|
</button-custom>
|
||||||
<!--
|
<!--
|
||||||
<button-custom id="file-export-cubes" text="Menu" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
<button-custom id="file-export-cubes" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||||
<icon icon="page_white_stack" width="20"/>
|
<icon icon="page_white_stack" width="20"/>
|
||||||
<text text="Export Cubes" grow="1" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
<text text="Export Cubes" grow="1" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||||
</button-custom>
|
</button-custom>
|
||||||
-->
|
-->
|
||||||
<button-custom id="file-cloud-upload" text="Menu" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
<button-custom id="file-cloud-upload" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||||
<icon icon="weather_clouds" width="20"/>
|
<icon icon="weather_clouds" width="20"/>
|
||||||
<text text="Cloud Publish" grow="1" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
<text text="Cloud Publish" grow="1" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||||
</button-custom>
|
</button-custom>
|
||||||
<button-custom id="file-cloud-browse" text="Menu" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
<button-custom id="file-cloud-browse" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||||
<icon icon="weather_clouds" width="20"/>
|
<icon icon="weather_clouds" width="20"/>
|
||||||
<text text="Cloud Browse" grow="1" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
<text text="Cloud Browse" grow="1" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||||
</button-custom>
|
</button-custom>
|
||||||
<!--<button-custom text="Menu" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
<!--<button-custom height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||||
<icon width="20"/>
|
<icon width="20"/>
|
||||||
<text text="Quit" grow="1" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
<text text="Quit" grow="1" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||||
</button-custom>-->
|
</button-custom>-->
|
||||||
</popup-menu>
|
</popup-menu>
|
||||||
</layout>
|
</layout>
|
||||||
|
|
||||||
|
<!--file submenu - export-->
|
||||||
|
<layout id="file-submenu-export">
|
||||||
|
<popup-menu positioning="absolute" position="100 100" width="150" thickness="1" border-color=".1" color=".4 .4 .4 .8" dir="col">
|
||||||
|
<button-custom id="file-submenu-export-png" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||||
|
<text text="PNG" grow="1" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||||
|
</button-custom>
|
||||||
|
<button-custom id="file-submenu-export-layers" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||||
|
<text text="Separate Layers" grow="1" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||||
|
</button-custom>
|
||||||
|
</popup-menu>
|
||||||
|
</layout>
|
||||||
|
|
||||||
<!--edit menu-->
|
<!--edit menu-->
|
||||||
<layout id="edit-menu">
|
<layout id="edit-menu">
|
||||||
<popup-menu positioning="absolute" position="100 100" width="150" thickness="1" border-color=".1" color=".4 .4 .4 .8" dir="col">
|
<popup-menu positioning="absolute" position="100 100" width="150" thickness="1" border-color=".1" color=".4 .4 .4 .8" dir="col">
|
||||||
<button-custom text="Menu" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
<button-custom height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||||
<icon icon="page_add" width="20"/>
|
<icon icon="page_add" width="20"/>
|
||||||
<text text="New Panodoc" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
<text text="New Panodoc" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||||
</button-custom>
|
</button-custom>
|
||||||
<button-custom text="Menu" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
<button-custom height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||||
<icon icon="disk" width="20"/>
|
<icon icon="disk" width="20"/>
|
||||||
<text text="Save" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
<text text="Save" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||||
</button-custom>
|
</button-custom>
|
||||||
<button-custom text="Menu" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
<button-custom height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||||
<icon icon="disk_multiple" width="20"/>
|
<icon icon="disk_multiple" width="20"/>
|
||||||
<text text="Save as.." margin="0 0 0 5" font-face="arial" font-size="11"/>
|
<text text="Save as.." margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||||
</button-custom>
|
</button-custom>
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ public:
|
|||||||
NodeMessageBox* msgbox;
|
NodeMessageBox* msgbox;
|
||||||
NodeSettings* settings;
|
NodeSettings* settings;
|
||||||
NodePopupMenu* popup = nullptr;
|
NodePopupMenu* popup = nullptr;
|
||||||
|
NodePopupMenu* subpopup = nullptr;
|
||||||
NodePopupMenu* menu_file = nullptr;
|
NodePopupMenu* menu_file = nullptr;
|
||||||
NodePopupMenu* menu_edit = nullptr;
|
NodePopupMenu* menu_edit = nullptr;
|
||||||
NodePopupMenu* menu_layers = nullptr;
|
NodePopupMenu* menu_layers = nullptr;
|
||||||
@@ -178,7 +179,8 @@ public:
|
|||||||
void dialog_save_ver();
|
void dialog_save_ver();
|
||||||
void dialog_open();
|
void dialog_open();
|
||||||
void dialog_browse();
|
void dialog_browse();
|
||||||
void dialog_export();
|
void dialog_export(std::string ext);
|
||||||
|
void dialog_export_layers();
|
||||||
void dialog_export_cubes();
|
void dialog_export_cubes();
|
||||||
void dialog_layer_rename();
|
void dialog_layer_rename();
|
||||||
void dialog_resize();
|
void dialog_resize();
|
||||||
|
|||||||
@@ -412,7 +412,7 @@ void App::dialog_save()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void App::dialog_export()
|
void App::dialog_export(std::string ext)
|
||||||
{
|
{
|
||||||
if (!check_license())
|
if (!check_license())
|
||||||
{
|
{
|
||||||
@@ -423,7 +423,30 @@ void App::dialog_export()
|
|||||||
if (canvas)
|
if (canvas)
|
||||||
{
|
{
|
||||||
// TODO: use picker
|
// TODO: use picker
|
||||||
canvas->m_canvas->export_equirectangular(work_path + "/" + doc_name + ".jpg", [this]{
|
canvas->m_canvas->export_equirectangular(work_path + "/" + doc_name + ext, [this]{
|
||||||
|
#if defined(__IOS__)
|
||||||
|
message_box("Export JPG", "Image exported to Photos");
|
||||||
|
#elif defined(__OSX__)
|
||||||
|
message_box("Export JPG", "Image exported to Pictures/PanoPainter folder");
|
||||||
|
#elif defined(_WIN32)
|
||||||
|
message_box("Export JPG", "Image exported to " + work_path);
|
||||||
|
#endif
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void App::dialog_export_layers()
|
||||||
|
{
|
||||||
|
if (!check_license())
|
||||||
|
{
|
||||||
|
message_box("License", "This function is disabled in demo mode.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (canvas)
|
||||||
|
{
|
||||||
|
// TODO: use picker
|
||||||
|
canvas->m_canvas->export_layers(doc_name, [this] {
|
||||||
#if defined(__IOS__)
|
#if defined(__IOS__)
|
||||||
message_box("Export JPG", "Image exported to Photos");
|
message_box("Export JPG", "Image exported to Photos");
|
||||||
#elif defined(__OSX__)
|
#elif defined(__OSX__)
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ void App::init_toolbar_main()
|
|||||||
button->on_click = [this, button](Node*) {
|
button->on_click = [this, button](Node*) {
|
||||||
if (canvas)
|
if (canvas)
|
||||||
{
|
{
|
||||||
canvas->m_canvas->export_anim();
|
//canvas->m_canvas->export_anim();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -463,10 +463,40 @@ void App::init_menu_file()
|
|||||||
};
|
};
|
||||||
if (auto b = popup->find<NodeButtonCustom>("file-export"))
|
if (auto b = popup->find<NodeButtonCustom>("file-export"))
|
||||||
b->on_click = [this](Node*) {
|
b->on_click = [this](Node*) {
|
||||||
dialog_export();
|
dialog_export(".jpg");
|
||||||
popup->mouse_release();
|
popup->mouse_release();
|
||||||
popup->destroy();
|
popup->destroy();
|
||||||
};
|
};
|
||||||
|
if (auto b = popup->find<NodeButtonCustom>("file-export-tick"))
|
||||||
|
b->on_click = [this,b](Node*) {
|
||||||
|
glm::vec2 pos = b->m_pos + glm::vec2(b->m_size.x, 0);
|
||||||
|
subpopup = (NodePopupMenu*)layout[const_hash("file-submenu-export")]->m_children[0]->clone();
|
||||||
|
subpopup->update();
|
||||||
|
if (YGNodeStyleGetDirection(layout[main_id]->y_node) == YGDirectionRTL)
|
||||||
|
pos.x = pos.x - subpopup->m_size.x + b->m_size.x;
|
||||||
|
subpopup->SetPositioning(YGPositionTypeAbsolute);
|
||||||
|
subpopup->SetPosition(pos.x, pos.y);
|
||||||
|
layout[main_id]->add_child(subpopup);
|
||||||
|
layout[main_id]->update();
|
||||||
|
subpopup->mouse_capture();
|
||||||
|
subpopup->m_mouse_ignore = false;
|
||||||
|
subpopup->m_flood_events = true;
|
||||||
|
subpopup->m_capture_children = false;
|
||||||
|
subpopup->find<NodeButtonCustom>("file-submenu-export-png")->on_click = [this](Node*) {
|
||||||
|
dialog_export(".png");
|
||||||
|
subpopup->mouse_release();
|
||||||
|
subpopup->destroy();
|
||||||
|
popup->mouse_release();
|
||||||
|
popup->destroy();
|
||||||
|
};
|
||||||
|
subpopup->find<NodeButtonCustom>("file-submenu-export-layers")->on_click = [this](Node*) {
|
||||||
|
dialog_export_layers();
|
||||||
|
subpopup->mouse_release();
|
||||||
|
subpopup->destroy();
|
||||||
|
popup->mouse_release();
|
||||||
|
popup->destroy();
|
||||||
|
};
|
||||||
|
};
|
||||||
if (auto b = popup->find<NodeButtonCustom>("file-share"))
|
if (auto b = popup->find<NodeButtonCustom>("file-share"))
|
||||||
b->on_click = [this](Node*) {
|
b->on_click = [this](Node*) {
|
||||||
share_file(doc_path);
|
share_file(doc_path);
|
||||||
|
|||||||
@@ -168,15 +168,15 @@ void App::initShaders()
|
|||||||
"void main() {\n"
|
"void main() {\n"
|
||||||
" mediump float stroke = 1.0 - texture(tex, uv).r;\n"
|
" mediump float stroke = 1.0 - texture(tex, uv).r;\n"
|
||||||
" int zero_count = 0;\n"
|
" int zero_count = 0;\n"
|
||||||
" if (textureOffset(tex, uv, ivec2(-1, -1)).r == 1.0) zero_count++;\n"
|
" if (textureOffset(tex, uv, ivec2(-1, -1)).r > 0.99) zero_count++;\n"
|
||||||
" if (textureOffset(tex, uv, ivec2(-1, 0)).r == 1.0) zero_count++;\n"
|
" if (textureOffset(tex, uv, ivec2(-1, 0)).r > 0.99) zero_count++;\n"
|
||||||
" if (textureOffset(tex, uv, ivec2(-1, +1)).r == 1.0) zero_count++;\n"
|
" if (textureOffset(tex, uv, ivec2(-1, +1)).r > 0.99) zero_count++;\n"
|
||||||
" if (textureOffset(tex, uv, ivec2( 0, -1)).r == 1.0) zero_count++;\n"
|
" if (textureOffset(tex, uv, ivec2( 0, -1)).r > 0.99) zero_count++;\n"
|
||||||
" if (textureOffset(tex, uv, ivec2( 0, 0)).r == 1.0) zero_count++;\n"
|
" if (textureOffset(tex, uv, ivec2( 0, 0)).r > 0.99) zero_count++;\n"
|
||||||
" if (textureOffset(tex, uv, ivec2( 0, +1)).r == 1.0) zero_count++;\n"
|
" if (textureOffset(tex, uv, ivec2( 0, +1)).r > 0.99) zero_count++;\n"
|
||||||
" if (textureOffset(tex, uv, ivec2(+1, -1)).r == 1.0) zero_count++;\n"
|
" if (textureOffset(tex, uv, ivec2(+1, -1)).r > 0.99) zero_count++;\n"
|
||||||
" if (textureOffset(tex, uv, ivec2(+1, 0)).r == 1.0) zero_count++;\n"
|
" if (textureOffset(tex, uv, ivec2(+1, 0)).r > 0.99) zero_count++;\n"
|
||||||
" if (textureOffset(tex, uv, ivec2(+1, +1)).r == 1.0) zero_count++;\n"
|
" if (textureOffset(tex, uv, ivec2(+1, +1)).r > 0.99) zero_count++;\n"
|
||||||
" mediump float edge = (zero_count > 1 && zero_count < 9) ? 0.75 : 0.0;\n"
|
" mediump float edge = (zero_count > 1 && zero_count < 9) ? 0.75 : 0.0;\n"
|
||||||
" frag = vec4(col.rgb, edge * (1.0 - float(zero_count) / 9.f));\n"
|
" frag = vec4(col.rgb, edge * (1.0 - float(zero_count) / 9.f));\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
|
|||||||
104
src/canvas.cpp
104
src/canvas.cpp
@@ -1334,7 +1334,7 @@ void Canvas::export_equirectangular_thread(std::string file_path)
|
|||||||
face.bind();
|
face.bind();
|
||||||
// copy the framebuffer before clearing to white
|
// copy the framebuffer before clearing to white
|
||||||
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, m_width, m_height);
|
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, m_width, m_height);
|
||||||
m_tmp[i].clear({ 1, 1, 1, 1 });
|
m_tmp[i].clear({ 1, 1, 1, 0 });
|
||||||
m_plane.draw_fill();
|
m_plane.draw_fill();
|
||||||
face.unbind();
|
face.unbind();
|
||||||
|
|
||||||
@@ -1402,10 +1402,10 @@ void Canvas::export_equirectangular_thread(std::string file_path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
LOG("writing %s", file_path.c_str());
|
LOG("writing %s", file_path.c_str());
|
||||||
jpge::params params;
|
if (file_path.substr(file_path.size() - 4) == ".jpg")
|
||||||
params.m_quality = 100;
|
stbi_write_jpg(file_path.c_str(), m_latlong.getWidth(), m_latlong.getHeight(), 4, latlong_data.get(), 100);
|
||||||
bool saved = jpge::compress_image_to_jpeg_file(file_path.c_str(), m_latlong.getWidth(), m_latlong.getHeight(), 4, latlong_data.get(), params);
|
else if (file_path.substr(file_path.size() - 4) == ".png")
|
||||||
inject_xmp(file_path.c_str());
|
stbi_write_png(file_path.c_str(), m_latlong.getWidth(), m_latlong.getHeight(), 4, latlong_data.get(), 0);
|
||||||
|
|
||||||
{
|
{
|
||||||
progress++;
|
progress++;
|
||||||
@@ -1503,10 +1503,21 @@ void Canvas::inject_xmp(std::string jpg_path)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Canvas::export_anim()
|
void Canvas::export_layers(std::string file_name, std::function<void()> on_complete)
|
||||||
|
{
|
||||||
|
if (App::I.check_license())
|
||||||
|
{
|
||||||
|
std::thread t([=] {
|
||||||
|
export_layers_thread(file_name);
|
||||||
|
if (on_complete)
|
||||||
|
on_complete();
|
||||||
|
});
|
||||||
|
t.detach();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Canvas::export_layers_thread(std::string file_name)
|
||||||
{
|
{
|
||||||
if (!App::I.check_license())
|
|
||||||
return;
|
|
||||||
// save viewport and clear color states
|
// save viewport and clear color states
|
||||||
GLint vp[4];
|
GLint vp[4];
|
||||||
GLfloat cc[4];
|
GLfloat cc[4];
|
||||||
@@ -1514,6 +1525,24 @@ void Canvas::export_anim()
|
|||||||
glGetFloatv(GL_COLOR_CLEAR_VALUE, cc);
|
glGetFloatv(GL_COLOR_CLEAR_VALUE, cc);
|
||||||
GLboolean blend = glIsEnabled(GL_BLEND);
|
GLboolean blend = glIsEnabled(GL_BLEND);
|
||||||
|
|
||||||
|
gl_state gl;
|
||||||
|
App::I.async_start();
|
||||||
|
std::shared_ptr<NodeProgressBar> pb;
|
||||||
|
if (App::I.layout.m_loaded)
|
||||||
|
{
|
||||||
|
pb = std::make_shared<NodeProgressBar>();
|
||||||
|
pb->m_manager = &App::I.layout;
|
||||||
|
pb->init();
|
||||||
|
pb->create();
|
||||||
|
pb->loaded();
|
||||||
|
pb->m_progress->SetWidthP(0);
|
||||||
|
pb->m_title->set_text("Export Pano Layers");
|
||||||
|
App::I.layout[App::I.main_id]->add_child(pb);
|
||||||
|
App::I.async_update();
|
||||||
|
}
|
||||||
|
int progress = 0;
|
||||||
|
int total = (m_order.size() + 1) * 6;
|
||||||
|
|
||||||
// prepare common states
|
// prepare common states
|
||||||
glViewport(0, 0, m_width, m_height);
|
glViewport(0, 0, m_width, m_height);
|
||||||
|
|
||||||
@@ -1540,20 +1569,21 @@ void Canvas::export_anim()
|
|||||||
glViewport(0, 0, m_width, m_height);
|
glViewport(0, 0, m_width, m_height);
|
||||||
for (int i = 0; i < 6; i++)
|
for (int i = 0; i < 6; i++)
|
||||||
{
|
{
|
||||||
|
glEnable(GL_BLEND);
|
||||||
m_tmp[i].bindFramebuffer();
|
m_tmp[i].bindFramebuffer();
|
||||||
|
|
||||||
if (seq == 0)
|
//if (seq == 0)
|
||||||
{
|
//{
|
||||||
m_tmp[i].clear({ 1, 1, 1, 1 });
|
// m_tmp[i].clear({ 1, 1, 1, 1 });
|
||||||
ShaderManager::use(kShader::Checkerboard);
|
// ShaderManager::use(kShader::Checkerboard);
|
||||||
ShaderManager::u_mat4(kShaderUniform::MVP, glm::ortho(-.5f, .5f, -.5f, .5f, -1.f, 1.f));
|
// ShaderManager::u_mat4(kShaderUniform::MVP, glm::ortho(-.5f, .5f, -.5f, .5f, -1.f, 1.f));
|
||||||
m_plane.draw_fill();
|
// m_plane.draw_fill();
|
||||||
glEnable(GL_BLEND);
|
// glEnable(GL_BLEND);
|
||||||
}
|
//}
|
||||||
else
|
//else
|
||||||
{
|
{
|
||||||
m_tmp[i].clear({ 1, 1, 1, 0 });
|
m_tmp[i].clear({ 1, 1, 1, 0 });
|
||||||
glDisable(GL_BLEND);
|
//glDisable(GL_BLEND);
|
||||||
}
|
}
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
@@ -1575,6 +1605,18 @@ void Canvas::export_anim()
|
|||||||
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
|
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
|
||||||
|
|
||||||
m_tmp[i].unbindFramebuffer();
|
m_tmp[i].unbindFramebuffer();
|
||||||
|
|
||||||
|
progress++;
|
||||||
|
float p = (float)progress / total * 100.f;
|
||||||
|
LOG("progress: %f", p);
|
||||||
|
|
||||||
|
if (App::I.layout.m_loaded)
|
||||||
|
{
|
||||||
|
pb->m_progress->SetWidthP(p);
|
||||||
|
gl.save();
|
||||||
|
App::I.async_update();
|
||||||
|
gl.restore();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1596,19 +1638,37 @@ void Canvas::export_anim()
|
|||||||
auto latlong_data = std::make_unique<uint8_t[]>(m_latlong.bytes());
|
auto latlong_data = std::make_unique<uint8_t[]>(m_latlong.bytes());
|
||||||
m_latlong.readTextureData(latlong_data.get());
|
m_latlong.readTextureData(latlong_data.get());
|
||||||
static char name[128];
|
static char name[128];
|
||||||
sprintf(name, "%s/latlong-frame%02d.png", App::I.work_path.c_str(), seq);
|
sprintf(name, "%s/%s-layer-%02d.png", App::I.work_path.c_str(), file_name.c_str(), seq);
|
||||||
seq++;
|
seq++;
|
||||||
LOG("writing %s", name);
|
LOG("writing %s", name);
|
||||||
|
App::I.async_end();
|
||||||
int ret = stbi_write_png(name, m_latlong.getWidth(), m_latlong.getHeight(), 4, latlong_data.get(), m_latlong.stride());
|
int ret = stbi_write_png(name, m_latlong.getWidth(), m_latlong.getHeight(), 4, latlong_data.get(), m_latlong.stride());
|
||||||
//jpge::params params;
|
App::I.async_start();
|
||||||
//params.m_quality = 100;
|
}
|
||||||
//bool saved = jpge::compress_image_to_jpeg_file(name, m_latlong.getWidth(), m_latlong.getHeight(), 4, latlong_data.get(), params);
|
|
||||||
|
progress++;
|
||||||
|
float p = (float)progress / total * 100.f;
|
||||||
|
LOG("progress: %f", p);
|
||||||
|
|
||||||
|
if (App::I.layout.m_loaded)
|
||||||
|
{
|
||||||
|
pb->m_progress->SetWidthP(p);
|
||||||
|
gl.save();
|
||||||
|
App::I.async_update();
|
||||||
|
gl.restore();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
glDeleteTextures(1, &cube_id);
|
glDeleteTextures(1, &cube_id);
|
||||||
m_latlong.destroy();
|
m_latlong.destroy();
|
||||||
|
|
||||||
|
if (App::I.layout.m_loaded)
|
||||||
|
{
|
||||||
|
pb->destroy();
|
||||||
|
App::I.async_update();
|
||||||
|
}
|
||||||
|
App::I.async_end();
|
||||||
|
|
||||||
// restore viewport and clear color states
|
// restore viewport and clear color states
|
||||||
blend ? glEnable(GL_BLEND) : glDisable(GL_BLEND);
|
blend ? glEnable(GL_BLEND) : glDisable(GL_BLEND);
|
||||||
glViewport(vp[0], vp[1], vp[2], vp[3]);
|
glViewport(vp[0], vp[1], vp[2], vp[3]);
|
||||||
|
|||||||
@@ -242,7 +242,8 @@ public:
|
|||||||
void import_equirectangular_thread(std::string file_path);
|
void import_equirectangular_thread(std::string file_path);
|
||||||
void export_equirectangular(std::string file_path, std::function<void()> on_complete = nullptr);
|
void export_equirectangular(std::string file_path, std::function<void()> on_complete = nullptr);
|
||||||
void export_equirectangular_thread(std::string file_path);
|
void export_equirectangular_thread(std::string file_path);
|
||||||
void export_anim();
|
void export_layers(std::string file_name, std::function<void()> on_complete = nullptr);
|
||||||
|
void export_layers_thread(std::string file_name);
|
||||||
void export_cubes();
|
void export_cubes();
|
||||||
void project_save(std::function<void(bool)> on_complete = nullptr);
|
void project_save(std::function<void(bool)> on_complete = nullptr);
|
||||||
void project_save(std::string file_path, std::function<void(bool)> on_complete = nullptr);
|
void project_save(std::string file_path, std::function<void(bool)> on_complete = nullptr);
|
||||||
|
|||||||
@@ -59,6 +59,18 @@ void Image::flip()
|
|||||||
std::swap(m_data, flipped);
|
std::swap(m_data, flipped);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Image::gayscale_alpha()
|
||||||
|
{
|
||||||
|
int np = width * height;
|
||||||
|
auto ptr = reinterpret_cast<glm::u8vec4*>(m_data.get());
|
||||||
|
for (int i = 0; i < np; i++)
|
||||||
|
{
|
||||||
|
auto& c = ptr[i];
|
||||||
|
c.g = c.b = c.r = 255 - c.a;
|
||||||
|
c.a = 255;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Image Image::resize(int w, int h) const
|
Image Image::resize(int w, int h) const
|
||||||
{
|
{
|
||||||
Image ret;
|
Image ret;
|
||||||
@@ -90,3 +102,50 @@ Image Image::resize(int w, int h) const
|
|||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Image Image::resize_power2() const
|
||||||
|
{
|
||||||
|
int w = pow(2, ceil(log(width) / log(2)));
|
||||||
|
int h = pow(2, ceil(log(height) / log(2)));
|
||||||
|
if (w == width && h == height)
|
||||||
|
{
|
||||||
|
Image i;
|
||||||
|
i.create(width, height);
|
||||||
|
std::copy(m_data.get(), m_data.get() + width * height * comp, i.m_data.get());
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return resize(w, h);
|
||||||
|
}
|
||||||
|
|
||||||
|
Image Image::resize_squared() const
|
||||||
|
{
|
||||||
|
Image ret;
|
||||||
|
if (width == height)
|
||||||
|
{
|
||||||
|
ret.create(width, height);
|
||||||
|
std::copy(m_data.get(), m_data.get() + width * height * comp, ret.m_data.get());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int pad_x = 0;
|
||||||
|
int pad_y = 0;
|
||||||
|
int size = 0;
|
||||||
|
if (height > width)
|
||||||
|
{
|
||||||
|
size = height;
|
||||||
|
pad_x = (size - width) / 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
size = width;
|
||||||
|
pad_y = (size - height) / 2;
|
||||||
|
}
|
||||||
|
ret.create(size, size);
|
||||||
|
auto ptr_src = reinterpret_cast<glm::u8vec4*>(m_data.get());
|
||||||
|
auto ptr_dst = reinterpret_cast<glm::u8vec4*>(ret.m_data.get());
|
||||||
|
std::fill_n(ptr_dst, size * size, glm::u8vec4(0));
|
||||||
|
for (int y = 0; y < height; y++)
|
||||||
|
std::copy_n(ptr_src + y * width, width, ptr_dst + pad_x + (y + pad_y) * ret.width);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|||||||
@@ -31,6 +31,10 @@ public:
|
|||||||
m_data.reset();
|
m_data.reset();
|
||||||
}
|
}
|
||||||
void flip();
|
void flip();
|
||||||
|
// convert to grayscale and set opaque
|
||||||
|
void gayscale_alpha();
|
||||||
void create() { m_data = std::make_unique<uint8_t[]>(size()); }
|
void create() { m_data = std::make_unique<uint8_t[]>(size()); }
|
||||||
Image resize(int w, int h) const;
|
Image resize(int w, int h) const;
|
||||||
|
Image resize_power2() const;
|
||||||
|
Image resize_squared() const;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -65,9 +65,14 @@ void NodePanelBrush::init()
|
|||||||
|
|
||||||
std::string path_high = App::I.data_path + "/brushes/" + name + ".png";
|
std::string path_high = App::I.data_path + "/brushes/" + name + ".png";
|
||||||
std::string path_thumb = App::I.data_path + "/brushes/thumbs/" + name + ".png";
|
std::string path_thumb = App::I.data_path + "/brushes/thumbs/" + name + ".png";
|
||||||
|
|
||||||
|
img = img.resize_squared();
|
||||||
|
img.gayscale_alpha();
|
||||||
|
|
||||||
auto thumb = img.resize(64, 64);
|
auto thumb = img.resize(64, 64);
|
||||||
thumb.save(path_thumb);
|
thumb.save(path_thumb);
|
||||||
img.save(path_high);
|
auto po2 = img.resize_power2();
|
||||||
|
po2.save(path_high);
|
||||||
|
|
||||||
async_start();
|
async_start();
|
||||||
NodeButtonBrush* brush = new NodeButtonBrush;
|
NodeButtonBrush* brush = new NodeButtonBrush;
|
||||||
@@ -75,7 +80,7 @@ void NodePanelBrush::init()
|
|||||||
brush->init();
|
brush->init();
|
||||||
brush->create();
|
brush->create();
|
||||||
brush->loaded();
|
brush->loaded();
|
||||||
brush->set_icon(path.c_str());
|
brush->set_icon(path_thumb.c_str());
|
||||||
brush->thumb_path = path_thumb;
|
brush->thumb_path = path_thumb;
|
||||||
brush->high_path = path_high;
|
brush->high_path = path_high;
|
||||||
brush->brush_name = name;
|
brush->brush_name = name;
|
||||||
|
|||||||
Reference in New Issue
Block a user