From ea0679dfe51e834ee4106361476d249599a8b8e4 Mon Sep 17 00:00:00 2001 From: omigamedev Date: Fri, 12 Jul 2019 10:47:58 +0200 Subject: [PATCH] update iOS project --- PanoPainter/AppDelegate.m | 12 +- PanoPainter/GameViewController.h | 2 - PanoPainter/GameViewController.m | 219 ++++++++----------------------- src/app.cpp | 1 + src/app_dialogs.cpp | 1 - src/app_layout.cpp | 2 - src/canvas.cpp | 1 + src/objc_utils.cpp | 60 +++++++-- 8 files changed, 112 insertions(+), 186 deletions(-) diff --git a/PanoPainter/AppDelegate.m b/PanoPainter/AppDelegate.m index ded2494..436a8e3 100644 --- a/PanoPainter/AppDelegate.m +++ b/PanoPainter/AppDelegate.m @@ -23,7 +23,7 @@ - (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary *)options { - App::I.open_document([url fileSystemRepresentation]); + App::I->open_document([url fileSystemRepresentation]); return true; } @@ -73,29 +73,29 @@ - (void)applicationWillResignActive:(UIApplication *)application { // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. - App::I.redraw = true; + App::I->redraw = true; [view reset_touch]; } - (void)applicationDidEnterBackground:(UIApplication *)application { // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. - App::I.redraw = true; + App::I->redraw = true; } - (void)applicationWillEnterForeground:(UIApplication *)application { // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. - App::I.redraw = true; + App::I->redraw = true; } - (void)applicationDidBecomeActive:(UIApplication *)application { // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. - App::I.redraw = true; + App::I->redraw = true; } - (void)applicationWillTerminate:(UIApplication *)application { // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. - App::I.redraw = true; + App::I->redraw = true; } @end diff --git a/PanoPainter/GameViewController.h b/PanoPainter/GameViewController.h index 512fb32..282adeb 100644 --- a/PanoPainter/GameViewController.h +++ b/PanoPainter/GameViewController.h @@ -33,8 +33,6 @@ - (void)unregisterForKeyboardNotifications; - (void)crash; - (void)share_file:(NSString*)file_path; -- (void)tick; -- (void)render_loop; - (std::string)clipboard_get_string; - (bool)clipboard_set_string:(const std::string&)s; @end diff --git a/PanoPainter/GameViewController.m b/PanoPainter/GameViewController.m index 21a23f3..d1e2d3a 100644 --- a/PanoPainter/GameViewController.m +++ b/PanoPainter/GameViewController.m @@ -12,8 +12,6 @@ #include "app.h" #import "objc_utils.h" -std::deque> tasklist; -std::mutex task_mutex; std::mutex render_mutex; std::condition_variable render_cv; @@ -30,9 +28,6 @@ std::condition_variable render_cv; NSLock* gl_lock; } @property (strong, nonatomic) EAGLContext *context; - -- (void)setupGL; -- (void)tearDownGL; @end //std::map< @@ -82,6 +77,7 @@ std::recursive_mutex lock_mutex; - (void)async_swap { [self.context presentRenderbuffer:GL_FRAMEBUFFER]; + [self->glview display]; } - (void)share_file:(NSString *)file_path @@ -144,12 +140,18 @@ std::recursive_mutex lock_mutex; - (void)insertText:(NSString *)text { if (const char* cstr = [text cStringUsingEncoding:NSASCIIStringEncoding]) - App::I.key_char(cstr[0]); + App::I->ui_task_async([=] + { + App::I->key_char(cstr[0]); + }); NSLog(@"%@", text); // Do something with the typed character } - (void)deleteBackward { - App::I.key_char('\b'); + App::I->ui_task_async([=] + { + App::I->key_char('\b'); + }); // Handle the delete key } - (BOOL)hasText { @@ -192,13 +194,13 @@ std::recursive_mutex lock_mutex; - (void)keyboardWillBeShown:(NSNotification*)aNotification { - App::I.redraw = true; - App::I.animate = true; + App::I->redraw = true; + App::I->animate = true; } - (void)keyboardWasHidden:(NSNotification*)aNotification { - App::I.redraw = true; - App::I.animate = false; + App::I->redraw = true; + App::I->animate = false; [self unregisterForKeyboardNotifications]; } @@ -213,11 +215,12 @@ std::recursive_mutex lock_mutex; frame.size.height -= kbSize.height; view.frame = frame; - [self async_lock]; - App::I.resize(frame.size.width * view.contentScaleFactor, + App::I->ui_task_async([=] + { + App::I->resize(frame.size.width * view.contentScaleFactor, frame.size.height * view.contentScaleFactor); - App::I.animate = false; - [self async_unlock]; + }); + App::I->animate = false; } // Called when the UIKeyboardWillHideNotification is sent @@ -225,21 +228,23 @@ std::recursive_mutex lock_mutex; { CGRect frame = [[UIScreen mainScreen] bounds]; self.view.frame = frame; - [self async_lock]; - App::I.resize(frame.size.width * self.view.contentScaleFactor, + App::I->ui_task_async([=] + { + App::I->resize(frame.size.width * self.view.contentScaleFactor, frame.size.height * self.view.contentScaleFactor); - App::I.animate = true; - [self async_unlock]; + }); + App::I->animate = true; } - (void)reset_touch { - [self async_lock]; - if (t_count == 2) - App::I.gesture_end(); - else - App::I.mouse_cancel(0); - [self async_unlock]; + App::I->ui_task_async([=] + { + if (t_count == 2) + App::I->gesture_end(); + else + App::I->mouse_cancel(0); + }); t_count = 0; } @@ -255,9 +260,8 @@ std::set ignored_touch; if (source == kEventSource::Stylus) pen_down = true; - std::lock_guard lock(task_mutex); - tasklist.emplace_back([touchLocation, scale, f=touch.force, source] { - App::I.mouse_down(0, touchLocation.x * scale, touchLocation.y * scale, f, source, 0); + App::I->ui_task_async([touchLocation, scale, f=touch.force, source] { + App::I->mouse_down(0, touchLocation.x * scale, touchLocation.y * scale, f, source, 0); }); t_count = 1; t_pos = {touchLocation.x * scale, touchLocation.y * scale}; @@ -301,25 +305,23 @@ std::set ignored_touch; if (pen_down) { - std::lock_guard lock(task_mutex); - tasklist.emplace_back([tt0=t0.type,tt1=t1.type,p0,p1,f0=t0.force,f1=t1.force] { + App::I->ui_task_async([tt0=t0.type,tt1=t1.type,p0,p1,f0=t0.force,f1=t1.force] { if (tt0 == UITouchType::UITouchTypeStylus) - App::I.mouse_move(p0.x, p0.y, f0, kEventSource::Stylus, 0); + App::I->mouse_move(p0.x, p0.y, f0, kEventSource::Stylus, 0); if (tt1 == UITouchType::UITouchTypeStylus) - App::I.mouse_move(p1.x, p1.y, f1, kEventSource::Stylus, 0); + App::I->mouse_move(p1.x, p1.y, f1, kEventSource::Stylus, 0); }); } else if (n == 2) { - std::lock_guard lock(task_mutex); - tasklist.emplace_back([c=t_count, p0, p1] { + App::I->ui_task_async([c=t_count, p0, p1] { if (c == 1) { - App::I.mouse_cancel(0); - App::I.gesture_start(p0, p1); + App::I->mouse_cancel(0); + App::I->gesture_start(p0, p1); } else - App::I.gesture_move(p0, p1); + App::I->gesture_move(p0, p1); }); t_count = 2; } @@ -332,15 +334,14 @@ std::set ignored_touch; //force = [app sonarpen_pressure]; if (t_count == 2) { - //App::I.gesture_end(); - //App::I.mouse_down(0, touchLocation.x * scale, touchLocation.y * scale, force); + //App::I->gesture_end(); + //App::I->mouse_down(0, touchLocation.x * scale, touchLocation.y * scale, force); } else { kEventSource source = touch.type == UITouchType::UITouchTypeStylus ? kEventSource::Stylus : kEventSource::Touch; - std::lock_guard lock(task_mutex); - tasklist.emplace_back([touchLocation, scale, source, force] { - App::I.mouse_move(touchLocation.x * scale, touchLocation.y * scale, force, source, 0); + App::I->ui_task_async([touchLocation, scale, source, force] { + App::I->mouse_move(touchLocation.x * scale, touchLocation.y * scale, force, source, 0); }); } } @@ -361,12 +362,11 @@ std::set ignored_touch; kEventSource source = touch.type == UITouchType::UITouchTypeStylus ? kEventSource::Stylus : kEventSource::Touch; pen_down = false; - std::lock_guard lock(task_mutex); - tasklist.emplace_back([tc=t_count, touchLocation, scale, source] { + App::I->ui_task_async([tc=t_count, touchLocation, scale, source] { if (tc == 2) - App::I.gesture_end(); + App::I->gesture_end(); else - App::I.mouse_up(0, touchLocation.x * scale, touchLocation.y * scale, source, 0); + App::I->mouse_up(0, touchLocation.x * scale, touchLocation.y * scale, source, 0); }); t_count = 0; @@ -375,15 +375,16 @@ std::set ignored_touch; - (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id)coordinator { - [self async_lock]; - App::I.resize(size.width * self.view.contentScaleFactor, + App::I->ui_task_async([=] + { + App::I->resize(size.width * self.view.contentScaleFactor, size.height * self.view.contentScaleFactor); - [self async_unlock]; + }); } - (void)viewDidAppear:(BOOL)animated { - App::I.redraw = true; + App::I->redraw = true; [self resignFirstResponder]; //[self registerForKeyboardNotifications]; } @@ -391,8 +392,9 @@ std::set ignored_touch; - (void)viewDidLoad { [super viewDidLoad]; - App::I.initLog(); - App::I.ios_view = self; + App::I = new App; + App::I->initLog(); + App::I->ios_view = self; //self.preferredFramesPerSecond = 60; self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3]; @@ -409,122 +411,17 @@ std::set ignored_touch; view.enableSetNeedsDisplay = NO; glview = view; - App::I.width = view.frame.size.width * view.contentScaleFactor; - App::I.height = view.frame.size.height * view.contentScaleFactor; + App::I->width = view.frame.size.width * view.contentScaleFactor; + App::I->height = view.frame.size.height * view.contentScaleFactor; - [self setupGL]; -} - -- (void)dealloc -{ - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } -} - -- (void)didReceiveMemoryWarning -{ - [super didReceiveMemoryWarning]; - - if ([self isViewLoaded] && ([[self view] window] == nil)) { - self.view = nil; - - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } - self.context = nil; - } - - // Dispose of any resources that can be recreated. + App::I->render_thread_start(); + App::I->ui_thread_start(); } - (BOOL)prefersStatusBarHidden { return YES; } --(void)tick -{ - //std::lock_guard lock(render_mutex); - render_cv.notify_one(); -} - --(void)render_loop -{ - while (true) - { - static auto time = std::chrono::steady_clock::now(); - static double elapsed = 0; - static double min_fps_timer = 0; - auto now = std::chrono::steady_clock::now(); - auto dt = std::chrono::duration(now - time); - time = now; - elapsed += dt.count(); - min_fps_timer += dt.count(); - - if (min_fps_timer > 0.5) - { - App::I.redraw = true; - min_fps_timer = 0; - } - - std::deque> working_list; - if (!tasklist.empty()) - { - std::lock_guard lock(task_mutex); - working_list = std::move(tasklist); - } - - App::I.tick(dt.count()); - - [self async_lock]; - if (!(App::I.redraw || App::I.animate || !working_list.empty())) - { - //[self.context presentRenderbuffer:GL_FRAMEBUFFER]; - [self->glview display]; - [self async_unlock]; - std::unique_lock lock(render_mutex); - render_cv.wait(lock); - continue; - } - - while (!working_list.empty()) - { - working_list.front()(); - working_list.pop_front(); - } - App::I.clear(); - App::I.update(elapsed); - [self.context presentRenderbuffer:GL_FRAMEBUFFER]; - [self->glview display]; - [self async_unlock]; - elapsed = 0; - } -} - -- (void)setupGL -{ - [self async_lock]; - App::I.init(); - [self async_unlock]; - - std::thread([self]{ - [self render_loop]; - }).detach(); - - displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(tick)]; - displayLink.frameInterval = 1; - [displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; -} - -- (void)tearDownGL -{ - [EAGLContext setCurrentContext:self.context]; -} - @end @implementation GameView diff --git a/src/app.cpp b/src/app.cpp index 381702f..72a380b 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -520,6 +520,7 @@ void App::async_update() void App::async_redraw() { redraw = true; + ui_cv.notify_all(); } void App::async_end() diff --git a/src/app_dialogs.cpp b/src/app_dialogs.cpp index 952229a..def5f1a 100644 --- a/src/app_dialogs.cpp +++ b/src/app_dialogs.cpp @@ -34,7 +34,6 @@ NodeMessageBox* App::message_box(const std::string &title, const std::string& te m->btn_ok->m_text->set_text("Ok"); if (!cancel_button) m->btn_cancel->destroy(); - layout[main_id]->update(); return m; } diff --git a/src/app_layout.cpp b/src/app_layout.cpp index e3db4dc..b016f59 100644 --- a/src/app_layout.cpp +++ b/src/app_layout.cpp @@ -540,7 +540,6 @@ void App::init_menu_file() else { Image img; - async_start(); img.load_file(path); if (img.width == img.height / 6 || img.width == img.height * 2) { @@ -554,7 +553,6 @@ void App::init_menu_file() Canvas::set_mode(kCanvasMode::Import); } async_redraw(); - async_end(); } }); popup->mouse_release(); diff --git a/src/canvas.cpp b/src/canvas.cpp index 6438bb6..a51347f 100644 --- a/src/canvas.cpp +++ b/src/canvas.cpp @@ -1448,6 +1448,7 @@ void Canvas::FloodData::apply() layer->m_dirty_face[plane] = true; layer->m_dirty_box[plane] = box_union(layer->m_dirty_box[plane], bb[plane]); } + Canvas::I->m_unsaved = true; } void Canvas::resize(int width, int height) diff --git a/src/objc_utils.cpp b/src/objc_utils.cpp index 3056988..f2a8f65 100644 --- a/src/objc_utils.cpp +++ b/src/objc_utils.cpp @@ -41,14 +41,9 @@ std::string base_address; std::atomic_flag handler_executed; -void exception_handler(NSException *exception) + +void save_recovery() { - if (handler_executed.test_and_set()) - exit(0); - LOG("exception %s\n", [[exception name] cStringUsingEncoding:NSUTF8StringEncoding]); - NSString* callstack = [[NSThread callStackSymbols] componentsJoinedByString:@"\n"]; - LOG("base:\n%s\ncallstack:\n%s", base_address.c_str(), [callstack cStringUsingEncoding:NSUTF8StringEncoding]); - auto t = std::time(nullptr); auto tm = *std::localtime(&t); std::ostringstream oss; @@ -57,6 +52,16 @@ void exception_handler(NSException *exception) if (App::I->canvas && App::I->canvas->m_canvas) App::I->canvas->m_canvas->project_save_thread(path); +} + +void exception_handler(NSException *exception) +{ + if (handler_executed.test_and_set()) + exit(0); + LOG("exception %s\n", [[exception name] cStringUsingEncoding:NSUTF8StringEncoding]); + NSString* callstack = [[NSThread callStackSymbols] componentsJoinedByString:@"\n"]; + LOG("base:\n%s\ncallstack:\n%s", base_address.c_str(), [callstack cStringUsingEncoding:NSUTF8StringEncoding]); + save_recovery(); exit(0); } @@ -66,15 +71,19 @@ static void signal_handler (int signo) { LOG("signal %d\n", signo); NSString* callstack = [[NSThread callStackSymbols] componentsJoinedByString:@"\n"]; LOG("base:\n%s\ncallstack:\n%s", base_address.c_str(), [callstack cStringUsingEncoding:NSUTF8StringEncoding]); + save_recovery(); + exit(0); +} - auto t = std::time(nullptr); - auto tm = *std::localtime(&t); - std::ostringstream oss; - oss << std::put_time(&tm, "%d-%m-%Y %H-%M-%S"); - auto path = App::I->data_path + "/" + App::I->doc_name + "-recovery (" + oss.str() + ").ppi"; +void SignalHandler(int sig, siginfo_t *info, void *context) +{ + save_recovery(); + exit(0); +} - if (App::I->canvas && App::I->canvas->m_canvas) - App::I->canvas->m_canvas->project_save_thread(path); +void TerminateHandler() +{ + save_recovery(); exit(0); } @@ -89,4 +98,27 @@ void install_global_handlers() signal(SIGFPE, signal_handler); signal(SIGBUS, signal_handler); signal(SIGPIPE, signal_handler); + +/* + struct sigaction mySigAction; + mySigAction.sa_sigaction = SignalHandler; + mySigAction.sa_flags = SA_SIGINFO; + + sigemptyset(&mySigAction.sa_mask); + sigaction(SIGQUIT, &mySigAction, NULL); + sigaction(SIGILL, &mySigAction, NULL); + sigaction(SIGTRAP, &mySigAction, NULL); + sigaction(SIGABRT, &mySigAction, NULL); + sigaction(SIGEMT, &mySigAction, NULL); + sigaction(SIGFPE, &mySigAction, NULL); + sigaction(SIGBUS, &mySigAction, NULL); + sigaction(SIGSEGV, &mySigAction, NULL); + sigaction(SIGSYS, &mySigAction, NULL); + sigaction(SIGPIPE, &mySigAction, NULL); + sigaction(SIGALRM, &mySigAction, NULL); + sigaction(SIGXCPU, &mySigAction, NULL); + sigaction(SIGXFSZ, &mySigAction, NULL); + + std::set_terminate(TerminateHandler); +*/ }