add tick and on_tick event, fix unsaved document prompt, implement TextInput blinking cursor
This commit is contained in:
@@ -179,11 +179,16 @@ static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTime
|
|||||||
working_list.front()();
|
working_list.front()();
|
||||||
working_list.pop_front();
|
working_list.pop_front();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double dt = now - _prevTime;
|
||||||
|
|
||||||
|
if (dt > 0.1)
|
||||||
|
App::I.redraw = true;
|
||||||
|
|
||||||
if (App::I.redraw)
|
if (App::I.redraw)
|
||||||
{
|
{
|
||||||
App::I.clear();
|
App::I.clear();
|
||||||
App::I.update(now - _prevTime);
|
App::I.update(dt);
|
||||||
CGLFlushDrawable([glctx CGLContextObj]);
|
CGLFlushDrawable([glctx CGLContextObj]);
|
||||||
_prevTime = now;
|
_prevTime = now;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -452,6 +452,10 @@
|
|||||||
<scroll id="files-list" dir="row" wrap="1" flood-events="1" grow="1" height="100%" margin="0 0 0 0" pad="0 20 0 0" color=".2 .2 .2 1">
|
<scroll id="files-list" dir="row" wrap="1" flood-events="1" grow="1" height="100%" margin="0 0 0 0" pad="0 20 0 0" color=".2 .2 .2 1">
|
||||||
</scroll>
|
</scroll>
|
||||||
</border>
|
</border>
|
||||||
|
<node dir="row">
|
||||||
|
<node grow="1"><text os="win,osx" id="path" text="Workind dir: path" text-wrap-width="470" font-face="arial" font-size="11" margin="10 5 10 10"/></node>
|
||||||
|
<button id="btn-path" text="Set destination dir" width="140" height="30" margin="0 10 0 0"/>
|
||||||
|
</node>
|
||||||
<node id="footer" height="40" dir="row" align="flex-end" justify="flex-end" pad="10">
|
<node id="footer" height="40" dir="row" align="flex-end" justify="flex-end" pad="10">
|
||||||
<node grow="1"><button id="btn-delete" text="Delete Project" width="100" height="30" margin="0 10 0 0" color="1 0 0 1"/></node>
|
<node grow="1"><button id="btn-delete" text="Delete Project" width="100" height="30" margin="0 10 0 0" color="1 0 0 1"/></node>
|
||||||
<button id="btn-ok" text="Open Project" width="100" height="30" margin="0 10 0 0"/>
|
<button id="btn-ok" text="Open Project" width="100" height="30" margin="0 10 0 0"/>
|
||||||
@@ -481,7 +485,7 @@
|
|||||||
</scroll>
|
</scroll>
|
||||||
</border>
|
</border>
|
||||||
<node id="footer" height="40" dir="row" align="flex-end" justify="flex-end" pad="10">
|
<node id="footer" height="40" dir="row" align="flex-end" justify="flex-end" pad="10">
|
||||||
<node grow="1"/>
|
<node grow="1" os="win,osx"><button id="btn-path" text="Set destination dir" width="120" height="30" margin="0 10 0 0"/></node>
|
||||||
<button id="btn-ok" text="Open Project" width="100" height="30" margin="0 10 0 0"/>
|
<button id="btn-ok" text="Open Project" width="100" height="30" margin="0 10 0 0"/>
|
||||||
<button id="btn-cancel" text="Cancel" width="60" height="30"/>
|
<button id="btn-cancel" text="Cancel" width="60" height="30"/>
|
||||||
</node>
|
</node>
|
||||||
@@ -537,7 +541,9 @@
|
|||||||
<text text="Project name: " font-face="arial" font-size="11" margin="0 5 0 5"/>
|
<text text="Project name: " font-face="arial" font-size="11" margin="0 5 0 5"/>
|
||||||
<text-input id="txt-input" justify="center" pad="5" grow="1" height="30" color=".3"/>
|
<text-input id="txt-input" justify="center" pad="5" grow="1" height="30" color=".3"/>
|
||||||
</border>
|
</border>
|
||||||
|
<text os="win,osx" id="path" text="Workind dir: path" text-wrap-width="470" font-face="arial" font-size="11" margin="10 5 10 5"/>
|
||||||
<node height="40" grow="1" dir="row" align="flex-end" justify="flex-end">
|
<node height="40" grow="1" dir="row" align="flex-end" justify="flex-end">
|
||||||
|
<node grow="1" os="win,osx"><button id="btn-path" text="Set working dir" width="120" height="30" margin="0 10 0 0"/></node>
|
||||||
<button id="btn-ok" text="Save Project" width="100" height="30" margin="0 10 0 0"/>
|
<button id="btn-ok" text="Save Project" width="100" height="30" margin="0 10 0 0"/>
|
||||||
<button id="btn-cancel" text="Cancel" width="60" height="30"/>
|
<button id="btn-cancel" text="Cancel" width="60" height="30"/>
|
||||||
</node>
|
</node>
|
||||||
@@ -557,7 +563,7 @@
|
|||||||
<text text="Note: resolution is measured in pixels per each face of the cube.\nThe output equirectangular will be Resolution x 4 times.\nExample: 1024px will generate a 4096x2048 equirectangular image." font-face="arial" font-size="11" margin="0 5 10 5"/>
|
<text text="Note: resolution is measured in pixels per each face of the cube.\nThe output equirectangular will be Resolution x 4 times.\nExample: 1024px will generate a 4096x2048 equirectangular image." font-face="arial" font-size="11" margin="0 5 10 5"/>
|
||||||
<border dir="row" align="center" height="30" color=".2 .2 .2 1">
|
<border dir="row" align="center" height="30" color=".2 .2 .2 1">
|
||||||
<text text="Project name: " font-face="arial" font-size="11" margin="0 5 0 5"/>
|
<text text="Project name: " font-face="arial" font-size="11" margin="0 5 0 5"/>
|
||||||
<text-input id="txt-input" justify="center" pad="5" grow="1" height="30" color=".3"/>
|
<text-input id="txt-input" align="center" pad="5" grow="1" height="30" color=".3"/>
|
||||||
<combobox id="resolution" width="100" height="30" text="1024" combo-list="512px,1024px,1536px,2048px" default="1"/>
|
<combobox id="resolution" width="100" height="30" text="1024" combo-list="512px,1024px,1536px,2048px" default="1"/>
|
||||||
</border>
|
</border>
|
||||||
<text os="win,osx" id="path" text="Workind dir: path" text-wrap-width="470" font-face="arial" font-size="11" margin="10 5 10 5"/>
|
<text os="win,osx" id="path" text="Workind dir: path" text-wrap-width="470" font-face="arial" font-size="11" margin="10 5 10 5"/>
|
||||||
|
|||||||
@@ -442,6 +442,8 @@ void App::update(float dt)
|
|||||||
if (canvas && canvas->m_canvas)
|
if (canvas && canvas->m_canvas)
|
||||||
canvas->m_canvas->stroke_draw();
|
canvas->m_canvas->stroke_draw();
|
||||||
|
|
||||||
|
layout[main_id]->tick(dt);
|
||||||
|
|
||||||
if (!(redraw || animate))
|
if (!(redraw || animate))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|||||||
@@ -92,6 +92,12 @@ void App::dialog_newdoc()
|
|||||||
std::string name = dialog->input->m_string;
|
std::string name = dialog->input->m_string;
|
||||||
std::string path = work_path + "/" + name + ".ppi";
|
std::string path = work_path + "/" + name + ".ppi";
|
||||||
|
|
||||||
|
if (name.empty())
|
||||||
|
{
|
||||||
|
message_box("Warning", "You need to specify a name to file.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto action = [this, dialog, name, path] {
|
auto action = [this, dialog, name, path] {
|
||||||
std::array<int, 4> resolutions{ 512, 1024, 1536, 2048 };
|
std::array<int, 4> resolutions{ 512, 1024, 1536, 2048 };
|
||||||
int res = resolutions[dialog->m_resolution->m_current_index];
|
int res = resolutions[dialog->m_resolution->m_current_index];
|
||||||
@@ -110,6 +116,8 @@ void App::dialog_newdoc()
|
|||||||
canvas->m_canvas->layer_add("Default");
|
canvas->m_canvas->layer_add("Default");
|
||||||
layers->add_layer("Default");
|
layers->add_layer("Default");
|
||||||
|
|
||||||
|
canvas->m_canvas->m_unsaved = true;
|
||||||
|
canvas->m_canvas->m_newdoc = false;
|
||||||
title_update();
|
title_update();
|
||||||
|
|
||||||
dialog->destroy();
|
dialog->destroy();
|
||||||
@@ -154,8 +162,11 @@ void App::dialog_newdoc()
|
|||||||
m->btn_ok->m_text->set_text("Yes");
|
m->btn_ok->m_text->set_text("Yes");
|
||||||
m->btn_cancel->m_text->set_text("No");
|
m->btn_cancel->m_text->set_text("No");
|
||||||
m->btn_ok->on_click = [this, m, show_dialog](Node*) {
|
m->btn_ok->on_click = [this, m, show_dialog](Node*) {
|
||||||
ui::Canvas::I->project_save([this, m, show_dialog] {
|
ui::Canvas::I->project_save([this, m, show_dialog](bool success){
|
||||||
show_dialog();
|
if (success)
|
||||||
|
show_dialog();
|
||||||
|
else
|
||||||
|
message_box("Saving Error", "There was a problem saving the document");
|
||||||
});
|
});
|
||||||
m->destroy();
|
m->destroy();
|
||||||
};
|
};
|
||||||
@@ -215,8 +226,11 @@ void App::dialog_open()
|
|||||||
m->btn_ok->m_text->set_text("Yes");
|
m->btn_ok->m_text->set_text("Yes");
|
||||||
m->btn_cancel->m_text->set_text("No");
|
m->btn_cancel->m_text->set_text("No");
|
||||||
m->btn_ok->on_click = [this,m,show_dialog](Node*){
|
m->btn_ok->on_click = [this,m,show_dialog](Node*){
|
||||||
ui::Canvas::I->project_save([this,m,show_dialog] {
|
ui::Canvas::I->project_save([this,m,show_dialog](bool success){
|
||||||
show_dialog();
|
if (success)
|
||||||
|
show_dialog();
|
||||||
|
else
|
||||||
|
message_box("Saving Error", "There was a problem saving the document");
|
||||||
});
|
});
|
||||||
m->destroy();
|
m->destroy();
|
||||||
};
|
};
|
||||||
@@ -268,8 +282,11 @@ void App::dialog_browse()
|
|||||||
m->btn_ok->m_text->set_text("Yes");
|
m->btn_ok->m_text->set_text("Yes");
|
||||||
m->btn_cancel->m_text->set_text("No");
|
m->btn_cancel->m_text->set_text("No");
|
||||||
m->btn_ok->on_click = [this, m, show_dialog](Node*) {
|
m->btn_ok->on_click = [this, m, show_dialog](Node*) {
|
||||||
ui::Canvas::I->project_save([this, m, show_dialog] {
|
ui::Canvas::I->project_save([this, m, show_dialog](bool success){
|
||||||
show_dialog();
|
if (success)
|
||||||
|
show_dialog();
|
||||||
|
else
|
||||||
|
message_box("Saving Error", "There was a problem saving the document");
|
||||||
});
|
});
|
||||||
m->destroy();
|
m->destroy();
|
||||||
};
|
};
|
||||||
@@ -335,21 +352,16 @@ void App::dialog_save()
|
|||||||
|
|
||||||
if (name.empty())
|
if (name.empty())
|
||||||
{
|
{
|
||||||
auto msgbox = new NodeMessageBox();
|
message_box("Warning", "You need to specify a name to file.");
|
||||||
msgbox->m_manager = &layout;
|
|
||||||
msgbox->init();
|
|
||||||
msgbox->m_title->set_text("Warning");
|
|
||||||
msgbox->m_message->set_text("You need to specify a name to file.");
|
|
||||||
layout[main_id]->add_child(msgbox);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto action = [this, dialog, name, path] {
|
auto action = [this, dialog, name, path] {
|
||||||
|
canvas->m_canvas->project_save(path);
|
||||||
doc_name = name;
|
doc_name = name;
|
||||||
doc_path = path;
|
doc_path = path;
|
||||||
doc_dir = work_path;
|
doc_dir = work_path;
|
||||||
title_update();
|
title_update();
|
||||||
canvas->m_canvas->project_save(path);
|
|
||||||
dialog->destroy();
|
dialog->destroy();
|
||||||
App::I.hideKeyboard();
|
App::I.hideKeyboard();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -205,7 +205,7 @@ void ui::Stroke::add_point(glm::vec2 pos, float pressure)
|
|||||||
{
|
{
|
||||||
#ifdef __IOS__
|
#ifdef __IOS__
|
||||||
m_curve = glm::min(m_curve + 0.1f, 1.f);
|
m_curve = glm::min(m_curve + 0.1f, 1.f);
|
||||||
pressure = pressure * glm::pow(m_curve, 2.f);
|
//pressure = pressure * glm::pow(m_curve, 2.f);
|
||||||
#endif // __IOS__
|
#endif // __IOS__
|
||||||
m_pressure_buff.add(pressure);
|
m_pressure_buff.add(pressure);
|
||||||
pressure = m_pressure_buff.average();
|
pressure = m_pressure_buff.average();
|
||||||
|
|||||||
@@ -1497,39 +1497,39 @@ void ui::Canvas::export_cubes()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void ui::Canvas::project_save(std::function<void()> on_complete)
|
void ui::Canvas::project_save(std::function<void(bool)> on_complete)
|
||||||
{
|
{
|
||||||
if (App::I.check_license())
|
if (App::I.check_license())
|
||||||
{
|
{
|
||||||
std::thread t([=] {
|
std::thread t([=] {
|
||||||
project_save_thread(App::I.doc_path);
|
bool ret = project_save_thread(App::I.doc_path);
|
||||||
if (on_complete)
|
if (on_complete)
|
||||||
on_complete();
|
on_complete(ret);
|
||||||
});
|
});
|
||||||
t.detach();
|
t.detach();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ui::Canvas::project_save(std::string file_path, std::function<void()> on_complete)
|
void ui::Canvas::project_save(std::string file_path, std::function<void(bool)> on_complete)
|
||||||
{
|
{
|
||||||
if (App::I.check_license())
|
if (App::I.check_license())
|
||||||
{
|
{
|
||||||
std::thread t([=] {
|
std::thread t([=] {
|
||||||
project_save_thread(file_path);
|
bool ret = project_save_thread(file_path);
|
||||||
if (on_complete)
|
if (on_complete)
|
||||||
on_complete();
|
on_complete(ret);
|
||||||
});
|
});
|
||||||
t.detach();
|
t.detach();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ui::Canvas::project_save_thread(std::string file_path)
|
bool ui::Canvas::project_save_thread(std::string file_path)
|
||||||
{
|
{
|
||||||
gl_state gl;
|
gl_state gl;
|
||||||
|
|
||||||
// already saved, nothing to do
|
// already saved, nothing to do
|
||||||
if (!m_unsaved)
|
if (!m_unsaved && file_path == App::I.doc_path)
|
||||||
return;
|
return true;
|
||||||
|
|
||||||
// static char name[128];
|
// static char name[128];
|
||||||
// sprintf(name, "%s/latlong.ppi", data_path.c_str());
|
// sprintf(name, "%s/latlong.ppi", data_path.c_str());
|
||||||
@@ -1549,7 +1549,6 @@ void ui::Canvas::project_save_thread(std::string file_path)
|
|||||||
if (!(fp = fopen(tmp_path.c_str(), "wb")))
|
if (!(fp = fopen(tmp_path.c_str(), "wb")))
|
||||||
{
|
{
|
||||||
LOG("cannot write tmp project to %s", tmp_path.c_str());
|
LOG("cannot write tmp project to %s", tmp_path.c_str());
|
||||||
//return;
|
|
||||||
use_tmp = false;
|
use_tmp = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1560,7 +1559,7 @@ void ui::Canvas::project_save_thread(std::string file_path)
|
|||||||
if (!(fp = fopen(file_path.c_str(), "wb")))
|
if (!(fp = fopen(file_path.c_str(), "wb")))
|
||||||
{
|
{
|
||||||
LOG("cannot write project to %s", file_path.c_str());
|
LOG("cannot write project to %s", file_path.c_str());
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
LOG("unsafe mode saving directly to %s", file_path.c_str());
|
LOG("unsafe mode saving directly to %s", file_path.c_str());
|
||||||
}
|
}
|
||||||
@@ -1644,6 +1643,7 @@ void ui::Canvas::project_save_thread(std::string file_path)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
bool success = false;
|
||||||
if (use_tmp)
|
if (use_tmp)
|
||||||
{
|
{
|
||||||
LOG("project saved tmp to %s", tmp_path.c_str());
|
LOG("project saved tmp to %s", tmp_path.c_str());
|
||||||
@@ -1652,31 +1652,40 @@ void ui::Canvas::project_save_thread(std::string file_path)
|
|||||||
{
|
{
|
||||||
if (std::rename(tmp_path.c_str(), file_path.c_str()) == 0)
|
if (std::rename(tmp_path.c_str(), file_path.c_str()) == 0)
|
||||||
{
|
{
|
||||||
|
success = true;
|
||||||
LOG("tmp file swapped succesfully");
|
LOG("tmp file swapped succesfully");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
success = false;
|
||||||
LOG("tmp file NOT swapped, original removed");
|
LOG("tmp file NOT swapped, original removed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
success = false;
|
||||||
LOG("could not remove %s", file_path.c_str());
|
LOG("could not remove %s", file_path.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
success = true;
|
||||||
LOG("project saved to %s", file_path.c_str());
|
LOG("project saved to %s", file_path.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
m_unsaved = false;
|
if (success)
|
||||||
m_newdoc = false;
|
{
|
||||||
|
m_unsaved = false;
|
||||||
|
m_newdoc = false;
|
||||||
|
}
|
||||||
|
|
||||||
App::I.async_start();
|
App::I.async_start();
|
||||||
pb->destroy();
|
pb->destroy();
|
||||||
App::I.title_update();
|
App::I.title_update();
|
||||||
App::I.async_update();
|
App::I.async_update();
|
||||||
App::I.async_end();
|
App::I.async_end();
|
||||||
|
|
||||||
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ui::Canvas::project_open(std::string file_path, std::function<void(bool)> on_complete)
|
void ui::Canvas::project_open(std::string file_path, std::function<void(bool)> on_complete)
|
||||||
|
|||||||
@@ -213,9 +213,9 @@ public:
|
|||||||
void export_equirectangular_thread(std::string file_path);
|
void export_equirectangular_thread(std::string file_path);
|
||||||
void export_anim();
|
void export_anim();
|
||||||
void export_cubes();
|
void export_cubes();
|
||||||
void project_save(std::function<void()> on_complete = nullptr);
|
void project_save(std::function<void(bool)> on_complete = nullptr);
|
||||||
void project_save(std::string file_path, std::function<void()> on_complete = nullptr);
|
void project_save(std::string file_path, std::function<void(bool)> on_complete = nullptr);
|
||||||
void project_save_thread(std::string file_path);
|
bool project_save_thread(std::string file_path);
|
||||||
void project_open(std::string file_path, std::function<void(bool)> on_complete = nullptr);
|
void project_open(std::string file_path, std::function<void(bool)> on_complete = nullptr);
|
||||||
bool project_open_thread(std::string file_path);
|
bool project_open_thread(std::string file_path);
|
||||||
void inject_xmp(std::string jpg_path);
|
void inject_xmp(std::string jpg_path);
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ enum class kKey : uint8_t
|
|||||||
KeyCtrl,
|
KeyCtrl,
|
||||||
KeyShift,
|
KeyShift,
|
||||||
KeyTab,
|
KeyTab,
|
||||||
|
KeyEnter,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class kEventResult : uint8_t
|
enum class kEventResult : uint8_t
|
||||||
|
|||||||
@@ -188,7 +188,7 @@ kKey convert_key(int key)
|
|||||||
CASE(kVK_ANSI_Keypad7, kKey::Unknown);
|
CASE(kVK_ANSI_Keypad7, kKey::Unknown);
|
||||||
CASE(kVK_ANSI_Keypad8, kKey::Unknown);
|
CASE(kVK_ANSI_Keypad8, kKey::Unknown);
|
||||||
CASE(kVK_ANSI_Keypad9, kKey::Unknown);
|
CASE(kVK_ANSI_Keypad9, kKey::Unknown);
|
||||||
CASE(kVK_Return, kKey::Unknown);
|
CASE(kVK_Return, kKey::KeyEnter);
|
||||||
CASE(kVK_Tab, kKey::KeyTab);
|
CASE(kVK_Tab, kKey::KeyTab);
|
||||||
CASE(kVK_Space, kKey::Unknown);
|
CASE(kVK_Space, kKey::Unknown);
|
||||||
CASE(kVK_Delete, kKey::Unknown);
|
CASE(kVK_Delete, kKey::Unknown);
|
||||||
@@ -436,4 +436,4 @@ kKey convert_key(int key)
|
|||||||
default:
|
default:
|
||||||
return kKey::Unknown;
|
return kKey::Unknown;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
24
src/node.cpp
24
src/node.cpp
@@ -483,6 +483,23 @@ glm::vec4 Node::GetPadding() const
|
|||||||
return{ t, r, b, l };
|
return{ t, r, b, l };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Node::SetMargin(float t, float r, float b, float l)
|
||||||
|
{
|
||||||
|
YGNodeStyleSetMargin(y_node, YGEdgeTop, t);
|
||||||
|
YGNodeStyleSetMargin(y_node, YGEdgeRight, r);
|
||||||
|
YGNodeStyleSetMargin(y_node, YGEdgeBottom, b);
|
||||||
|
YGNodeStyleSetMargin(y_node, YGEdgeLeft, l);
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::vec4 Node::GetMargin() const
|
||||||
|
{
|
||||||
|
float t = YGNodeLayoutGetMargin(y_node, YGEdgeTop);
|
||||||
|
float r = YGNodeLayoutGetMargin(y_node, YGEdgeRight);
|
||||||
|
float b = YGNodeLayoutGetMargin(y_node, YGEdgeBottom);
|
||||||
|
float l = YGNodeLayoutGetMargin(y_node, YGEdgeLeft);
|
||||||
|
return{ t, r, b, l };
|
||||||
|
}
|
||||||
|
|
||||||
void Node::SetPosition(const glm::vec2 pos)
|
void Node::SetPosition(const glm::vec2 pos)
|
||||||
{
|
{
|
||||||
SetPosition(pos.x, pos.y);
|
SetPosition(pos.x, pos.y);
|
||||||
@@ -656,6 +673,13 @@ void Node::update_internal(const glm::vec2& origin, const glm::mat4& proj)
|
|||||||
c->update_internal(m_pos, proj);
|
c->update_internal(m_pos, proj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Node::tick(float dt)
|
||||||
|
{
|
||||||
|
for (auto& c : m_children)
|
||||||
|
c->tick(dt);
|
||||||
|
on_tick(dt);
|
||||||
|
}
|
||||||
|
|
||||||
void Node::parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* attr)
|
void Node::parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* attr)
|
||||||
{
|
{
|
||||||
switch (ka)
|
switch (ka)
|
||||||
|
|||||||
@@ -139,6 +139,8 @@ public:
|
|||||||
|
|
||||||
void SetPadding(float t, float r, float b, float l);
|
void SetPadding(float t, float r, float b, float l);
|
||||||
glm::vec4 GetPadding() const;
|
glm::vec4 GetPadding() const;
|
||||||
|
void SetMargin(float t, float r, float b, float l);
|
||||||
|
glm::vec4 GetMargin() const;
|
||||||
void SetPosition(float l, float t, float r, float b);
|
void SetPosition(float l, float t, float r, float b);
|
||||||
void SetPosition(float l, float t);
|
void SetPosition(float l, float t);
|
||||||
void SetPosition(const glm::vec2 pos);
|
void SetPosition(const glm::vec2 pos);
|
||||||
@@ -198,6 +200,7 @@ public:
|
|||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void on_tick(float dt) { };
|
||||||
virtual kEventResult on_event(Event* e);
|
virtual kEventResult on_event(Event* e);
|
||||||
virtual kEventResult handle_event(Event* e);
|
virtual kEventResult handle_event(Event* e);
|
||||||
virtual void handle_resize(glm::vec2 old_size, glm::vec2 new_size);;
|
virtual void handle_resize(glm::vec2 old_size, glm::vec2 new_size);;
|
||||||
@@ -207,6 +210,7 @@ public:
|
|||||||
virtual void added(Node* parent);
|
virtual void added(Node* parent);
|
||||||
virtual void removed(Node* parent);
|
virtual void removed(Node* parent);
|
||||||
const Node* init_template(const char* id);
|
const Node* init_template(const char* id);
|
||||||
|
void tick(float dt);
|
||||||
void async_start();
|
void async_start();
|
||||||
void async_update();
|
void async_update();
|
||||||
void async_end();
|
void async_end();
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include "node_image_texture.h"
|
#include "node_image_texture.h"
|
||||||
#include "asset.h"
|
#include "asset.h"
|
||||||
#include "node_message_box.h"
|
#include "node_message_box.h"
|
||||||
|
#include "node_text.h"
|
||||||
#include "app.h"
|
#include "app.h"
|
||||||
|
|
||||||
Node* NodeDialogBrowse::clone_instantiate() const
|
Node* NodeDialogBrowse::clone_instantiate() const
|
||||||
@@ -72,6 +73,47 @@ void NodeDialogBrowse::init_controls()
|
|||||||
root()->update();
|
root()->update();
|
||||||
};
|
};
|
||||||
container = find<Node>("files-list");
|
container = find<Node>("files-list");
|
||||||
|
init_list();
|
||||||
|
#if defined(_WIN32) || defined(__OSX__)
|
||||||
|
static char path_buffer[256];
|
||||||
|
btn_path = find<NodeButton>("btn-path");
|
||||||
|
btn_path->on_click = [this](Node*){
|
||||||
|
App::I.pick_dir([this](std::string path){
|
||||||
|
LOG("change working path to %s", path.c_str());
|
||||||
|
async_start();
|
||||||
|
App::I.work_path = path;
|
||||||
|
realpath(path.c_str(), path_buffer);
|
||||||
|
working_path->set_text_format("Destination dir: %s", path_buffer);
|
||||||
|
search_path = path;
|
||||||
|
clear_list();
|
||||||
|
init_list();
|
||||||
|
async_update();
|
||||||
|
async_end();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
working_path = find<NodeText>("path");
|
||||||
|
realpath(App::I.work_path.c_str(), path_buffer);
|
||||||
|
working_path->set_text_format("Working dir: %s", path_buffer);
|
||||||
|
#endif
|
||||||
|
// if (auto* first = (NodeDialogBrowseItem*)container->get_child_at(0))
|
||||||
|
// {
|
||||||
|
// first->on_selected(first);
|
||||||
|
// first->m_selected = true;
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
void NodeDialogBrowse::clear_list()
|
||||||
|
{
|
||||||
|
for (auto& n : container->m_children)
|
||||||
|
{
|
||||||
|
if (auto item = std::dynamic_pointer_cast<NodeDialogBrowseItem>(n))
|
||||||
|
item->m_thumb->tex.destroy();
|
||||||
|
}
|
||||||
|
container->remove_all_children();
|
||||||
|
}
|
||||||
|
|
||||||
|
void NodeDialogBrowse::init_list()
|
||||||
|
{
|
||||||
auto names = Asset::list_files(search_path, false, ".*\\.ppi");
|
auto names = Asset::list_files(search_path, false, ".*\\.ppi");
|
||||||
for (const auto& n : names)
|
for (const auto& n : names)
|
||||||
{
|
{
|
||||||
@@ -104,11 +146,7 @@ void NodeDialogBrowse::init_controls()
|
|||||||
}
|
}
|
||||||
container->add_child(node);
|
container->add_child(node);
|
||||||
}
|
}
|
||||||
// if (auto* first = (NodeDialogBrowseItem*)container->get_child_at(0))
|
|
||||||
// {
|
|
||||||
// first->on_selected(first);
|
|
||||||
// first->m_selected = true;
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NodeDialogBrowse::is_selected()
|
bool NodeDialogBrowse::is_selected()
|
||||||
@@ -142,6 +180,7 @@ void NodeDialogBrowseItem::init()
|
|||||||
void NodeDialogBrowseItem::init_controls()
|
void NodeDialogBrowseItem::init_controls()
|
||||||
{
|
{
|
||||||
m_text = find<NodeText>("title");
|
m_text = find<NodeText>("title");
|
||||||
|
m_thumb = find<NodeImageTexture>("thumb-tex");
|
||||||
}
|
}
|
||||||
void NodeDialogBrowseItem::loaded()
|
void NodeDialogBrowseItem::loaded()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -32,6 +32,8 @@ public:
|
|||||||
NodeButton* btn_cancel;
|
NodeButton* btn_cancel;
|
||||||
NodeButton* btn_ok;
|
NodeButton* btn_ok;
|
||||||
NodeButton* btn_delete;
|
NodeButton* btn_delete;
|
||||||
|
NodeButton* btn_path;
|
||||||
|
NodeText* working_path;
|
||||||
NodeDialogBrowseItem* current = nullptr;
|
NodeDialogBrowseItem* current = nullptr;
|
||||||
Node* container;
|
Node* container;
|
||||||
std::string selected_path;
|
std::string selected_path;
|
||||||
@@ -42,6 +44,8 @@ public:
|
|||||||
virtual void clone_finalize(Node* dest) const override;
|
virtual void clone_finalize(Node* dest) const override;
|
||||||
virtual void init() override;
|
virtual void init() override;
|
||||||
void init_controls();
|
void init_controls();
|
||||||
|
void init_list();
|
||||||
|
void clear_list();
|
||||||
virtual void loaded() override;
|
virtual void loaded() override;
|
||||||
bool is_selected();
|
bool is_selected();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -194,6 +194,24 @@ void NodeDialogSave::init_controls()
|
|||||||
if (btn_ok->on_click)
|
if (btn_ok->on_click)
|
||||||
btn_ok->on_click(btn_ok);
|
btn_ok->on_click(btn_ok);
|
||||||
};
|
};
|
||||||
|
#if defined(_WIN32) || defined(__OSX__)
|
||||||
|
static char path_buffer[256];
|
||||||
|
btn_path = find<NodeButton>("btn-path");
|
||||||
|
btn_path->on_click = [this](Node*){
|
||||||
|
App::I.pick_dir([this](std::string path){
|
||||||
|
LOG("change working path to %s", path.c_str());
|
||||||
|
async_start();
|
||||||
|
App::I.work_path = path;
|
||||||
|
realpath(path.c_str(), path_buffer);
|
||||||
|
working_path->set_text_format("Working dir: %s", path_buffer);
|
||||||
|
async_update();
|
||||||
|
async_end();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
working_path = find<NodeText>("path");
|
||||||
|
realpath(App::I.work_path.c_str(), path_buffer);
|
||||||
|
working_path->set_text_format("Working dir: %s", path_buffer);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
void NodeDialogSave::loaded()
|
void NodeDialogSave::loaded()
|
||||||
{
|
{
|
||||||
@@ -238,9 +256,12 @@ void NodeDialogNewDoc::init_controls()
|
|||||||
btn_path->on_click = [this](Node*){
|
btn_path->on_click = [this](Node*){
|
||||||
App::I.pick_dir([this](std::string path){
|
App::I.pick_dir([this](std::string path){
|
||||||
LOG("change working path to %s", path.c_str());
|
LOG("change working path to %s", path.c_str());
|
||||||
|
async_start();
|
||||||
App::I.work_path = path;
|
App::I.work_path = path;
|
||||||
realpath(path.c_str(), path_buffer);
|
realpath(path.c_str(), path_buffer);
|
||||||
working_path->set_text_format("Working dir: %s", path_buffer);
|
working_path->set_text_format("Working dir: %s", path_buffer);
|
||||||
|
async_update();
|
||||||
|
async_end();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
working_path = find<NodeText>("path");
|
working_path = find<NodeText>("path");
|
||||||
|
|||||||
@@ -50,6 +50,8 @@ class NodeDialogSave : public NodeBorder
|
|||||||
public:
|
public:
|
||||||
NodeButton* btn_cancel;
|
NodeButton* btn_cancel;
|
||||||
NodeButton* btn_ok;
|
NodeButton* btn_ok;
|
||||||
|
NodeButton* btn_path;
|
||||||
|
NodeText* working_path;
|
||||||
NodeTextInput* input;
|
NodeTextInput* input;
|
||||||
std::string selected_path;
|
std::string selected_path;
|
||||||
virtual Node* clone_instantiate() const override;
|
virtual Node* clone_instantiate() const override;
|
||||||
|
|||||||
@@ -21,5 +21,26 @@ void NodeMessageBox::init()
|
|||||||
btn_ok = m_template->find<NodeButton>("btn-ok");
|
btn_ok = m_template->find<NodeButton>("btn-ok");
|
||||||
btn_ok->on_click = [&](Node*) { destroy(); };
|
btn_ok->on_click = [&](Node*) { destroy(); };
|
||||||
btn_cancel = m_template->find<NodeButton>("btn-cancel");
|
btn_cancel = m_template->find<NodeButton>("btn-cancel");
|
||||||
btn_cancel->on_click = [&](Node*) { destroy(); };
|
on_submit = btn_cancel->on_click = [&](Node*) { destroy(); };
|
||||||
|
}
|
||||||
|
|
||||||
|
kEventResult NodeMessageBox::handle_event(Event* e)
|
||||||
|
{
|
||||||
|
Node::handle_event(e);
|
||||||
|
auto ke = (KeyEvent*)e;
|
||||||
|
switch (e->m_type)
|
||||||
|
{
|
||||||
|
case kEventType::KeyDown:
|
||||||
|
break;
|
||||||
|
case kEventType::KeyUp:
|
||||||
|
if (ke->m_key == kKey::KeyEnter && on_submit)
|
||||||
|
on_submit(this);
|
||||||
|
break;
|
||||||
|
case kEventType::KeyChar:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return kEventResult::Available;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return kEventResult::Consumed;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
class NodeMessageBox : public Node
|
class NodeMessageBox : public Node
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
std::function<void(Node*)> on_submit = nullptr;
|
||||||
Node* m_template;
|
Node* m_template;
|
||||||
NodeButton* btn_ok;
|
NodeButton* btn_ok;
|
||||||
NodeButton* btn_cancel;
|
NodeButton* btn_cancel;
|
||||||
@@ -13,4 +14,5 @@ public:
|
|||||||
NodeText* m_title;
|
NodeText* m_title;
|
||||||
virtual Node* clone_instantiate() const override;
|
virtual Node* clone_instantiate() const override;
|
||||||
virtual void init() override;
|
virtual void init() override;
|
||||||
|
virtual kEventResult handle_event(Event* e);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,22 +2,35 @@
|
|||||||
#include "app.h"
|
#include "app.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "node_text_input.h"
|
#include "node_text_input.h"
|
||||||
|
#include "node_border.h"
|
||||||
|
|
||||||
Node* NodeTextInput::clone_instantiate() const
|
Node* NodeTextInput::clone_instantiate() const
|
||||||
{
|
{
|
||||||
return new NodeTextInput();
|
return new NodeTextInput();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NodeTextInput::on_tick(float dt)
|
||||||
|
{
|
||||||
|
timer += dt;
|
||||||
|
if (timer > 1.0)
|
||||||
|
{
|
||||||
|
timer = 0;
|
||||||
|
if (m_cursor)
|
||||||
|
m_cursor->m_display = !m_cursor->m_display;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void NodeTextInput::clone_finalize(Node* dest) const
|
void NodeTextInput::clone_finalize(Node* dest) const
|
||||||
{
|
{
|
||||||
NodeBorder::clone_copy(dest);
|
NodeBorder::clone_copy(dest);
|
||||||
NodeTextInput* n = static_cast<NodeTextInput*>(dest);
|
NodeTextInput* n = static_cast<NodeTextInput*>(dest);
|
||||||
if (n->m_children.size())
|
if (n->m_children.size())
|
||||||
{
|
{
|
||||||
auto t = n->m_children[0];
|
n->m_text = (NodeText*)n->m_children[0].get();
|
||||||
n->m_text = (NodeText*)t.get();
|
n->m_cursor = (NodeBorder*)n->m_children[1].get();
|
||||||
}
|
}
|
||||||
n->m_string = m_string;
|
n->m_string = m_string;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void NodeTextInput::init()
|
void NodeTextInput::init()
|
||||||
@@ -34,6 +47,11 @@ void NodeTextInput::init_controls()
|
|||||||
m_text->m_text = "TextInput";
|
m_text->m_text = "TextInput";
|
||||||
m_text->create();
|
m_text->create();
|
||||||
m_string = "TextInput";
|
m_string = "TextInput";
|
||||||
|
YGNodeStyleSetFlexDirection(y_node, YGFlexDirectionRow);
|
||||||
|
m_cursor = add_child<NodeBorder>();
|
||||||
|
m_cursor->SetWidth(4);
|
||||||
|
m_cursor->SetHeightP(100);
|
||||||
|
m_cursor->SetMargin(0, 0, 0, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
kEventResult NodeTextInput::handle_event(Event* e)
|
kEventResult NodeTextInput::handle_event(Event* e)
|
||||||
@@ -58,7 +76,16 @@ kEventResult NodeTextInput::handle_event(Event* e)
|
|||||||
// break;
|
// break;
|
||||||
//}
|
//}
|
||||||
break;
|
break;
|
||||||
|
case kEventType::KeyUp:
|
||||||
|
if (ke->m_key == kKey::KeyEnter && on_return)
|
||||||
|
on_return(this);
|
||||||
|
break;
|
||||||
case kEventType::KeyChar:
|
case kEventType::KeyChar:
|
||||||
|
if (m_cursor)
|
||||||
|
{
|
||||||
|
timer = 0;
|
||||||
|
m_cursor->m_display = true;
|
||||||
|
}
|
||||||
if (ke->m_char == '\b') // backspace
|
if (ke->m_char == '\b') // backspace
|
||||||
{
|
{
|
||||||
if (!m_string.empty())
|
if (!m_string.empty())
|
||||||
@@ -77,8 +104,6 @@ kEventResult NodeTextInput::handle_event(Event* e)
|
|||||||
}
|
}
|
||||||
else if (ke->m_char == '\n' || ke->m_char == '\r') // enter/return
|
else if (ke->m_char == '\n' || ke->m_char == '\r') // enter/return
|
||||||
{
|
{
|
||||||
if (on_return)
|
|
||||||
on_return(this);
|
|
||||||
}
|
}
|
||||||
else if (ke->m_char >= 32 && ke->m_char < (32 + 96))
|
else if (ke->m_char >= 32 && ke->m_char < (32 + 96))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -5,12 +5,15 @@
|
|||||||
class NodeTextInput : public NodeBorder
|
class NodeTextInput : public NodeBorder
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
float timer = 0;
|
||||||
NodeText* m_text;
|
NodeText* m_text;
|
||||||
|
NodeBorder* m_cursor;
|
||||||
std::string m_string;
|
std::string m_string;
|
||||||
std::function<void(NodeTextInput*target)> on_return;
|
std::function<void(NodeTextInput*target)> on_return;
|
||||||
virtual Node* clone_instantiate() const override;
|
virtual Node* clone_instantiate() const override;
|
||||||
virtual void clone_finalize(Node* dest) const override;
|
virtual void clone_finalize(Node* dest) const override;
|
||||||
virtual void init() override;
|
virtual void init() override;
|
||||||
|
virtual void on_tick(float dt) override;
|
||||||
virtual kEventResult handle_event(Event* e) override;
|
virtual kEventResult handle_event(Event* e) override;
|
||||||
void init_controls();
|
void init_controls();
|
||||||
void set_text(const std::string& s);
|
void set_text(const std::string& s);
|
||||||
|
|||||||
Reference in New Issue
Block a user