conditional os in UI xml, add system dialog file open on osx, check api format or error message when opening a document, per-char text wrap on NodeText, additional info on create doc dialog like working path

This commit is contained in:
2018-10-06 14:20:07 +02:00
parent 5baa807cce
commit 739784b0d1
23 changed files with 161 additions and 63 deletions

View File

@@ -38,15 +38,15 @@ std::mutex task_mutex;
{ {
[[NSApplication sharedApplication] terminate:nil]; [[NSApplication sharedApplication] terminate:nil];
} }
- (std::string)pick_file - (std::string)pick_file:(NSArray<NSString*>*)types
{ {
NSOpenPanel *panel = [NSOpenPanel openPanel]; NSOpenPanel *panel = [NSOpenPanel openPanel];
[panel setCanChooseFiles:YES]; [panel setCanChooseFiles:YES];
[panel setCanChooseDirectories:NO]; [panel setCanChooseDirectories:NO];
[panel setAllowsMultipleSelection:NO]; // yes if more than one dir is allowed [panel setAllowsMultipleSelection:NO]; // yes if more than one dir is allowed
NSArray* fileTypes = [NSArray arrayWithObjects:@"png", @"PNG", @"jpg", @"JPG", @"jpeg", nil]; //NSArray* fileTypes = [NSArray arrayWithObjects:@"png", @"PNG", @"jpg", @"JPG", @"jpeg", nil];
[panel setAllowedFileTypes:fileTypes]; [panel setAllowedFileTypes:types];
NSInteger clicked = [panel runModal]; NSInteger clicked = [panel runModal];

View File

@@ -22,5 +22,5 @@
- (void)async_lock; - (void)async_lock;
- (void)async_unlock; - (void)async_unlock;
- (void)async_swap; - (void)async_swap;
- (std::string)pick_file; - (std::string)pick_file:(NSArray<NSString*>*)types;
@end @end

View File

@@ -121,6 +121,7 @@
AD787AEA20D4611100C4712A /* PanoQL.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = AD787ADD20D4611100C4712A /* PanoQL.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; AD787AEA20D4611100C4712A /* PanoQL.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = AD787ADD20D4611100C4712A /* PanoQL.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
AD787AF720D4637E00C4712A /* ThumbnailProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = AD787AF620D4637E00C4712A /* ThumbnailProvider.m */; }; AD787AF720D4637E00C4712A /* ThumbnailProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = AD787AF620D4637E00C4712A /* ThumbnailProvider.m */; };
AD787AFB20D4637E00C4712A /* PanoThumb.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = AD787AF320D4637E00C4712A /* PanoThumb.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; AD787AFB20D4637E00C4712A /* PanoThumb.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = AD787AF320D4637E00C4712A /* PanoThumb.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
AD97A6732168D79600F2F0BC /* HockeySDKResources.bundle in Resources */ = {isa = PBXBuildFile; fileRef = AD97A6722168D78600F2F0BC /* HockeySDKResources.bundle */; };
ADBC8C4E1FAE7D360094B339 /* node_dialog_browse.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ADBC8C471FAE7CC20094B339 /* node_dialog_browse.cpp */; }; ADBC8C4E1FAE7D360094B339 /* node_dialog_browse.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ADBC8C471FAE7CC20094B339 /* node_dialog_browse.cpp */; };
ADBC8C4F1FAE7D370094B339 /* node_dialog_browse.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ADBC8C471FAE7CC20094B339 /* node_dialog_browse.cpp */; }; ADBC8C4F1FAE7D370094B339 /* node_dialog_browse.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ADBC8C471FAE7CC20094B339 /* node_dialog_browse.cpp */; };
ADBC8C551FAFD0520094B339 /* app_cloud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ADBC8C511FAFD0360094B339 /* app_cloud.cpp */; }; ADBC8C551FAFD0520094B339 /* app_cloud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ADBC8C511FAFD0360094B339 /* app_cloud.cpp */; };
@@ -143,7 +144,6 @@
ADC8F782216678270084ECAD /* QuickLook.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ADC8F77C216678260084ECAD /* QuickLook.framework */; }; ADC8F782216678270084ECAD /* QuickLook.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ADC8F77C216678260084ECAD /* QuickLook.framework */; };
ADC8F783216678270084ECAD /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ADC8F77D216678270084ECAD /* MobileCoreServices.framework */; }; ADC8F783216678270084ECAD /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ADC8F77D216678270084ECAD /* MobileCoreServices.framework */; };
ADC8F784216678270084ECAD /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ADC8F77E216678270084ECAD /* SystemConfiguration.framework */; }; ADC8F784216678270084ECAD /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ADC8F77E216678270084ECAD /* SystemConfiguration.framework */; };
ADC8F786216678660084ECAD /* HockeySDK.embeddedframework in Resources */ = {isa = PBXBuildFile; fileRef = ADC8F785216678660084ECAD /* HockeySDK.embeddedframework */; };
ADC8F787216679B00084ECAD /* HockeySDK.embeddedframework in CopyFiles */ = {isa = PBXBuildFile; fileRef = ADC8F785216678660084ECAD /* HockeySDK.embeddedframework */; }; ADC8F787216679B00084ECAD /* HockeySDK.embeddedframework in CopyFiles */ = {isa = PBXBuildFile; fileRef = ADC8F785216678660084ECAD /* HockeySDK.embeddedframework */; };
ADC8F78921667C740084ECAD /* HockeySDK.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ADC8F78821667C740084ECAD /* HockeySDK.framework */; }; ADC8F78921667C740084ECAD /* HockeySDK.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ADC8F78821667C740084ECAD /* HockeySDK.framework */; };
ADD6AFD71F94DEB000E92461 /* node_progress_bar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ADD6AFD61F94DEAF00E92461 /* node_progress_bar.cpp */; }; ADD6AFD71F94DEB000E92461 /* node_progress_bar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ADD6AFD61F94DEAF00E92461 /* node_progress_bar.cpp */; };
@@ -405,6 +405,7 @@
AD95AEC31E41EDEC002DD03A /* font.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = font.cpp; sourceTree = "<group>"; }; AD95AEC31E41EDEC002DD03A /* font.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = font.cpp; sourceTree = "<group>"; };
AD95AEC41E41EDEC002DD03A /* font.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = font.h; sourceTree = "<group>"; }; AD95AEC41E41EDEC002DD03A /* font.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = font.h; sourceTree = "<group>"; };
AD95AEC51E41EDEC002DD03A /* pch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = pch.cpp; sourceTree = "<group>"; }; AD95AEC51E41EDEC002DD03A /* pch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = pch.cpp; sourceTree = "<group>"; };
AD97A6722168D78600F2F0BC /* HockeySDKResources.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; name = HockeySDKResources.bundle; path = "libs/hockeyapp/HockeySDK-iOS/HockeySDK.embeddedframework/HockeySDKResources.bundle"; sourceTree = "<group>"; };
ADB1C3D81EA3A156009A65BD /* event.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = event.cpp; sourceTree = "<group>"; }; ADB1C3D81EA3A156009A65BD /* event.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = event.cpp; sourceTree = "<group>"; };
ADB1C3D91EA3A156009A65BD /* event.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = event.h; sourceTree = "<group>"; }; ADB1C3D91EA3A156009A65BD /* event.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = event.h; sourceTree = "<group>"; };
ADB1C3DB1EA531B0009A65BD /* keymap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = keymap.h; sourceTree = "<group>"; }; ADB1C3DB1EA531B0009A65BD /* keymap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = keymap.h; sourceTree = "<group>"; };
@@ -549,6 +550,7 @@
AD06989520CC6C210010825F /* iOS */ = { AD06989520CC6C210010825F /* iOS */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
AD97A6722168D78600F2F0BC /* HockeySDKResources.bundle */,
ADC8F785216678660084ECAD /* HockeySDK.embeddedframework */, ADC8F785216678660084ECAD /* HockeySDK.embeddedframework */,
ADC8F779216678260084ECAD /* CoreTelephony.framework */, ADC8F779216678260084ECAD /* CoreTelephony.framework */,
ADC8F77A216678260084ECAD /* CoreText.framework */, ADC8F77A216678260084ECAD /* CoreText.framework */,
@@ -1095,7 +1097,7 @@
ADD7D27C1EBF9AE300D5A897 /* Main.storyboard in Resources */, ADD7D27C1EBF9AE300D5A897 /* Main.storyboard in Resources */,
ADD7D27E1EBF9AE300D5A897 /* Assets.xcassets in Resources */, ADD7D27E1EBF9AE300D5A897 /* Assets.xcassets in Resources */,
ADD7D2811EBF9AE300D5A897 /* LaunchScreen.storyboard in Resources */, ADD7D2811EBF9AE300D5A897 /* LaunchScreen.storyboard in Resources */,
ADC8F786216678660084ECAD /* HockeySDK.embeddedframework in Resources */, AD97A6732168D79600F2F0BC /* HockeySDKResources.bundle in Resources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };

View File

@@ -415,10 +415,11 @@
<layout id="dialog-resize"> <layout id="dialog-resize">
<border positioning="absolute" position="0 0" color=".4 .4 .4 .8" width="100%" height="100%" align="center" justify="center"> <border positioning="absolute" position="0 0" color=".4 .4 .4 .8" width="100%" height="100%" align="center" justify="center">
<border thickness="1" border-color=".2" pad="3"> <border thickness="1" border-color=".2" pad="3">
<border width="400" height="30" color=".2 .2 .2 .9" dir="row" align="center" justify="center"> <border width="500" height="30" color=".2 .2 .2 .9" dir="row" align="center" justify="center">
<text text="Resize Document Resolution" font-face="arial" font-size="11"></text> <text text="Resize Document Resolution" font-face="arial" font-size="11"></text>
</border> </border>
<border width="400" color="0 0 0 .9" pad="10" dir="col"> <border width="500" color="0 0 0 .9" pad="10" dir="col">
<text text="This action is permanent and cannot be undone.\nAll of the history will be cleared.\nResolution 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">
<node grow="1"><text id="current-res" text="Current: 1024px" font-face="arial" font-size="11" margin="0 5 0 5"/></node> <node grow="1"><text id="current-res" text="Current: 1024px" font-face="arial" font-size="11" margin="0 5 0 5"/></node>
<text text="New Resolution:" font-face="arial" font-size="11" margin="0 5 0 5"/> <text text="New Resolution:" font-face="arial" font-size="11" margin="0 5 0 5"/>
@@ -549,15 +550,17 @@
<layout id="dialog-newdoc"> <layout id="dialog-newdoc">
<border positioning="absolute" position="0 0" color=".4 .4 .4 .8" width="100%" height="100%" align="center" justify="center"> <border positioning="absolute" position="0 0" color=".4 .4 .4 .8" width="100%" height="100%" align="center" justify="center">
<border thickness="1" border-color=".2" pad="3"> <border thickness="1" border-color=".2" pad="3">
<border width="400" height="30" color=".2 .2 .2 .9" dir="row" align="center" justify="center"> <border width="500" height="30" color=".2 .2 .2 .9" dir="row" align="center" justify="center">
<text text="Create New Pano Project" font-face="arial" font-size="11"></text> <text text="Create New Pano Project" font-face="arial" font-size="11"></text>
</border> </border>
<border width="400" color="0 0 0 .9" pad="10" dir="col"> <border width="500" color="0 0 0 .9" pad="10" dir="col">
<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" justify="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"/>
<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">
<button id="btn-ok" text="Create Project" width="100" height="30" margin="0 10 0 0"/> <button id="btn-ok" text="Create Project" width="100" height="30" margin="0 10 0 0"/>
<button id="btn-cancel" text="Cancel" width="60" height="30" pad="10"/> <button id="btn-cancel" text="Cancel" width="60" height="30" pad="10"/>
@@ -811,6 +814,11 @@ Here's a list of what's available in this release.
<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" text="Menu" 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"/>
</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">
<icon icon="image" width="20"/>
<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" text="Menu" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">

View File

@@ -37,16 +37,25 @@ void App::open_document(std::string path)
doc_name = path.substr(start, path.length() - start - strlen(".ppi")); doc_name = path.substr(start, path.length() - start - strlen(".ppi"));
canvas->reset_camera(); canvas->reset_camera();
layers->clear(); layers->clear();
canvas->m_canvas->project_open(path, [this] { canvas->m_canvas->project_open(path, [this](bool success){
// on complete // on complete
async_start(); if (success)
title_update();
for (auto& i : canvas->m_canvas->m_order)
{ {
auto* l = layers->add_layer(canvas->m_canvas->m_layers[i].m_name.c_str()); async_start();
l->m_opacity->m_value.x = canvas->m_canvas->m_layers[i].m_opacity; title_update();
for (auto& i : canvas->m_canvas->m_order)
{
auto* l = layers->add_layer(canvas->m_canvas->m_layers[i].m_name.c_str());
l->m_opacity->m_value.x = canvas->m_canvas->m_layers[i].m_opacity;
}
async_end();
}
else
{
message_box("Open Document Error",
"There was an error opening the document.\n"
"It may be inaccessible or corrupted.");
} }
async_end();
}); });
ActionManager::clear(); ActionManager::clear();
} }

View File

@@ -94,6 +94,7 @@ public:
struct engine* and_engine; struct engine* and_engine;
#endif #endif
void pick_image(std::function<void(std::string path)> callback); void pick_image(std::function<void(std::string path)> callback);
void pick_file(std::vector<std::string> types, std::function<void(std::string path)> callback);
void display_file(std::string path); void display_file(std::string path);
void showKeyboard(); void showKeyboard();
void hideKeyboard(); void hideKeyboard();

View File

@@ -1,5 +1,6 @@
#include "pch.h" #include "pch.h"
#include "app.h" #include "app.h"
#include "action.h"
#include "node_dialog_open.h" #include "node_dialog_open.h"
#include "node_dialog_browse.h" #include "node_dialog_browse.h"
#include "node_dialog_resize.h" #include "node_dialog_resize.h"
@@ -167,6 +168,7 @@ void App::dialog_newdoc()
} }
} }
// DEPRECATED
void App::dialog_open() void App::dialog_open()
{ {
auto show_dialog = [this] { auto show_dialog = [this] {
@@ -184,19 +186,19 @@ void App::dialog_open()
dialog->btn_ok->on_click = [this, dialog](Node*) dialog->btn_ok->on_click = [this, dialog](Node*)
{ {
canvas->reset_camera(); // canvas->reset_camera();
layers->clear(); // layers->clear();
doc_name = dialog->selected_name; // doc_name = dialog->selected_name;
canvas->m_canvas->project_open(dialog->selected_path, [this] { // canvas->m_canvas->project_open(dialog->selected_path, [this](bool success) {
// on complete // // on complete
async_start(); // async_start();
title_update(); // title_update();
for (auto& i : canvas->m_canvas->m_order) // for (auto& i : canvas->m_canvas->m_order)
layers->add_layer(canvas->m_canvas->m_layers[i].m_name.c_str()); // layers->add_layer(canvas->m_canvas->m_layers[i].m_name.c_str());
async_end(); // async_end();
}); // });
dialog->destroy(); // dialog->destroy();
ActionManager::clear(); // ActionManager::clear();
}; };
async_end(); async_end();
}; };
@@ -410,6 +412,7 @@ void App::dialog_resize()
if (canvas) if (canvas)
canvas->m_canvas->resize(res, res); canvas->m_canvas->resize(res, res);
App::I.title_update(); App::I.title_update();
ActionManager::clear();
dialog->destroy(); dialog->destroy();
}; };

View File

@@ -51,7 +51,33 @@ void App::pick_image(std::function<void(std::string path)> callback)
[ios_view pick_photo:callback]; [ios_view pick_photo:callback];
#elif __OSX__ #elif __OSX__
dispatch_async(dispatch_get_main_queue(), ^{ dispatch_async(dispatch_get_main_queue(), ^{
std::string path = [osx_view pick_file]; NSArray* fileTypes = [NSArray arrayWithObjects:@"png", @"PNG", @"jpg", @"JPG", @"jpeg", nil];
std::string path = [osx_view pick_file:fileTypes];
if (!path.empty())
callback(path);
});
#elif __ANDROID__
pick_file(and_app, callback);
#elif _WIN32
std::string path = win32_open_file();
if (!path.empty())
callback(path);
#endif
}
void App::pick_file(std::vector<std::string> types, std::function<void (std::string)> callback)
{
redraw = true;
#ifdef __IOS__
// not implemented on ios
//[ios_view pick_photo:callback];
#elif __OSX__
dispatch_async(dispatch_get_main_queue(), ^{
//NSArray* fileTypes = [NSArray arrayWithObjects:@"ppi", @"PPI", nil];
NSMutableArray<NSString*>* fileTypes = [NSMutableArray arrayWithCapacity:types.size()];
for (const auto& t : types)
[fileTypes addObject:[NSString stringWithCString:t.c_str() encoding:NSUTF8StringEncoding]];
std::string path = [osx_view pick_file:fileTypes];
if (!path.empty()) if (!path.empty())
callback(path); callback(path);
}); });

View File

@@ -389,7 +389,10 @@ void App::init_menu_file()
}; };
if (auto b = popup->find<NodeButtonCustom>("file-open")) if (auto b = popup->find<NodeButtonCustom>("file-open"))
b->on_click = [this](Node*) { b->on_click = [this](Node*) {
dialog_open(); //dialog_open();
App::I.pick_file({"ppi","PPI"}, [this](std::string path){
App::I.open_document(path);
});
popup->mouse_release(); popup->mouse_release();
popup->destroy(); popup->destroy();
}; };

View File

@@ -13,7 +13,7 @@ AAssetManager* Asset::m_am;
bool Asset::delete_file(const std::string& path) bool Asset::delete_file(const std::string& path)
{ {
LOG("delete project: %s", path.c_str()); LOG("delete file: %s", path.c_str());
std::remove(path.c_str()); std::remove(path.c_str());
return true; return true;
} }
@@ -136,7 +136,7 @@ bool Asset::open(const char* path)
#ifdef __ANDROID__ #ifdef __ANDROID__
if (!(m_asset = AAssetManager_open(m_am, path, AASSET_MODE_RANDOM))) if (!(m_asset = AAssetManager_open(m_am, path, AASSET_MODE_RANDOM)))
{ {
LOG("AAssetManager_open failed"); LOG("AAssetManager_open failed %s", path);
return false; return false;
} }
m_len = (int)AAsset_getLength(m_asset); m_len = (int)AAsset_getLength(m_asset);
@@ -150,7 +150,7 @@ bool Asset::open(const char* path)
//LOG("asset file: %s", file_path.c_str()); //LOG("asset file: %s", file_path.c_str());
if (!(m_fp = fopen(file_path.c_str(), "rb"))) if (!(m_fp = fopen(file_path.c_str(), "rb")))
{ {
LOG("errno = %d", errno); LOG("asset open errno = %d, %s", errno, path);
return false; return false;
} }
fseek(m_fp, 0, SEEK_END); fseek(m_fp, 0, SEEK_END);

View File

@@ -1674,31 +1674,34 @@ void ui::Canvas::project_save_thread(std::string file_path)
App::I.async_end(); App::I.async_end();
} }
void ui::Canvas::project_open(std::string file_path, std::function<void()> on_complete) void ui::Canvas::project_open(std::string file_path, std::function<void(bool)> on_complete)
{ {
std::thread t([=] { std::thread t([=] {
project_open_thread(file_path); bool result = project_open_thread(file_path);
if (on_complete) if (on_complete)
on_complete(); on_complete(result);
}); });
t.detach(); t.detach();
} }
void ui::Canvas::project_open_thread(std::string file_path) bool ui::Canvas::project_open_thread(std::string file_path)
{ {
FILE* fp = fopen(file_path.c_str(), "rb"); FILE* fp = fopen(file_path.c_str(), "rb");
if (!fp) if (!fp)
{ {
LOG("cannot write project to %s", file_path.c_str()); LOG("cannot write project to %s", file_path.c_str());
return; // should probably return a bool return false; // should probably return a bool
} }
PPIHeader ppi_header; PPIHeader ppi_header;
fread(&ppi_header, sizeof(PPIHeader), 1, fp); fread(&ppi_header, sizeof(PPIHeader), 1, fp);
if (!ppi_header.valid()) if (!ppi_header.valid())
return; {
LOG("INVALID PPI HEADER");
return false;
}
gl_state gl; gl_state gl;
std::shared_ptr<NodeProgressBar> pb; std::shared_ptr<NodeProgressBar> pb;
if (App::I.layout.m_loaded) if (App::I.layout.m_loaded)
@@ -1832,6 +1835,7 @@ void ui::Canvas::project_open_thread(std::string file_path)
App::I.title_update(); App::I.title_update();
App::I.async_end(); App::I.async_end();
} }
return true;
} }
ui::Image ui::Canvas::thumbnail_generate(int w, int h) ui::Image ui::Canvas::thumbnail_generate(int w, int h)
@@ -2134,7 +2138,6 @@ ui::Layer::Snapshot ui::Layer::snapshot(std::string data_path)
{ {
Snapshot snap; Snapshot snap;
static int counter = 0; static int counter = 0;
LOG("errno = %d", errno);
glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_2D, 0);
//glBindFramebuffer(GL_FRAMEBUFFER, 0); //glBindFramebuffer(GL_FRAMEBUFFER, 0);
for (int i = 0; i < 6; i++) for (int i = 0; i < 6; i++)

View File

@@ -216,8 +216,8 @@ public:
void project_save(std::function<void()> on_complete = nullptr); void project_save(std::function<void()> 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()> on_complete = nullptr);
void project_save_thread(std::string file_path); void project_save_thread(std::string file_path);
void project_open(std::string file_path, std::function<void()> on_complete = nullptr); void project_open(std::string file_path, std::function<void(bool)> on_complete = nullptr);
void 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);
ui::Image thumbnail_generate(int w, int h); ui::Image thumbnail_generate(int w, int h);
ui::Image thumbnail_read(std::string data_path); ui::Image thumbnail_read(std::string data_path);

View File

@@ -75,9 +75,14 @@ void TextMesh::update(kFont id, const char* text)
if (text[i] == '\n') if (text[i] == '\n')
{ {
x = 0; x = 0;
y += f.size *2; y += f.size * 2;
continue; continue;
} }
if (max_width > 0 && x > max_width * 2 /*font scale factor*/)
{
x = 0;
y += f.size * 2;
}
int c = text[i] - f.start_char; int c = text[i] - f.start_char;
stbtt_aligned_quad q; stbtt_aligned_quad q;
stbtt_GetBakedQuad((stbtt_bakedchar*)f.chars.data(), f.w, f.h, c, &x, &y, &q, true); stbtt_GetBakedQuad((stbtt_bakedchar*)f.chars.data(), f.w, f.h, c, &x, &y, &q, true);

View File

@@ -40,6 +40,7 @@ class TextMesh
public: public:
GLuint font_array = 0; GLuint font_array = 0;
int font_array_count = 0; int font_array_count = 0;
int max_width = 0;
GLuint font_buffers[2] = {0, 0}; GLuint font_buffers[2] = {0, 0};
kFont font_id; kFont font_id;
glm::vec2 bb = { 0, 0 }; glm::vec2 bb = { 0, 0 };

View File

@@ -48,6 +48,16 @@ bool LayoutManager::load(const char* path)
LOG("Layout node without id"); LOG("Layout node without id");
return false; return false;
} }
if (auto os = current->Attribute("os"))
{
auto osv = split(os, ',');
if (std::find(osv.begin(), osv.end(), PP_OS) == osv.end())
{
LOG("Layout %s not for this os(%s), skipping", id_str, PP_OS)
current = current->NextSiblingElement("layout");
continue;
}
}
//LOG("Parsing layout: %s", id_str); //LOG("Parsing layout: %s", id_str);
uint16_t id = const_hash(id_str); uint16_t id = const_hash(id_str);
auto p = m_layouts.find(id); auto p = m_layouts.find(id);

View File

@@ -866,6 +866,17 @@ void Node::load_internal(const tinyxml2::XMLElement* x_node)
auto x_child = x_node->FirstChildElement(); auto x_child = x_node->FirstChildElement();
while (x_child) while (x_child)
{ {
if (auto os = x_child->Attribute("os"))
{
auto osv = split(os, ',');
if (std::find(osv.begin(), osv.end(), PP_OS) == osv.end())
{
LOG("Element %s not for this os(%s), skipping", x_child->Name(), PP_OS)
x_child = x_child->NextSiblingElement();
continue;
}
}
kWidget child_id = (kWidget)const_hash(x_child->Name()); kWidget child_id = (kWidget)const_hash(x_child->Name());
switch (child_id) switch (child_id)
{ {

View File

@@ -24,6 +24,7 @@ enum class kAttribute : uint16_t
BorderColor = const_hash("border-color"), BorderColor = const_hash("border-color"),
Type = const_hash("type"), Type = const_hash("type"),
Text = const_hash("text"), Text = const_hash("text"),
TextWrapWidth = const_hash("text-wrap-width"),
FontFace = const_hash("font-face"), FontFace = const_hash("font-face"),
FontSize = const_hash("font-size"), FontSize = const_hash("font-size"),
Justify = const_hash("justify"), Justify = const_hash("justify"),

View File

@@ -232,6 +232,12 @@ void NodeDialogNewDoc::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__)
working_path = find<NodeText>("path");
static char path_buffer[256];
realpath(App::I.data_path.c_str(), path_buffer);
working_path->set_text_format("Working dir: %s", path_buffer);
#endif
} }
void NodeDialogNewDoc::loaded() void NodeDialogNewDoc::loaded()
{ {

View File

@@ -66,6 +66,7 @@ public:
NodeButton* btn_cancel; NodeButton* btn_cancel;
NodeButton* btn_ok; NodeButton* btn_ok;
NodeTextInput* input; NodeTextInput* input;
NodeText* working_path;
NodeComboBox* m_resolution; NodeComboBox* m_resolution;
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;

View File

@@ -12,6 +12,7 @@ void NodeText::clone_copy(Node* dest) const
{ {
Node::clone_copy(dest); Node::clone_copy(dest);
NodeText* n = static_cast<NodeText*>(dest); NodeText* n = static_cast<NodeText*>(dest);
n->m_text_mesh.max_width = m_text_mesh.max_width;
n->m_text_mesh.create(); n->m_text_mesh.create();
n->m_text_mesh.update(font_id, m_text.c_str()); n->m_text_mesh.update(font_id, m_text.c_str());
n->m_text = m_text; n->m_text = m_text;
@@ -53,6 +54,9 @@ void NodeText::parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* att
Node::parse_attributes(ka, attr); Node::parse_attributes(ka, attr);
switch (ka) switch (ka)
{ {
case kAttribute::TextWrapWidth:
m_text_mesh.max_width = attr->IntValue();
break;
case kAttribute::Text: case kAttribute::Text:
m_text = unescape(attr->Value()); m_text = unescape(attr->Value());
break; break;
@@ -84,6 +88,18 @@ void NodeText::set_text(const char* s)
SetSize(m_text_mesh.bb); SetSize(m_text_mesh.bb);
} }
void NodeText::set_text_format(const char* fmt, ...)
{
static char buffer[4096];
va_list args;
va_start(args, fmt);
vsnprintf(buffer, sizeof(buffer), fmt, args);
va_end(args);
m_text = buffer;
m_text_mesh.update(font_id, buffer);
SetSize(m_text_mesh.bb);
}
void NodeText::draw() void NodeText::draw()
{ {
using namespace ui; using namespace ui;

View File

@@ -17,6 +17,7 @@ public:
virtual void restore_context() override; virtual void restore_context() override;
virtual void parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* attr) override; virtual void parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* attr) override;
void set_text(const char* s); void set_text(const char* s);
void set_text_format(const char* fmt, ...);
void set_font(kFont fontID); void set_font(kFont fontID);
virtual void draw() override; virtual void draw() override;
}; };

View File

@@ -8,21 +8,7 @@
#ifdef __APPLE__ #ifdef __APPLE__
#include "TargetConditionals.h" #include "TargetConditionals.h"
#if TARGET_OS_IPHONE && TARGET_IPHONE_SIMULATOR #if TARGET_OS_IOS
#define TARGET_OS_IOS 1
#define __IOS__ 1
#include <CoreFoundation/CoreFoundation.h>
#ifdef __OBJC__
#import <Foundation/Foundation.h>
#import <AVFoundation/AVFoundation.h>
#import <UIKit/UIKit.h>
#import <GLKit/GLKit.h>
#endif
#include <OpenGLES/ES3/gl.h>
#include <OpenGLES/ES3/glext.h>
#define SHADER_VERSION "#version 300 es\n"
#elif TARGET_OS_IPHONE
#define TARGET_OS_IOS 1
#define __IOS__ 1 #define __IOS__ 1
#include <CoreFoundation/CoreFoundation.h> #include <CoreFoundation/CoreFoundation.h>
#ifdef __OBJC__ #ifdef __OBJC__
@@ -34,8 +20,8 @@
#include <OpenGLES/ES3/gl.h> #include <OpenGLES/ES3/gl.h>
#include <OpenGLES/ES3/glext.h> #include <OpenGLES/ES3/glext.h>
#define SHADER_VERSION "#version 300 es\n" #define SHADER_VERSION "#version 300 es\n"
#define PP_OS "ios"
#else #else
#define TARGET_OS_OSX 1
#define __OSX__ 1 #define __OSX__ 1
#ifdef __OBJC__ #ifdef __OBJC__
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
@@ -44,6 +30,7 @@
#include <OpenGL/gl3.h> #include <OpenGL/gl3.h>
#include <OpenGL/gl3ext.h> #include <OpenGL/gl3ext.h>
#define SHADER_VERSION "#version 150\n" #define SHADER_VERSION "#version 150\n"
#define PP_OS "osx"
#endif #endif
#include <sys/stat.h> #include <sys/stat.h>
@@ -51,6 +38,7 @@
#include <dirent.h> #include <dirent.h>
#elif __ANDROID__ #elif __ANDROID__
#include <EGL/egl.h> #include <EGL/egl.h>
#include <EGL/eglext.h> #include <EGL/eglext.h>
#include <GLES3/gl3.h> #include <GLES3/gl3.h>
@@ -61,8 +49,10 @@
#include <android_native_app_glue.h> #include <android_native_app_glue.h>
#define SHADER_VERSION "#version 300 es\n" #define SHADER_VERSION "#version 300 es\n"
#define PP_OS "android"
#elif _WIN32 #elif _WIN32
#define _USE_MATH_DEFINES #define _USE_MATH_DEFINES
#define _CRT_SECURE_NO_WARNINGS #define _CRT_SECURE_NO_WARNINGS
#define _SCL_SECURE_NO_WARNINGS #define _SCL_SECURE_NO_WARNINGS
@@ -77,6 +67,7 @@
#include <shlwapi.h> #include <shlwapi.h>
#define SHADER_VERSION "#version 150\n" #define SHADER_VERSION "#version 150\n"
#define PP_OS "win"
#endif #endif

View File

@@ -15,7 +15,7 @@ public:
void assign(GLuint tex, int w = -1, int h = -1, GLuint internal_format = GL_RGBA8, GLuint format = GL_RGBA); void assign(GLuint tex, int w = -1, int h = -1, GLuint internal_format = GL_RGBA8, GLuint format = GL_RGBA);
bool load(std::string filename); bool load(std::string filename);
bool load_file(std::string filename); bool load_file(std::string filename);
void destroy() { if (m_tex) LOG("TEX destroy %d", m_tex); glDeleteTextures(1, &m_tex); m_tex = 0; } void destroy() { if (m_tex) /*LOG("TEX destroy %d", m_tex);*/ glDeleteTextures(1, &m_tex); m_tex = 0; }
void bind() const { glBindTexture(GL_TEXTURE_2D, m_tex); } void bind() const { glBindTexture(GL_TEXTURE_2D, m_tex); }
void unbind() const { glBindTexture(GL_TEXTURE_2D, 0); } void unbind() const { glBindTexture(GL_TEXTURE_2D, 0); }
void update(const uint8_t* data); void update(const uint8_t* data);