Commit d4336bfb authored by Gaëtan Renaudeau's avatar Gaëtan Renaudeau

simplify impl of capture(). Fixes #33

parent 5a34d05c
...@@ -7,7 +7,6 @@ ...@@ -7,7 +7,6 @@
@property (nonatomic) BOOL opaque; @property (nonatomic) BOOL opaque;
@property (nonatomic) BOOL autoRedraw; @property (nonatomic) BOOL autoRedraw;
@property (nonatomic) BOOL eventsThrough; @property (nonatomic) BOOL eventsThrough;
@property (nonatomic) int captureNextFrameId;
@property (nonatomic) BOOL visibleContent; @property (nonatomic) BOOL visibleContent;
@property (nonatomic) NSNumber *nbContentTextures; @property (nonatomic) NSNumber *nbContentTextures;
@property (nonatomic) NSNumber *renderId; @property (nonatomic) NSNumber *renderId;
...@@ -18,4 +17,6 @@ ...@@ -18,4 +17,6 @@
- (instancetype)initWithBridge:(RCTBridge *)bridge; - (instancetype)initWithBridge:(RCTBridge *)bridge;
- (void) capture:(RCTResponseSenderBlock)callback;
@end @end
...@@ -34,6 +34,8 @@ NSString* srcResource (id res) ...@@ -34,6 +34,8 @@ NSString* srcResource (id res)
GLRenderData *_renderData; GLRenderData *_renderData;
NSMutableArray *_captureListeners;
NSArray *_contentTextures; NSArray *_contentTextures;
NSDictionary *_images; // This caches the currently used images (imageSrc -> GLReactImage) NSDictionary *_images; // This caches the currently used images (imageSrc -> GLReactImage)
...@@ -48,8 +50,6 @@ NSString* srcResource (id res) ...@@ -48,8 +50,6 @@ NSString* srcResource (id res)
NSTimer *animationTimer; NSTimer *animationTimer;
int _lastCaptureId;
BOOL _needSync; BOOL _needSync;
} }
...@@ -59,8 +59,8 @@ NSString* srcResource (id res) ...@@ -59,8 +59,8 @@ NSString* srcResource (id res)
_bridge = bridge; _bridge = bridge;
_images = @{}; _images = @{};
_preloaded = [[NSMutableArray alloc] init]; _preloaded = [[NSMutableArray alloc] init];
_captureListeners = [[NSMutableArray alloc] init];
_preloadingDone = false; _preloadingDone = false;
_lastCaptureId = 0;
self.context = [bridge.rnglContext getContext]; self.context = [bridge.rnglContext getContext];
self.contentScaleFactor = RCTScreenScale(); self.contentScaleFactor = RCTScreenScale();
} }
...@@ -71,6 +71,12 @@ RCT_NOT_IMPLEMENTED(-init) ...@@ -71,6 +71,12 @@ RCT_NOT_IMPLEMENTED(-init)
//// Props Setters //// Props Setters
- (void) capture:(RCTResponseSenderBlock)callback
{
[_captureListeners addObject:callback];
[self setNeedsDisplay];
}
-(void)setImagesToPreload:(NSArray *)imagesToPreload -(void)setImagesToPreload:(NSArray *)imagesToPreload
{ {
if (_preloadingDone) return; if (_preloadingDone) return;
...@@ -139,12 +145,6 @@ RCT_NOT_IMPLEMENTED(-init) ...@@ -139,12 +145,6 @@ RCT_NOT_IMPLEMENTED(-init)
_nbContentTextures = nbContentTextures; _nbContentTextures = nbContentTextures;
} }
- (void)setCaptureNextFrameId:(int)captureNextFrameId
{
_captureNextFrameId = captureNextFrameId;
[self setNeedsDisplay];
}
//// Sync methods (called from props setters) //// Sync methods (called from props setters)
- (void) syncEventsThrough - (void) syncEventsThrough
...@@ -322,9 +322,12 @@ RCT_NOT_IMPLEMENTED(-init) ...@@ -322,9 +322,12 @@ RCT_NOT_IMPLEMENTED(-init)
else { else {
[self render]; [self render];
_deferredRendering = false; _deferredRendering = false;
if (_captureNextFrameId > _lastCaptureId) {
_lastCaptureId ++; unsigned long nbCaptureListeners = [_captureListeners count];
int id = _lastCaptureId; if (nbCaptureListeners > 0) {
NSArray *listeners = _captureListeners;
_captureListeners = [[NSMutableArray alloc] init];
dispatch_async(dispatch_get_main_queue(), ^{ // snapshot not allowed in render tick. defer it. dispatch_async(dispatch_get_main_queue(), ^{ // snapshot not allowed in render tick. defer it.
if (!weakSelf) return; if (!weakSelf) return;
UIImage *frameImage = [weakSelf snapshot]; UIImage *frameImage = [weakSelf snapshot];
...@@ -332,7 +335,10 @@ RCT_NOT_IMPLEMENTED(-init) ...@@ -332,7 +335,10 @@ RCT_NOT_IMPLEMENTED(-init)
NSString *frame = NSString *frame =
[NSString stringWithFormat:@"data:image/png;base64,%@", [NSString stringWithFormat:@"data:image/png;base64,%@",
[frameData base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength]]; [frameData base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength]];
[weakSelf dispatchOnCapture:frame withId:id]; for (int i = 0; i < nbCaptureListeners; i++) {
RCTResponseSenderBlock listener = listeners[i];
listener(@[[NSNull null], frame]);
}
}); });
} }
} }
......
#import "GLCanvasManager.h" #import "GLCanvasManager.h"
#import "GLCanvas.h" #import "GLCanvas.h"
#import "RCTConvert+GLData.h" #import "RCTConvert+GLData.h"
#import "RCTSparseArray.h"
#import "RCTUIManager.h"
#import "RCTLog.h" #import "RCTLog.h"
#import <UIKit/UIKit.h> #import <UIKit/UIKit.h>
...@@ -21,7 +23,6 @@ RCT_EXPORT_VIEW_PROPERTY(opaque, BOOL); ...@@ -21,7 +23,6 @@ RCT_EXPORT_VIEW_PROPERTY(opaque, BOOL);
RCT_EXPORT_VIEW_PROPERTY(autoRedraw, BOOL); RCT_EXPORT_VIEW_PROPERTY(autoRedraw, BOOL);
RCT_EXPORT_VIEW_PROPERTY(eventsThrough, BOOL); RCT_EXPORT_VIEW_PROPERTY(eventsThrough, BOOL);
RCT_EXPORT_VIEW_PROPERTY(visibleContent, BOOL); RCT_EXPORT_VIEW_PROPERTY(visibleContent, BOOL);
RCT_EXPORT_VIEW_PROPERTY(captureNextFrameId, int);
RCT_EXPORT_VIEW_PROPERTY(data, GLData); RCT_EXPORT_VIEW_PROPERTY(data, GLData);
RCT_EXPORT_VIEW_PROPERTY(renderId, NSNumber); RCT_EXPORT_VIEW_PROPERTY(renderId, NSNumber);
RCT_EXPORT_VIEW_PROPERTY(imagesToPreload, NSArray); RCT_EXPORT_VIEW_PROPERTY(imagesToPreload, NSArray);
...@@ -29,22 +30,19 @@ RCT_EXPORT_VIEW_PROPERTY(onLoad, BOOL); ...@@ -29,22 +30,19 @@ RCT_EXPORT_VIEW_PROPERTY(onLoad, BOOL);
RCT_EXPORT_VIEW_PROPERTY(onProgress, BOOL); RCT_EXPORT_VIEW_PROPERTY(onProgress, BOOL);
RCT_EXPORT_VIEW_PROPERTY(onChange, BOOL); RCT_EXPORT_VIEW_PROPERTY(onChange, BOOL);
/* TODO RCT_EXPORT_METHOD(capture: (nonnull NSNumber *)reactTag callback:(RCTResponseSenderBlock)callback)
{
RCT_EXPORT_METHOD(capture: [self.bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry) {
(nonnull NSNumber *)reactTag GLCanvas *view = viewRegistry[reactTag];
callback:(RCTResponseSenderBlock)callback) if (![view isKindOfClass:[GLCanvas class]]) {
{ RCTLog(@"expecting UIView, got: %@", view);
UIView *view = [self.bridge.uiManager viewForReactTag:reactTag];
if ([view isKindOfClass:[GLCanvas class]]) {
[((GLCanvas*)view) capture: callback];
}
else {
callback(@[@"view is not a GLCanvas"]); callback(@[@"view is not a GLCanvas"]);
} }
else {
[view capture:callback];
} }
*/ }];
}
- (UIView *)view - (UIView *)view
{ {
......
...@@ -34,9 +34,9 @@ ...@@ -34,9 +34,9 @@
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
346089BA1BEFD0A500C90DB5 /* GLCanvas.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLCanvas.h; sourceTree = "<group>"; }; 346089BA1BEFD0A500C90DB5 /* GLCanvas.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLCanvas.h; sourceTree = "<group>"; };
346089BB1BEFD0A500C90DB5 /* GLCanvas.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GLCanvas.m; sourceTree = "<group>"; }; 346089BB1BEFD0A500C90DB5 /* GLCanvas.m */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.objc; path = GLCanvas.m; sourceTree = "<group>"; tabWidth = 2; };
346089BC1BEFD0A500C90DB5 /* GLCanvasManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLCanvasManager.h; sourceTree = "<group>"; }; 346089BC1BEFD0A500C90DB5 /* GLCanvasManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLCanvasManager.h; sourceTree = "<group>"; };
346089BD1BEFD0A500C90DB5 /* GLCanvasManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GLCanvasManager.m; sourceTree = "<group>"; }; 346089BD1BEFD0A500C90DB5 /* GLCanvasManager.m */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.objc; path = GLCanvasManager.m; sourceTree = "<group>"; tabWidth = 2; };
346089BE1BEFD0A500C90DB5 /* GLData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLData.h; sourceTree = "<group>"; }; 346089BE1BEFD0A500C90DB5 /* GLData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLData.h; sourceTree = "<group>"; };
346089BF1BEFD0A500C90DB5 /* GLData.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GLData.m; sourceTree = "<group>"; }; 346089BF1BEFD0A500C90DB5 /* GLData.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GLData.m; sourceTree = "<group>"; };
346089C01BEFD0A500C90DB5 /* GLFBO.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLFBO.h; sourceTree = "<group>"; }; 346089C01BEFD0A500C90DB5 /* GLFBO.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLFBO.h; sourceTree = "<group>"; };
......
...@@ -2,7 +2,8 @@ const React = require("react-native"); ...@@ -2,7 +2,8 @@ const React = require("react-native");
const { const {
Component, Component,
requireNativeComponent requireNativeComponent,
NativeModules: { GLCanvasManager }
} = React; } = React;
const GLCanvasNative = requireNativeComponent("GLCanvas", GLCanvas); const GLCanvasNative = requireNativeComponent("GLCanvas", GLCanvas);
...@@ -10,47 +11,21 @@ const GLCanvasNative = requireNativeComponent("GLCanvas", GLCanvas); ...@@ -10,47 +11,21 @@ const GLCanvasNative = requireNativeComponent("GLCanvas", GLCanvas);
class GLCanvas extends Component { class GLCanvas extends Component {
constructor (props) { constructor (props) {
super(props); super(props);
this.state = {
captureNextFrameId: 0 // the current id to send to the ObjC part.
};
this._captureId = 1; // track the current id to use for captures. it get incremented when the frame is obtained.
this._captureListeners = { [this._captureId]: [] }; // callbacks by capture id
this._needsCapture = false;
this.handleCapture = this.handleCapture.bind(this);
this.onCaptureFrame = this.onCaptureFrame.bind(this);
} }
captureFrame (cb) { captureFrame (cb) {
this._captureListeners[this._captureId].push(cb); GLCanvasManager.capture(
this.requestCapture(); React.findNodeHandle(this.refs.native),
} (error, frame) => {
onCaptureFrame ({ nativeEvent: {frame, id} }) { if (error) console.error(error); // eslint-disable-line no-console
if (id in this._captureListeners) { else cb(frame);
this._captureListeners[id].forEach(listener => listener(frame)); });
delete this._captureListeners[id];
}
this._captureId ++;
this._captureListeners[this._captureId] = [];
}
requestCapture () {
if (this._needsCapture) return;
this._needsCapture = true;
requestAnimationFrame(this.handleCapture);
}
handleCapture () {
if (!this._needsCapture) return;
this._needsCapture = false;
this.setState({ captureNextFrameId: this._captureId });
} }
render () { render () {
const { width, height, ...restProps } = this.props; const { width, height, ...restProps } = this.props;
const { captureNextFrameId } = this.state;
return <GLCanvasNative return <GLCanvasNative
ref="native" ref="native"
{...restProps} {...restProps}
style={{ width, height }} style={{ width, height }}
captureNextFrameId={captureNextFrameId}
onChange={this.onCaptureFrame} // FIXME using onChange is a current workaround before we migrate to react-native custom callbacks. later, replace with onCaptureNextFrame
/>; />;
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment