add timelapse video generation on iOS and mac , fix history memory
This commit is contained in:
@@ -141,6 +141,7 @@ static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTime
|
|||||||
App::I.clear();
|
App::I.clear();
|
||||||
App::I.update(now - _prevTime);
|
App::I.update(now - _prevTime);
|
||||||
CGLFlushDrawable([glctx CGLContextObj]);
|
CGLFlushDrawable([glctx CGLContextObj]);
|
||||||
|
_prevTime = now;
|
||||||
}
|
}
|
||||||
|
|
||||||
//[[self openGLContext] flushBuffer];
|
//[[self openGLContext] flushBuffer];
|
||||||
@@ -156,7 +157,7 @@ static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTime
|
|||||||
// return YES to have your layer redrawn
|
// return YES to have your layer redrawn
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
return kCVReturnSuccess;
|
return kCVReturnSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -328,6 +329,7 @@ static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTime
|
|||||||
@end @implementation Controller
|
@end @implementation Controller
|
||||||
- (void)windowWillClose:(NSNotification *)notification
|
- (void)windowWillClose:(NSNotification *)notification
|
||||||
{
|
{
|
||||||
|
App::I.terminate();
|
||||||
[[NSApplication sharedApplication] terminate:nil];
|
[[NSApplication sharedApplication] terminate:nil];
|
||||||
}
|
}
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -374,6 +374,10 @@ NSThread* lock_thread;
|
|||||||
|
|
||||||
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
|
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
|
||||||
{
|
{
|
||||||
|
static auto time = std::chrono::steady_clock::now();
|
||||||
|
auto now = std::chrono::steady_clock::now();
|
||||||
|
auto dt = std::chrono::duration<float>(now - time);
|
||||||
|
|
||||||
[gl_lock lock];
|
[gl_lock lock];
|
||||||
if (!(App::I.redraw || App::I.animate))
|
if (!(App::I.redraw || App::I.animate))
|
||||||
{
|
{
|
||||||
@@ -384,9 +388,10 @@ NSThread* lock_thread;
|
|||||||
[EAGLContext setCurrentContext:self.context];
|
[EAGLContext setCurrentContext:self.context];
|
||||||
[view bindDrawable];
|
[view bindDrawable];
|
||||||
App::I.clear();
|
App::I.clear();
|
||||||
App::I.update(0);
|
App::I.update(dt.count());
|
||||||
[self.context presentRenderbuffer:GL_FRAMEBUFFER];
|
[self.context presentRenderbuffer:GL_FRAMEBUFFER];
|
||||||
[gl_lock unlock];
|
[gl_lock unlock];
|
||||||
|
time = now;
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -614,6 +614,24 @@
|
|||||||
</popup-menu>
|
</popup-menu>
|
||||||
</layout>
|
</layout>
|
||||||
|
|
||||||
|
<!-- timelapse menu -->
|
||||||
|
<layout id="timelapse-menu">
|
||||||
|
<popup-menu positioning="absolute" position="100 100" width="150" thickness="1" border-color=".1" color=".4 .4 .4 .8" dir="col">
|
||||||
|
<button-custom id="timelapse-start" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||||
|
<icon icon="cancel" width="20"/>
|
||||||
|
<text id="menu-label" text="Start Recording" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||||
|
</button-custom>
|
||||||
|
<button-custom id="timelapse-clear" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||||
|
<icon icon="cancel" width="20"/>
|
||||||
|
<text id="menu-label" text="Clear Frames" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||||
|
</button-custom>
|
||||||
|
<button-custom id="timelapse-export" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||||
|
<icon icon="cancel" width="20"/>
|
||||||
|
<text id="menu-label" text="Export MP4" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||||
|
</button-custom>
|
||||||
|
</popup-menu>
|
||||||
|
</layout>
|
||||||
|
|
||||||
<!--main-->
|
<!--main-->
|
||||||
<layout id="main">
|
<layout id="main">
|
||||||
<node dir="col" wrap="0" width="100%" height="100%" pad="0">
|
<node dir="col" wrap="0" width="100%" height="100%" pad="0">
|
||||||
@@ -636,6 +654,7 @@
|
|||||||
-->
|
-->
|
||||||
<text id="txt-docname" text="Panodoc: no-name" font-face="arial" font-size="11" margin="0 20 0 10" color=".6 .6 .6 1"/>
|
<text id="txt-docname" text="Panodoc: no-name" font-face="arial" font-size="11" margin="0 20 0 10" color=".6 .6 .6 1"/>
|
||||||
<node height="100%" color="1" grow="1" align="center" justify="flex-end" dir="row">
|
<node height="100%" color="1" grow="1" align="center" justify="flex-end" dir="row">
|
||||||
|
<text id="txt-rec" text="" font-face="arial" font-size="11" margin="0 10 0 0" color=".6 .6 .6 1"/>
|
||||||
<text id="txt-memory" text="History memory: 0.00 Mb" font-face="arial" font-size="11" margin="0 5 0 0" color=".6 .6 .6 1"/>
|
<text id="txt-memory" text="History memory: 0.00 Mb" font-face="arial" font-size="11" margin="0 5 0 0" color=".6 .6 .6 1"/>
|
||||||
<button-custom id="btn-clean-memory" margin="0 20 0 0">
|
<button-custom id="btn-clean-memory" margin="0 20 0 0">
|
||||||
<icon icon="delete" width="20"/>
|
<icon icon="delete" width="20"/>
|
||||||
@@ -662,6 +681,9 @@
|
|||||||
<button-custom id="menu-layers" width="60" height="100%" margin="0 0 0 0" justify="center" align="center" pad="8" color=".1">
|
<button-custom id="menu-layers" width="60" height="100%" margin="0 0 0 0" justify="center" align="center" pad="8" color=".1">
|
||||||
<text text="Layers" font-face="arial" font-size="11"/>
|
<text text="Layers" font-face="arial" font-size="11"/>
|
||||||
</button-custom>
|
</button-custom>
|
||||||
|
<button-custom id="menu-timelapse" width="80" height="100%" margin="0 0 0 0" justify="center" align="center" pad="8" color=".1">
|
||||||
|
<text text="Timelapse" font-face="arial" font-size="11"/>
|
||||||
|
</button-custom>
|
||||||
<button-custom id="menu-about" width="60" height="100%" margin="0 0 0 0" justify="center" align="center" pad="8" color=".1">
|
<button-custom id="menu-about" width="60" height="100%" margin="0 0 0 0" justify="center" align="center" pad="8" color=".1">
|
||||||
<text text="About" font-face="arial" font-size="11"/>
|
<text text="About" font-face="arial" font-size="11"/>
|
||||||
</button-custom>
|
</button-custom>
|
||||||
@@ -725,6 +747,7 @@
|
|||||||
</scroll>
|
</scroll>
|
||||||
</node>
|
</node>
|
||||||
<!-- timeline -->
|
<!-- timeline -->
|
||||||
|
<!--
|
||||||
<node height="100%" width="1" grow="1" dir="col" justify="flex-start">
|
<node height="100%" width="1" grow="1" dir="col" justify="flex-start">
|
||||||
<border color=".3 .3 .3 .4" height="50" width="100%" pad="10" dir="row">
|
<border color=".3 .3 .3 .4" height="50" width="100%" pad="10" dir="row">
|
||||||
<text text="Timeline: " font-face="arial" font-size="11" margin="8 10 0 0"/>
|
<text text="Timeline: " font-face="arial" font-size="11" margin="8 10 0 0"/>
|
||||||
@@ -734,6 +757,7 @@
|
|||||||
</node>
|
</node>
|
||||||
</border>
|
</border>
|
||||||
</node>
|
</node>
|
||||||
|
-->
|
||||||
</node>
|
</node>
|
||||||
<!-- status bar -->
|
<!-- status bar -->
|
||||||
<!--<border height="30" width="100%" color=".15" border-color=".3" dir="row" pad="0 0 0 10" align="center">
|
<!--<border height="30" width="100%" color=".15" border-color=".3" dir="row" pad="0 0 0 10" align="center">
|
||||||
|
|||||||
@@ -127,6 +127,10 @@
|
|||||||
AD1063AB1EC7AE92002A525F /* node_text.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AD1063791EC7ADFA002A525F /* node_text.cpp */; };
|
AD1063AB1EC7AE92002A525F /* node_text.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AD1063791EC7ADFA002A525F /* node_text.cpp */; };
|
||||||
AD1063AC1EC7AE92002A525F /* node_viewport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AD10637B1EC7ADFA002A525F /* node_viewport.cpp */; };
|
AD1063AC1EC7AE92002A525F /* node_viewport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AD10637B1EC7ADFA002A525F /* node_viewport.cpp */; };
|
||||||
AD29CC621EA2B214008C8BFA /* action.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AD29CC601EA2B214008C8BFA /* action.cpp */; };
|
AD29CC621EA2B214008C8BFA /* action.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AD29CC601EA2B214008C8BFA /* action.cpp */; };
|
||||||
|
AD3087C2205F016F009F9260 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AD3087C1205F016F009F9260 /* AVFoundation.framework */; };
|
||||||
|
AD3087C4205F0177009F9260 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AD3087C3205F0177009F9260 /* AVFoundation.framework */; };
|
||||||
|
AD3087C62061D1B4009F9260 /* CoreVideo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AD3087C52061D1B3009F9260 /* CoreVideo.framework */; };
|
||||||
|
AD3087C82061D1CD009F9260 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AD3087C72061D1CD009F9260 /* CoreGraphics.framework */; };
|
||||||
AD30D82F1F783E0100B6A112 /* libcurl.4.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = AD30D82E1F783E0100B6A112 /* libcurl.4.tbd */; };
|
AD30D82F1F783E0100B6A112 /* libcurl.4.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = AD30D82E1F783E0100B6A112 /* libcurl.4.tbd */; };
|
||||||
AD30D8331F8049BD00B6A112 /* Photos.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AD30D8321F8049BC00B6A112 /* Photos.framework */; };
|
AD30D8331F8049BD00B6A112 /* Photos.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AD30D8321F8049BC00B6A112 /* Photos.framework */; };
|
||||||
AD3B1EC01E3B8B7600E918E3 /* layout.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AD3B1EBE1E3B8B7600E918E3 /* layout.cpp */; };
|
AD3B1EC01E3B8B7600E918E3 /* layout.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AD3B1EBE1E3B8B7600E918E3 /* layout.cpp */; };
|
||||||
@@ -316,6 +320,10 @@
|
|||||||
AD29CC601EA2B214008C8BFA /* action.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = action.cpp; sourceTree = "<group>"; };
|
AD29CC601EA2B214008C8BFA /* action.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = action.cpp; sourceTree = "<group>"; };
|
||||||
AD29CC611EA2B214008C8BFA /* action.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = action.h; sourceTree = "<group>"; };
|
AD29CC611EA2B214008C8BFA /* action.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = action.h; sourceTree = "<group>"; };
|
||||||
AD2FEBDA1F94A742002804DD /* main.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = main.h; sourceTree = "<group>"; };
|
AD2FEBDA1F94A742002804DD /* main.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = main.h; sourceTree = "<group>"; };
|
||||||
|
AD3087C1205F016F009F9260 /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.1.sdk/System/Library/Frameworks/AVFoundation.framework; sourceTree = DEVELOPER_DIR; };
|
||||||
|
AD3087C3205F0177009F9260 /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; };
|
||||||
|
AD3087C52061D1B3009F9260 /* CoreVideo.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreVideo.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.1.sdk/System/Library/Frameworks/CoreVideo.framework; sourceTree = DEVELOPER_DIR; };
|
||||||
|
AD3087C72061D1CD009F9260 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.1.sdk/System/Library/Frameworks/CoreGraphics.framework; sourceTree = DEVELOPER_DIR; };
|
||||||
AD30D82E1F783E0100B6A112 /* libcurl.4.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libcurl.4.tbd; path = usr/lib/libcurl.4.tbd; sourceTree = SDKROOT; };
|
AD30D82E1F783E0100B6A112 /* libcurl.4.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libcurl.4.tbd; path = usr/lib/libcurl.4.tbd; sourceTree = SDKROOT; };
|
||||||
AD30D8321F8049BC00B6A112 /* Photos.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Photos.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.0.sdk/System/Library/Frameworks/Photos.framework; sourceTree = DEVELOPER_DIR; };
|
AD30D8321F8049BC00B6A112 /* Photos.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Photos.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.0.sdk/System/Library/Frameworks/Photos.framework; sourceTree = DEVELOPER_DIR; };
|
||||||
AD3B1EBE1E3B8B7600E918E3 /* layout.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = layout.cpp; sourceTree = "<group>"; };
|
AD3B1EBE1E3B8B7600E918E3 /* layout.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = layout.cpp; sourceTree = "<group>"; };
|
||||||
@@ -412,6 +420,7 @@
|
|||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
AD3087C4205F0177009F9260 /* AVFoundation.framework in Frameworks */,
|
||||||
AD30D82F1F783E0100B6A112 /* libcurl.4.tbd in Frameworks */,
|
AD30D82F1F783E0100B6A112 /* libcurl.4.tbd in Frameworks */,
|
||||||
AD0E5CB11ECC726C00C35669 /* OpenGL.framework in Frameworks */,
|
AD0E5CB11ECC726C00C35669 /* OpenGL.framework in Frameworks */,
|
||||||
AD0E5CB01ECC726400C35669 /* Cocoa.framework in Frameworks */,
|
AD0E5CB01ECC726400C35669 /* Cocoa.framework in Frameworks */,
|
||||||
@@ -435,6 +444,9 @@
|
|||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
AD3087C82061D1CD009F9260 /* CoreGraphics.framework in Frameworks */,
|
||||||
|
AD3087C62061D1B4009F9260 /* CoreVideo.framework in Frameworks */,
|
||||||
|
AD3087C2205F016F009F9260 /* AVFoundation.framework in Frameworks */,
|
||||||
AD30D8331F8049BD00B6A112 /* Photos.framework in Frameworks */,
|
AD30D8331F8049BD00B6A112 /* Photos.framework in Frameworks */,
|
||||||
AD759B691F279B3900211963 /* GLKit.framework in Frameworks */,
|
AD759B691F279B3900211963 /* GLKit.framework in Frameworks */,
|
||||||
ADD7D2B31EBFA42C00D5A897 /* Security.framework in Frameworks */,
|
ADD7D2B31EBFA42C00D5A897 /* Security.framework in Frameworks */,
|
||||||
@@ -544,20 +556,8 @@
|
|||||||
AD58E0461E107411006ACC15 = {
|
AD58E0461E107411006ACC15 = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
AD759B671F2796EA00211963 /* OpenGLES.framework */,
|
|
||||||
ADD7D2B21EBFA42C00D5A897 /* Security.framework */,
|
|
||||||
ADD7D2B01EBFA42600D5A897 /* libz.tbd */,
|
|
||||||
ADD7D28E1EBF9D8C00D5A897 /* GLKit.framework */,
|
|
||||||
ADD7D28C1EBF9D6F00D5A897 /* CoreFoundation.framework */,
|
|
||||||
ADD7D28A1EBF9D5D00D5A897 /* UIKit.framework */,
|
|
||||||
ADD7D2861EBF9C6700D5A897 /* Foundation.framework */,
|
|
||||||
ADD7D2AE1EBFA35F00D5A897 /* libcurl.a */,
|
|
||||||
AD58E0731E3421CB006ACC15 /* libs */,
|
AD58E0731E3421CB006ACC15 /* libs */,
|
||||||
AD58E0611E17F23D006ACC15 /* data */,
|
AD58E0611E17F23D006ACC15 /* data */,
|
||||||
AD58E05F1E12DA86006ACC15 /* CoreVideo.framework */,
|
|
||||||
AD58E05D1E10754F006ACC15 /* CoreFoundation.framework */,
|
|
||||||
AD58E05B1E107536006ACC15 /* Cocoa.framework */,
|
|
||||||
AD58E0591E10752E006ACC15 /* OpenGL.framework */,
|
|
||||||
AD58E0511E107411006ACC15 /* engine */,
|
AD58E0511E107411006ACC15 /* engine */,
|
||||||
ADD7D26C1EBF9AE300D5A897 /* PanoPainter */,
|
ADD7D26C1EBF9AE300D5A897 /* PanoPainter */,
|
||||||
AD0E5C9D1ECC6F2B00C35669 /* PanoPainter-OSX */,
|
AD0E5C9D1ECC6F2B00C35669 /* PanoPainter-OSX */,
|
||||||
@@ -631,6 +631,7 @@
|
|||||||
AD58E0731E3421CB006ACC15 /* libs */ = {
|
AD58E0731E3421CB006ACC15 /* libs */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
ADD7D2AE1EBFA35F00D5A897 /* libcurl.a */,
|
||||||
ADE491101F86D07900FB8E92 /* p2t */,
|
ADE491101F86D07900FB8E92 /* p2t */,
|
||||||
AD0E11A21ECA61B500CDA6BB /* jpge.cpp */,
|
AD0E11A21ECA61B500CDA6BB /* jpge.cpp */,
|
||||||
AD0E119F1ECA619F00CDA6BB /* jpgd.cpp */,
|
AD0E119F1ECA619F00CDA6BB /* jpgd.cpp */,
|
||||||
@@ -644,6 +645,21 @@
|
|||||||
AD759B631F2793AD00211963 /* Frameworks */ = {
|
AD759B631F2793AD00211963 /* Frameworks */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
AD3087C72061D1CD009F9260 /* CoreGraphics.framework */,
|
||||||
|
AD3087C52061D1B3009F9260 /* CoreVideo.framework */,
|
||||||
|
AD3087C1205F016F009F9260 /* AVFoundation.framework */,
|
||||||
|
AD3087C3205F0177009F9260 /* AVFoundation.framework */,
|
||||||
|
AD759B671F2796EA00211963 /* OpenGLES.framework */,
|
||||||
|
ADD7D2B21EBFA42C00D5A897 /* Security.framework */,
|
||||||
|
ADD7D2B01EBFA42600D5A897 /* libz.tbd */,
|
||||||
|
ADD7D28E1EBF9D8C00D5A897 /* GLKit.framework */,
|
||||||
|
ADD7D28C1EBF9D6F00D5A897 /* CoreFoundation.framework */,
|
||||||
|
ADD7D28A1EBF9D5D00D5A897 /* UIKit.framework */,
|
||||||
|
ADD7D2861EBF9C6700D5A897 /* Foundation.framework */,
|
||||||
|
AD58E05F1E12DA86006ACC15 /* CoreVideo.framework */,
|
||||||
|
AD58E05D1E10754F006ACC15 /* CoreFoundation.framework */,
|
||||||
|
AD58E05B1E107536006ACC15 /* Cocoa.framework */,
|
||||||
|
AD58E0591E10752E006ACC15 /* OpenGL.framework */,
|
||||||
AD30D8321F8049BC00B6A112 /* Photos.framework */,
|
AD30D8321F8049BC00B6A112 /* Photos.framework */,
|
||||||
AD30D82E1F783E0100B6A112 /* libcurl.4.tbd */,
|
AD30D82E1F783E0100B6A112 /* libcurl.4.tbd */,
|
||||||
AD759B661F27964D00211963 /* GLKit.framework */,
|
AD759B661F27964D00211963 /* GLKit.framework */,
|
||||||
|
|||||||
308
engine/app.cpp
308
engine/app.cpp
@@ -3,6 +3,7 @@
|
|||||||
#include "app.h"
|
#include "app.h"
|
||||||
#include "node_icon.h"
|
#include "node_icon.h"
|
||||||
#include "node_dialog_open.h"
|
#include "node_dialog_open.h"
|
||||||
|
#include "node_progress_bar.h"
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
#include <Foundation/Foundation.h>
|
#include <Foundation/Foundation.h>
|
||||||
@@ -57,6 +58,13 @@ void App::initLog()
|
|||||||
NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
|
NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
|
||||||
NSString* docpath = [paths objectAtIndex:0];
|
NSString* docpath = [paths objectAtIndex:0];
|
||||||
data_path = [docpath cStringUsingEncoding:NSASCIIStringEncoding];
|
data_path = [docpath cStringUsingEncoding:NSASCIIStringEncoding];
|
||||||
|
NSString* recpath = [docpath stringByAppendingString:@"/rec"];
|
||||||
|
rec_path = [recpath cStringUsingEncoding:NSASCIIStringEncoding];
|
||||||
|
NSError* recerr = nil;
|
||||||
|
if (![[NSFileManager defaultManager] createDirectoryAtPath:recpath withIntermediateDirectories:YES attributes:nil error:&recerr])
|
||||||
|
{
|
||||||
|
LOG("error creating rec path: %s", [[recerr localizedDescription] cStringUsingEncoding:NSASCIIStringEncoding]);
|
||||||
|
}
|
||||||
#elif _WIN32
|
#elif _WIN32
|
||||||
//CHAR my_documents[MAX_PATH];
|
//CHAR my_documents[MAX_PATH];
|
||||||
//HRESULT result = SHGetFolderPathA(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, my_documents);
|
//HRESULT result = SHGetFolderPathA(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, my_documents);
|
||||||
@@ -277,6 +285,8 @@ void App::async_end()
|
|||||||
|
|
||||||
void App::update(float dt)
|
void App::update(float dt)
|
||||||
{
|
{
|
||||||
|
static float rec_timer = 0.f;
|
||||||
|
|
||||||
static std::mutex m;
|
static std::mutex m;
|
||||||
std::lock_guard<std::mutex> _lock(m);
|
std::lock_guard<std::mutex> _lock(m);
|
||||||
|
|
||||||
@@ -335,6 +345,26 @@ void App::update(float dt)
|
|||||||
//msgbox->watch(observer);
|
//msgbox->watch(observer);
|
||||||
glDisable(GL_SCISSOR_TEST);
|
glDisable(GL_SCISSOR_TEST);
|
||||||
|
|
||||||
|
if (rec_running)
|
||||||
|
{
|
||||||
|
rec_timer += dt;
|
||||||
|
if (rec_timer > 1.f)
|
||||||
|
{
|
||||||
|
LOG("rec tick");
|
||||||
|
rec_timer = 0.f;
|
||||||
|
|
||||||
|
auto data = new uint8_t[width * height * 4];
|
||||||
|
glReadBuffer(GL_BACK);
|
||||||
|
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data);
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(rec_mutex);
|
||||||
|
rec_frames.emplace_back(data);
|
||||||
|
rec_cv.notify_all();
|
||||||
|
}
|
||||||
|
update_rec_frames();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
redraw = false;
|
redraw = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -349,6 +379,7 @@ void App::terminate()
|
|||||||
layers->clear_context();
|
layers->clear_context();
|
||||||
color->clear_context();
|
color->clear_context();
|
||||||
stroke->clear_context();
|
stroke->clear_context();
|
||||||
|
rec_stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void App::update_memory_usage(size_t bytes)
|
void App::update_memory_usage(size_t bytes)
|
||||||
@@ -361,3 +392,280 @@ void App::update_memory_usage(size_t bytes)
|
|||||||
layout[main_id]->update();
|
layout[main_id]->update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void App::update_rec_frames()
|
||||||
|
{
|
||||||
|
if (auto txt = layout[main_id]->find<NodeText>("txt-rec"))
|
||||||
|
{
|
||||||
|
if (rec_running)
|
||||||
|
{
|
||||||
|
static char buffer[128];
|
||||||
|
sprintf(buffer, "Recorder %d frames", rec_count);
|
||||||
|
txt->set_text(buffer);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
txt->set_text("");
|
||||||
|
}
|
||||||
|
layout[main_id]->update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void App::rec_clear()
|
||||||
|
{
|
||||||
|
rec_stop();
|
||||||
|
#if defined(__IOS__) || defined(__OSX__)
|
||||||
|
NSString *path = [NSString stringWithUTF8String:rec_path.c_str()];
|
||||||
|
NSDirectoryEnumerator* en = [[NSFileManager defaultManager] enumeratorAtPath:path];
|
||||||
|
NSError* err = nil;
|
||||||
|
BOOL res;
|
||||||
|
NSString* file;
|
||||||
|
while (file = [en nextObject])
|
||||||
|
{
|
||||||
|
NSString* file_path = [path stringByAppendingPathComponent:file];
|
||||||
|
[[NSFileManager defaultManager] removeItemAtPath:file_path error:nil];
|
||||||
|
NSLog(@"delete: %@", file_path);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
rec_count = 0;
|
||||||
|
update_rec_frames();
|
||||||
|
}
|
||||||
|
|
||||||
|
void App::rec_start()
|
||||||
|
{
|
||||||
|
if (!rec_running)
|
||||||
|
{
|
||||||
|
NSString* path = [NSString stringWithUTF8String:rec_path.c_str()];
|
||||||
|
NSArray *dirFiles = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:nil];
|
||||||
|
NSArray *jpgFiles = [dirFiles filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"self ENDSWITH '.jpg'"]];
|
||||||
|
rec_count = (int)[jpgFiles count];
|
||||||
|
update_rec_frames();
|
||||||
|
rec_thread = std::thread(&App::rec_loop, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void App::rec_stop()
|
||||||
|
{
|
||||||
|
if (rec_running)
|
||||||
|
{
|
||||||
|
rec_running = false;
|
||||||
|
rec_cv.notify_all();
|
||||||
|
if (rec_thread.joinable())
|
||||||
|
rec_thread.join();
|
||||||
|
update_rec_frames();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void stillImageDataReleaseCallback(void *releaseRefCon, const void *baseAddress)
|
||||||
|
{
|
||||||
|
free((void *)baseAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
void App::rec_export(std::string path)
|
||||||
|
{
|
||||||
|
int progress = 0;
|
||||||
|
int tot = rec_count;
|
||||||
|
auto pb = layout[main_id]->add_child<NodeProgressBar>();
|
||||||
|
pb->m_progress->SetWidthP(0);
|
||||||
|
pb->m_title->set_text("Exporting MP4 movie");
|
||||||
|
async_update();
|
||||||
|
|
||||||
|
#if defined(__IOS__) || defined(__OSX__)
|
||||||
|
NSString* mov_path = [NSString stringWithFormat:@"%s/out.mp4", rec_path.c_str()];
|
||||||
|
if ([[NSFileManager defaultManager] fileExistsAtPath:mov_path])
|
||||||
|
{
|
||||||
|
NSLog(@"remove existing mp4");
|
||||||
|
[[NSFileManager defaultManager] removeItemAtPath:mov_path error:nil];
|
||||||
|
}
|
||||||
|
NSURL* url = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%s/out.mp4", rec_path.c_str()]];
|
||||||
|
AVAssetWriter* writer = [AVAssetWriter assetWriterWithURL:url fileType:AVFileTypeMPEG4 error:nil];
|
||||||
|
writer.shouldOptimizeForNetworkUse = NO;
|
||||||
|
NSDictionary *videoCompressionSettings = @{
|
||||||
|
AVVideoCodecKey : AVVideoCodecH264,
|
||||||
|
AVVideoWidthKey : @(width),
|
||||||
|
AVVideoHeightKey : @(height),
|
||||||
|
AVVideoCompressionPropertiesKey : @{ AVVideoAverageBitRateKey : @(8<<20) }
|
||||||
|
};
|
||||||
|
if (![writer canApplyOutputSettings:videoCompressionSettings forMediaType:AVMediaTypeVideo])
|
||||||
|
{
|
||||||
|
NSLog(@"Couldn't add asset writer video input.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
AVAssetWriterInput* input = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo
|
||||||
|
outputSettings:videoCompressionSettings
|
||||||
|
sourceFormatHint:nil];
|
||||||
|
input.expectsMediaDataInRealTime = YES;
|
||||||
|
|
||||||
|
NSDictionary *adaptorDict = @{
|
||||||
|
(id)kCVPixelBufferPixelFormatTypeKey : @(kCVPixelFormatType_32BGRA),
|
||||||
|
(id)kCVPixelBufferWidthKey : @(width),
|
||||||
|
(id)kCVPixelBufferHeightKey : @(height)
|
||||||
|
};
|
||||||
|
|
||||||
|
AVAssetWriterInputPixelBufferAdaptor* _pixelBufferAdaptor = [[AVAssetWriterInputPixelBufferAdaptor alloc]
|
||||||
|
initWithAssetWriterInput:input
|
||||||
|
sourcePixelBufferAttributes:adaptorDict];
|
||||||
|
|
||||||
|
|
||||||
|
// Add asset writer input to asset writer
|
||||||
|
if (![writer canAddInput:input]) {
|
||||||
|
NSLog(@"Couldn't add input to writer.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
[writer addInput:input];
|
||||||
|
|
||||||
|
CMTime t;
|
||||||
|
t.timescale = 30;
|
||||||
|
t.flags = kCMTimeFlags_Valid;
|
||||||
|
t.epoch = 0;
|
||||||
|
t.value = 0;
|
||||||
|
//[writer startSessionAtSourceTime:t];
|
||||||
|
|
||||||
|
CVPixelBufferRef buff = NULL;
|
||||||
|
uint8_t* data = (uint8_t*)calloc(1, width * height * 4);
|
||||||
|
CVPixelBufferCreateWithBytes(kCFAllocatorDefault, width, height, kCVPixelFormatType_32RGBA, data,
|
||||||
|
width * 4, stillImageDataReleaseCallback, nil, nil, &buff);
|
||||||
|
OSStatus err = CVPixelBufferPoolCreatePixelBuffer(nil, _pixelBufferAdaptor.pixelBufferPool, &buff);
|
||||||
|
|
||||||
|
|
||||||
|
if (writer.status == AVAssetWriterStatusUnknown)
|
||||||
|
{
|
||||||
|
// If the asset writer status is unknown, implies writing hasn't started yet, hence start writing with start time as the buffer's presentation timestamp
|
||||||
|
if ([writer startWriting])
|
||||||
|
{
|
||||||
|
[writer startSessionAtSourceTime:t];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (writer.status == AVAssetWriterStatusWriting)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < tot; i++)
|
||||||
|
{
|
||||||
|
// If the asset writer status is writing, append sample buffer to its corresponding asset writer input
|
||||||
|
if (input.readyForMoreMediaData)
|
||||||
|
{
|
||||||
|
char path[256];
|
||||||
|
snprintf(path, sizeof(path), "%s/%04d.jpg", rec_path.c_str(), i);
|
||||||
|
NSString* img_path = [NSString stringWithUTF8String:path];
|
||||||
|
NSLog(@"frame: %@", img_path);
|
||||||
|
#if __OSX__
|
||||||
|
NSImage *image = [[NSImage alloc] initWithContentsOfFile:img_path];
|
||||||
|
if (!image)
|
||||||
|
break;
|
||||||
|
NSRect imageRect = NSMakeRect(0, 0, image.size.width, image.size.height);
|
||||||
|
CGImageRef cgImage = [image CGImageForProposedRect:&imageRect context:NULL hints:nil];
|
||||||
|
#elif __IOS__
|
||||||
|
UIImage* image = [UIImage imageNamed:img_path];
|
||||||
|
if (!image)
|
||||||
|
break;
|
||||||
|
CGImageRef cgImage = image.CGImage;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
|
||||||
|
[NSNumber numberWithBool:YES], kCVPixelBufferCGImageCompatibilityKey,
|
||||||
|
[NSNumber numberWithBool:YES], kCVPixelBufferCGBitmapContextCompatibilityKey, nil];
|
||||||
|
CGSize sz = image.size;
|
||||||
|
CVPixelBufferRef pxbuffer = NULL;
|
||||||
|
{
|
||||||
|
CGImageRef image = cgImage;
|
||||||
|
CGSize size = sz;
|
||||||
|
CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault, size.width, size.height, kCVPixelFormatType_32ARGB, (__bridge CFDictionaryRef) options, &pxbuffer);
|
||||||
|
// CVReturn status = CVPixelBufferPoolCreatePixelBuffer(NULL, adaptor.pixelBufferPool, &pxbuffer);
|
||||||
|
|
||||||
|
//NSParameterAssert(status == kCVReturnSuccess && pxbuffer != NULL);
|
||||||
|
|
||||||
|
CVPixelBufferLockBaseAddress(pxbuffer, 0);
|
||||||
|
void *pxdata = CVPixelBufferGetBaseAddress(pxbuffer);
|
||||||
|
//NSParameterAssert(pxdata != NULL);
|
||||||
|
|
||||||
|
CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();
|
||||||
|
CGContextRef context = CGBitmapContextCreate(pxdata, size.width, size.height, 8, 4*size.width, rgbColorSpace, kCGImageAlphaPremultipliedFirst);
|
||||||
|
//NSParameterAssert(context);
|
||||||
|
|
||||||
|
CGContextDrawImage(context, CGRectMake(0, 0, CGImageGetWidth(image), CGImageGetHeight(image)), image);
|
||||||
|
|
||||||
|
CGColorSpaceRelease(rgbColorSpace);
|
||||||
|
CGContextRelease(context);
|
||||||
|
|
||||||
|
CVPixelBufferUnlockBaseAddress(pxbuffer, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
t.value = i;
|
||||||
|
if (![_pixelBufferAdaptor appendPixelBuffer:pxbuffer withPresentationTime:t])
|
||||||
|
{
|
||||||
|
NSLog(@"error %@", [writer.error localizedFailureReason]);
|
||||||
|
}
|
||||||
|
CFRelease(pxbuffer);
|
||||||
|
|
||||||
|
progress++;
|
||||||
|
pb->m_progress->SetWidthP((float)progress / tot * 100.f);
|
||||||
|
async_update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[input markAsFinished];
|
||||||
|
[writer finishWritingWithCompletionHandler:^{
|
||||||
|
NSString* path = [NSString stringWithFormat:@"%s/out.mp4", rec_path.c_str()];
|
||||||
|
NSLog(@"saved video %@", path);
|
||||||
|
#if __IOS__
|
||||||
|
if (UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(path))
|
||||||
|
{
|
||||||
|
NSLog(@"saving to camera roll");
|
||||||
|
UISaveVideoAtPathToSavedPhotosAlbum(path, nil, nil, nil);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (writer.status == AVAssetWriterStatusFailed)
|
||||||
|
{
|
||||||
|
NSLog(@"failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
pb->destroy();
|
||||||
|
async_update();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void App::rec_loop()
|
||||||
|
{
|
||||||
|
rec_running = true;
|
||||||
|
while(rec_running)
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(rec_mutex);
|
||||||
|
rec_cv.wait(lock);
|
||||||
|
if (!rec_running)
|
||||||
|
break;
|
||||||
|
if (!rec_frames.empty())
|
||||||
|
{
|
||||||
|
if (rec_frames.front())
|
||||||
|
{
|
||||||
|
auto inverted = std::make_unique<uint8_t[]>(width*height*4);
|
||||||
|
for (int y = height - 1, y1 = 0; y >= 0; y--, y1++)
|
||||||
|
{
|
||||||
|
uint8_t* dst = &inverted[y * width * 4];
|
||||||
|
uint8_t* src = &rec_frames.front()[y1 * width * 4];
|
||||||
|
std::copy_n(src, (int)width * 4, dst);
|
||||||
|
}
|
||||||
|
char path[256];
|
||||||
|
snprintf(path, sizeof(path), "%s/%04d.jpg", rec_path.c_str(), rec_count);
|
||||||
|
LOG("writing %s", path);
|
||||||
|
jpge::params params;
|
||||||
|
params.m_quality = 75;
|
||||||
|
bool saved = jpge::compress_image_to_jpeg_file(path, width, height, 4, inverted.get(), params);
|
||||||
|
if (!saved)
|
||||||
|
{
|
||||||
|
LOG("error writing the frame");
|
||||||
|
rec_running = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rec_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rec_frames.pop_front();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
19
engine/app.h
19
engine/app.h
@@ -36,6 +36,15 @@ class App
|
|||||||
public:
|
public:
|
||||||
static App I;
|
static App I;
|
||||||
std::string data_path{ "." };
|
std::string data_path{ "." };
|
||||||
|
|
||||||
|
std::string rec_path{ "." };
|
||||||
|
std::thread rec_thread;
|
||||||
|
bool rec_running = false;
|
||||||
|
int rec_count = 0;
|
||||||
|
std::mutex rec_mutex;
|
||||||
|
std::condition_variable rec_cv;
|
||||||
|
std::deque<std::unique_ptr<uint8_t[]>> rec_frames;
|
||||||
|
|
||||||
Sampler sampler;
|
Sampler sampler;
|
||||||
Texture2D tex;
|
Texture2D tex;
|
||||||
LayoutManager layout;
|
LayoutManager layout;
|
||||||
@@ -94,7 +103,6 @@ public:
|
|||||||
void create();
|
void create();
|
||||||
void terminate();
|
void terminate();
|
||||||
void clear();
|
void clear();
|
||||||
void update_memory_usage(size_t bytes);
|
|
||||||
void update(float dt);
|
void update(float dt);
|
||||||
void async_start();
|
void async_start();
|
||||||
void async_update();
|
void async_update();
|
||||||
@@ -113,12 +121,19 @@ public:
|
|||||||
bool key_up(kKey key);
|
bool key_up(kKey key);
|
||||||
bool key_char(char key);
|
bool key_char(char key);
|
||||||
|
|
||||||
|
void rec_clear();
|
||||||
|
void rec_loop();
|
||||||
|
void rec_start();
|
||||||
|
void rec_stop();
|
||||||
|
void rec_export(std::string path);
|
||||||
|
|
||||||
void init_toolbar_main();
|
void init_toolbar_main();
|
||||||
void init_toolbar_draw();
|
void init_toolbar_draw();
|
||||||
void init_sidebar();
|
void init_sidebar();
|
||||||
void init_menu_file();
|
void init_menu_file();
|
||||||
void init_menu_edit();
|
void init_menu_edit();
|
||||||
void init_menu_layer();
|
void init_menu_layer();
|
||||||
|
void init_menu_timelapse();
|
||||||
void dialog_newdoc();
|
void dialog_newdoc();
|
||||||
void dialog_save();
|
void dialog_save();
|
||||||
void dialog_save_ver();
|
void dialog_save_ver();
|
||||||
@@ -137,6 +152,8 @@ public:
|
|||||||
|
|
||||||
void brush_update();
|
void brush_update();
|
||||||
void title_update(std::string name, int resolution);
|
void title_update(std::string name, int resolution);
|
||||||
|
void update_memory_usage(size_t bytes);
|
||||||
|
void update_rec_frames();
|
||||||
|
|
||||||
void cmd_convert(std::string pano_path, std::string out_path);
|
void cmd_convert(std::string pano_path, std::string out_path);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -430,6 +430,51 @@ void App::init_menu_edit()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void App::init_menu_timelapse()
|
||||||
|
{
|
||||||
|
if (auto* menu_file = layout[main_id]->find<NodeButtonCustom>("menu-timelapse"))
|
||||||
|
{
|
||||||
|
menu_file->on_click = [=](Node*) {
|
||||||
|
glm::vec2 pos = menu_file->m_pos + glm::vec2(0, menu_file->m_size.y);
|
||||||
|
popup = (NodePopupMenu*)layout[const_hash("timelapse-menu")]->m_children[0]->clone();
|
||||||
|
popup->SetPositioning(YGPositionTypeAbsolute);
|
||||||
|
popup->SetPosition(pos.x, pos.y);
|
||||||
|
layout[main_id]->add_child(popup);
|
||||||
|
layout[main_id]->update();
|
||||||
|
popup->mouse_capture();
|
||||||
|
popup->m_mouse_ignore = false;
|
||||||
|
popup->m_flood_events = true;
|
||||||
|
popup->m_capture_children = false;
|
||||||
|
|
||||||
|
if (auto item = popup->find<NodeButtonCustom>("timelapse-start"))
|
||||||
|
{
|
||||||
|
if (auto text = popup->find<NodeText>("menu-label"))
|
||||||
|
{
|
||||||
|
text->set_text(App::I.rec_running ? "Stop Recording" : "Start Recording");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
popup->find<NodeButtonCustom>("timelapse-start")->on_click = [this](Node*) {
|
||||||
|
App::I.rec_running ? App::I.rec_stop() : App::I.rec_start();
|
||||||
|
popup->mouse_release();
|
||||||
|
popup->destroy();
|
||||||
|
};
|
||||||
|
|
||||||
|
popup->find<NodeButtonCustom>("timelapse-clear")->on_click = [this](Node*) {
|
||||||
|
App::I.rec_clear();
|
||||||
|
popup->mouse_release();
|
||||||
|
popup->destroy();
|
||||||
|
};
|
||||||
|
|
||||||
|
popup->find<NodeButtonCustom>("timelapse-export")->on_click = [this](Node*) {
|
||||||
|
popup->mouse_release();
|
||||||
|
popup->destroy();
|
||||||
|
App::I.rec_export("");
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void App::brush_update()
|
void App::brush_update()
|
||||||
{
|
{
|
||||||
// brushes->select_brush(canvas->m_brush.id);
|
// brushes->select_brush(canvas->m_brush.id);
|
||||||
@@ -549,6 +594,7 @@ void App::initLayout()
|
|||||||
init_menu_file();
|
init_menu_file();
|
||||||
init_menu_edit();
|
init_menu_edit();
|
||||||
init_menu_layer();
|
init_menu_layer();
|
||||||
|
init_menu_timelapse();
|
||||||
|
|
||||||
Brush b;
|
Brush b;
|
||||||
b.m_tex_id = brushes->get_texture_id(0);
|
b.m_tex_id = brushes->get_texture_id(0);
|
||||||
|
|||||||
@@ -163,11 +163,11 @@ class ActionStroke : public Action
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
std::unique_ptr<Stroke> m_stroke;
|
std::unique_ptr<Stroke> m_stroke;
|
||||||
std::unique_ptr<uint8_t[]> m_image[6];
|
std::unique_ptr<uint8_t[]> m_image[6] = SIXPLETTE(nullptr);
|
||||||
glm::ivec4 m_old_box[6];
|
glm::ivec4 m_old_box[6] = SIXPLETTE(glm::ivec4(0));
|
||||||
bool m_old_dirty[6];
|
bool m_old_dirty[6] = SIXPLETTE(false);
|
||||||
glm::ivec4 m_box[6];
|
glm::ivec4 m_box[6] = SIXPLETTE(glm::ivec4(0));
|
||||||
bool m_dirty[6];
|
bool m_dirty[6] = SIXPLETTE(false);
|
||||||
bool clear_layer = false;
|
bool clear_layer = false;
|
||||||
int m_layer_idx;
|
int m_layer_idx;
|
||||||
Canvas* m_canvas;
|
Canvas* m_canvas;
|
||||||
|
|||||||
@@ -56,6 +56,8 @@ void Node::watch(std::function<void(Node*)> observer)
|
|||||||
void Node::destroy()
|
void Node::destroy()
|
||||||
{
|
{
|
||||||
m_destroyed = true;
|
m_destroyed = true;
|
||||||
|
mouse_release();
|
||||||
|
key_release();
|
||||||
}
|
}
|
||||||
|
|
||||||
Node* Node::root()
|
Node* Node::root()
|
||||||
|
|||||||
@@ -54,9 +54,9 @@ kEventResult NodeButtonCustom::handle_event(Event* e)
|
|||||||
#else
|
#else
|
||||||
m_color = m_mouse_inside ? color_hover : color_normal;
|
m_color = m_mouse_inside ? color_hover : color_normal;
|
||||||
#endif
|
#endif
|
||||||
|
mouse_release();
|
||||||
if (m_mouse_inside && on_click != nullptr)
|
if (m_mouse_inside && on_click != nullptr)
|
||||||
on_click(this);
|
on_click(this);
|
||||||
mouse_release();
|
|
||||||
break;
|
break;
|
||||||
case kEventType::MouseCancel:
|
case kEventType::MouseCancel:
|
||||||
m_color = color_normal;
|
m_color = color_normal;
|
||||||
|
|||||||
10
engine/pch.h
10
engine/pch.h
@@ -11,7 +11,8 @@
|
|||||||
#define __IOS__ 1
|
#define __IOS__ 1
|
||||||
#include <CoreFoundation/CoreFoundation.h>
|
#include <CoreFoundation/CoreFoundation.h>
|
||||||
#ifdef __OBJC__
|
#ifdef __OBJC__
|
||||||
#include <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
|
#import <AVFoundation/AVFoundation.h>
|
||||||
#import <UIKit/UIKit.h>
|
#import <UIKit/UIKit.h>
|
||||||
#import <GLKit/GLKit.h>
|
#import <GLKit/GLKit.h>
|
||||||
#endif
|
#endif
|
||||||
@@ -23,7 +24,8 @@
|
|||||||
#define __IOS__ 1
|
#define __IOS__ 1
|
||||||
#include <CoreFoundation/CoreFoundation.h>
|
#include <CoreFoundation/CoreFoundation.h>
|
||||||
#ifdef __OBJC__
|
#ifdef __OBJC__
|
||||||
#include <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
|
#import <AVFoundation/AVFoundation.h>
|
||||||
#import <UIKit/UIKit.h>
|
#import <UIKit/UIKit.h>
|
||||||
#import <GLKit/GLKit.h>
|
#import <GLKit/GLKit.h>
|
||||||
#endif
|
#endif
|
||||||
@@ -33,6 +35,10 @@
|
|||||||
#else
|
#else
|
||||||
#define TARGET_OS_OSX 1
|
#define TARGET_OS_OSX 1
|
||||||
#define __OSX__ 1
|
#define __OSX__ 1
|
||||||
|
#ifdef __OBJC__
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#import <AVFoundation/AVFoundation.h>
|
||||||
|
#endif
|
||||||
#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"
|
||||||
|
|||||||
Reference in New Issue
Block a user