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

simplify impl of capture(). Fixes #33

parent 5a34d05c
......@@ -7,7 +7,6 @@
@property (nonatomic) BOOL opaque;
@property (nonatomic) BOOL autoRedraw;
@property (nonatomic) BOOL eventsThrough;
@property (nonatomic) int captureNextFrameId;
@property (nonatomic) BOOL visibleContent;
@property (nonatomic) NSNumber *nbContentTextures;
@property (nonatomic) NSNumber *renderId;
......@@ -18,4 +17,6 @@
- (instancetype)initWithBridge:(RCTBridge *)bridge;
- (void) capture:(RCTResponseSenderBlock)callback;
@end
......@@ -34,6 +34,8 @@ NSString* srcResource (id res)
GLRenderData *_renderData;
NSMutableArray *_captureListeners;
NSArray *_contentTextures;
NSDictionary *_images; // This caches the currently used images (imageSrc -> GLReactImage)
......@@ -48,8 +50,6 @@ NSString* srcResource (id res)
NSTimer *animationTimer;
int _lastCaptureId;
BOOL _needSync;
}
......@@ -59,8 +59,8 @@ NSString* srcResource (id res)
_bridge = bridge;
_images = @{};
_preloaded = [[NSMutableArray alloc] init];
_captureListeners = [[NSMutableArray alloc] init];
_preloadingDone = false;
_lastCaptureId = 0;
self.context = [bridge.rnglContext getContext];
self.contentScaleFactor = RCTScreenScale();
}
......@@ -71,6 +71,12 @@ RCT_NOT_IMPLEMENTED(-init)
//// Props Setters
- (void) capture:(RCTResponseSenderBlock)callback
{
[_captureListeners addObject:callback];
[self setNeedsDisplay];
}
-(void)setImagesToPreload:(NSArray *)imagesToPreload
{
if (_preloadingDone) return;
......@@ -139,12 +145,6 @@ RCT_NOT_IMPLEMENTED(-init)
_nbContentTextures = nbContentTextures;
}
- (void)setCaptureNextFrameId:(int)captureNextFrameId
{
_captureNextFrameId = captureNextFrameId;
[self setNeedsDisplay];
}
//// Sync methods (called from props setters)
- (void) syncEventsThrough
......@@ -322,9 +322,12 @@ RCT_NOT_IMPLEMENTED(-init)
else {
[self render];
_deferredRendering = false;
if (_captureNextFrameId > _lastCaptureId) {
_lastCaptureId ++;
int id = _lastCaptureId;
unsigned long nbCaptureListeners = [_captureListeners count];
if (nbCaptureListeners > 0) {
NSArray *listeners = _captureListeners;
_captureListeners = [[NSMutableArray alloc] init];
dispatch_async(dispatch_get_main_queue(), ^{ // snapshot not allowed in render tick. defer it.
if (!weakSelf) return;
UIImage *frameImage = [weakSelf snapshot];
......@@ -332,7 +335,10 @@ RCT_NOT_IMPLEMENTED(-init)
NSString *frame =
[NSString stringWithFormat:@"data:image/png;base64,%@",
[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 "GLCanvas.h"
#import "RCTConvert+GLData.h"
#import "RCTSparseArray.h"
#import "RCTUIManager.h"
#import "RCTLog.h"
#import <UIKit/UIKit.h>
......@@ -21,7 +23,6 @@ RCT_EXPORT_VIEW_PROPERTY(opaque, BOOL);
RCT_EXPORT_VIEW_PROPERTY(autoRedraw, BOOL);
RCT_EXPORT_VIEW_PROPERTY(eventsThrough, BOOL);
RCT_EXPORT_VIEW_PROPERTY(visibleContent, BOOL);
RCT_EXPORT_VIEW_PROPERTY(captureNextFrameId, int);
RCT_EXPORT_VIEW_PROPERTY(data, GLData);
RCT_EXPORT_VIEW_PROPERTY(renderId, NSNumber);
RCT_EXPORT_VIEW_PROPERTY(imagesToPreload, NSArray);
......@@ -29,22 +30,19 @@ RCT_EXPORT_VIEW_PROPERTY(onLoad, BOOL);
RCT_EXPORT_VIEW_PROPERTY(onProgress, BOOL);
RCT_EXPORT_VIEW_PROPERTY(onChange, BOOL);
/* TODO
RCT_EXPORT_METHOD(capture:
(nonnull NSNumber *)reactTag
callback:(RCTResponseSenderBlock)callback)
{
UIView *view = [self.bridge.uiManager viewForReactTag:reactTag];
if ([view isKindOfClass:[GLCanvas class]]) {
[((GLCanvas*)view) capture: callback];
}
else {
RCT_EXPORT_METHOD(capture: (nonnull NSNumber *)reactTag callback:(RCTResponseSenderBlock)callback)
{
[self.bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry) {
GLCanvas *view = viewRegistry[reactTag];
if (![view isKindOfClass:[GLCanvas class]]) {
RCTLog(@"expecting UIView, got: %@", view);
callback(@[@"view is not a GLCanvas"]);
}
else {
[view capture:callback];
}
*/
}];
}
- (UIView *)view
{
......
......@@ -34,9 +34,9 @@
/* Begin PBXFileReference section */
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>"; };
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>"; };
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>"; };
......
......@@ -2,7 +2,8 @@ const React = require("react-native");
const {
Component,
requireNativeComponent
requireNativeComponent,
NativeModules: { GLCanvasManager }
} = React;
const GLCanvasNative = requireNativeComponent("GLCanvas", GLCanvas);
......@@ -10,47 +11,21 @@ const GLCanvasNative = requireNativeComponent("GLCanvas", GLCanvas);
class GLCanvas extends Component {
constructor (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) {
this._captureListeners[this._captureId].push(cb);
this.requestCapture();
}
onCaptureFrame ({ nativeEvent: {frame, id} }) {
if (id in this._captureListeners) {
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 });
GLCanvasManager.capture(
React.findNodeHandle(this.refs.native),
(error, frame) => {
if (error) console.error(error); // eslint-disable-line no-console
else cb(frame);
});
}
render () {
const { width, height, ...restProps } = this.props;
const { captureNextFrameId } = this.state;
return <GLCanvasNative
ref="native"
{...restProps}
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