From efe635cb84933c9dea07169a324183e5c449bef3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Renaudeau?= Date: Mon, 28 Dec 2015 14:41:20 +0100 Subject: [PATCH] Fix onLoad to be triggered when new images are loading See https://github.com/ProjectSeptemberInc/gl-react/issues/38 --- Examples/AdvancedEffects/android/app/app.iml | 2 +- .../xcschemes/AdvancedEffects.xcscheme | 18 ++++- Examples/AdvancedEffects/src/Banner.js | 4 +- Examples/AdvancedEffects/src/Intro.js | 4 +- Examples/AdvancedEffects/src/Vignette.js | 1 + Examples/Hearts/android/app/app.iml | 7 ++ Examples/android/RNGL.iml | 2 +- android/RNGL.iml | 2 +- .../com/projectseptember/RNGL/GLCanvas.java | 78 +++++++++++-------- ios/GLCanvas.m | 78 ++++++++++++------- 10 files changed, 126 insertions(+), 70 deletions(-) diff --git a/Examples/AdvancedEffects/android/app/app.iml b/Examples/AdvancedEffects/android/app/app.iml index 2cd6263..04987cf 100644 --- a/Examples/AdvancedEffects/android/app/app.iml +++ b/Examples/AdvancedEffects/android/app/app.iml @@ -97,8 +97,8 @@ - + diff --git a/Examples/AdvancedEffects/ios/AdvancedEffects.xcodeproj/xcshareddata/xcschemes/AdvancedEffects.xcscheme b/Examples/AdvancedEffects/ios/AdvancedEffects.xcodeproj/xcshareddata/xcschemes/AdvancedEffects.xcscheme index fc0591b..0888e64 100644 --- a/Examples/AdvancedEffects/ios/AdvancedEffects.xcodeproj/xcshareddata/xcschemes/AdvancedEffects.xcscheme +++ b/Examples/AdvancedEffects/ios/AdvancedEffects.xcodeproj/xcshareddata/xcschemes/AdvancedEffects.xcscheme @@ -37,10 +37,10 @@ + shouldUseLaunchSchemeArgsEnv = "YES"> @@ -62,15 +62,18 @@ ReferencedContainer = "container:AdvancedEffects.xcodeproj"> + + @@ -82,14 +85,21 @@ ReferencedContainer = "container:AdvancedEffects.xcodeproj"> + + + + diff --git a/Examples/AdvancedEffects/src/Banner.js b/Examples/AdvancedEffects/src/Banner.js index c9f5285..8f41288 100644 --- a/Examples/AdvancedEffects/src/Banner.js +++ b/Examples/AdvancedEffects/src/Banner.js @@ -27,7 +27,9 @@ void main( void ) { class Banner extends React.Component { render () { const { width, height, time } = this.props; - return console.log("Banner onLoad")}> + return console.log("Banner onLoad")} + onProgress={e => console.log("Banner onProgress", e.nativeEvent)}> ; } diff --git a/Examples/AdvancedEffects/src/Intro.js b/Examples/AdvancedEffects/src/Intro.js index 6628298..94af9f9 100644 --- a/Examples/AdvancedEffects/src/Intro.js +++ b/Examples/AdvancedEffects/src/Intro.js @@ -40,7 +40,9 @@ void main() { class Intro extends React.Component { render () { const { time, fps, width, height } = this.props; - return + return console.log("Intro onLoad")} + onProgress={e => console.log("Intro onProgress", e.nativeEvent)}> true} onMoveShouldSetResponder={() => true} onLoad={() => console.log("Vignette onLoad")} + onProgress={e => console.log("Vignette onProgress", e.nativeEvent)} onResponderMove={this.onResponderMove}> + + + + @@ -77,10 +81,13 @@ + + + diff --git a/Examples/android/RNGL.iml b/Examples/android/RNGL.iml index e3cb714..d90b763 100644 --- a/Examples/android/RNGL.iml +++ b/Examples/android/RNGL.iml @@ -85,8 +85,8 @@ - + diff --git a/android/RNGL.iml b/android/RNGL.iml index 0ee7994..da94af0 100644 --- a/android/RNGL.iml +++ b/android/RNGL.iml @@ -1,5 +1,5 @@ - + diff --git a/android/src/main/java/com/projectseptember/RNGL/GLCanvas.java b/android/src/main/java/com/projectseptember/RNGL/GLCanvas.java index d7a8919..40cf63c 100644 --- a/android/src/main/java/com/projectseptember/RNGL/GLCanvas.java +++ b/android/src/main/java/com/projectseptember/RNGL/GLCanvas.java @@ -33,10 +33,12 @@ import java.nio.FloatBuffer; import java.nio.IntBuffer; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Queue; +import java.util.Set; import java.util.concurrent.Executor; import javax.microedition.khronos.egl.EGLConfig; @@ -47,7 +49,8 @@ public class GLCanvas extends GLSurfaceView private ReactContext reactContext; private RNGLContext rnglContext; - private boolean preloadingDone = false; + private boolean dirtyOnLoad = true; + private boolean neverRendered = true; private boolean deferredRendering = false; private GLRenderData renderData; private int defaultFBO; @@ -127,11 +130,15 @@ public class GLCanvas extends GLSurfaceView if (contentTextures.size() != this.nbContentTextures) resizeUniformContentTextures(nbContentTextures); - if (!preloadingDone) { - glClearColor(0.0f, 0.0f, 0.0f, 0.0f); - glClear(GL_COLOR_BUFFER_BIT); + if (haveRemainingToPreload()) { + if (neverRendered) { + neverRendered = false; + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + glClear(GL_COLOR_BUFFER_BIT); + } return; } + neverRendered = false; final boolean shouldRenderNow = deferredRendering || autoRedraw || nbContentTextures == 0; if (nbContentTextures > 0) { @@ -161,6 +168,15 @@ public class GLCanvas extends GLSurfaceView } } + private boolean haveRemainingToPreload() { + for (Uri uri: imagesToPreload) { + if (!preloaded.contains(uri)) { + return true; + } + } + return false; + } + public void setNbContentTextures(int n) { this.nbContentTextures = n; requestRender(); @@ -168,7 +184,7 @@ public class GLCanvas extends GLSurfaceView public void setRenderId(int renderId) { if (nbContentTextures > 0) { - if (preloadingDone) syncContentBitmaps(); + if (!haveRemainingToPreload()) syncContentBitmaps(); requestRender(); } } @@ -190,25 +206,18 @@ public class GLCanvas extends GLSurfaceView public void setData (GLData data) { this.data = data; - if (preloadingDone) syncContentBitmaps(); + if (!haveRemainingToPreload()) syncContentBitmaps(); requestSyncData(); } public void setImagesToPreload (ReadableArray imagesToPreloadRA) { - if (preloadingDone) return; List imagesToPreload = new ArrayList<>(); for (int i=0; i images = new HashMap<>(); GLRenderData node = recSyncData(data, images); if (node == null) return false; + Set imagesGone = diff(this.images.keySet(), images.keySet()); renderData = node; this.images = images; + this.preloaded.removeAll(imagesGone); return true; } @@ -652,6 +657,11 @@ public class GLCanvas extends GLSurfaceView recRender(renderData); glDisable(GL_BLEND); glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO); + + if (dirtyOnLoad && !haveRemainingToPreload()) { + dirtyOnLoad = false; + dispatchOnLoad(); + } } private void dispatchOnCaptureFrame (String frame) { @@ -666,7 +676,7 @@ public class GLCanvas extends GLSurfaceView private void dispatchOnProgress (double progress, int loaded, int total) { WritableMap event = Arguments.createMap(); - event.putDouble("progress", progress); + event.putDouble("progress", Double.isNaN(progress) ? 0.0 : progress); event.putInt("loaded", loaded); event.putInt("total", total); ReactContext reactContext = (ReactContext)getContext(); @@ -732,4 +742,10 @@ public class GLCanvas extends GLSurfaceView mPointerEvents = pointerEvents; } + static Set diff(Set a, Set b) { + Set d = new HashSet<>(); + d.addAll(a); + d.removeAll(b); + return d; + } } diff --git a/ios/GLCanvas.m b/ios/GLCanvas.m index 2af6583..9250e7d 100644 --- a/ios/GLCanvas.m +++ b/ios/GLCanvas.m @@ -26,6 +26,16 @@ NSString* srcResource (id res) return src; } +NSArray* diff (NSArray* a, NSArray* b) { + NSMutableArray *arr = [[NSMutableArray alloc] init]; + for (NSString* k in a) { + if (![b containsObject:k]) { + [arr addObject:k]; + } + } + return arr; +} + // For reference, see implementation of gl-shader's GLCanvas @implementation GLCanvas @@ -47,7 +57,8 @@ NSString* srcResource (id res) GLint defaultFBO; NSMutableArray *_preloaded; - BOOL _preloadingDone; + BOOL _dirtyOnLoad; + BOOL _neverRendered; NSTimer *animationTimer; @@ -61,7 +72,8 @@ NSString* srcResource (id res) _images = @{}; _preloaded = [[NSMutableArray alloc] init]; _captureFrameRequested = false; - _preloadingDone = false; + _dirtyOnLoad = true; + _neverRendered = true; self.context = [bridge.rnglContext getContext]; self.contentScaleFactor = RCTScreenScale(); } @@ -80,15 +92,8 @@ RCT_NOT_IMPLEMENTED(-init) -(void)setImagesToPreload:(NSArray *)imagesToPreload { - if (_preloadingDone) return; - if ([imagesToPreload count] == 0) { - [self dispatchOnLoad]; - _preloadingDone = true; - } - else { - _preloadingDone = false; - } _imagesToPreload = imagesToPreload; + [self requestSyncData]; } - (void)setOpaque:(BOOL)opaque @@ -151,7 +156,6 @@ RCT_NOT_IMPLEMENTED(-init) - (void)syncData { - [EAGLContext setCurrentContext:self.context]; @autoreleasepool { NSDictionary *prevImages = _images; @@ -270,6 +274,9 @@ RCT_NOT_IMPLEMENTED(-init) if (res != nil) { _renderData = traverseTree(_data); _images = images; + for (NSString *src in diff([prevImages allKeys], [images allKeys])) { + [_preloaded removeObject:src]; + } } } } @@ -303,6 +310,16 @@ RCT_NOT_IMPLEMENTED(-init) } } +- (BOOL)haveRemainingToPreload +{ + for (id res in _imagesToPreload) { + if (![_preloaded containsObject:srcResource(res)]) { + return true; + } + } + return false; +} + //// Draw @@ -316,11 +333,16 @@ RCT_NOT_IMPLEMENTED(-init) self.layer.opaque = _opaque; - if (!_preloadingDone) { - glClearColor(0.0, 0.0, 0.0, 0.0); - glClear(GL_COLOR_BUFFER_BIT); + if ([self haveRemainingToPreload]) { + if (_neverRendered) { + _neverRendered = false; + glClearColor(0.0, 0.0, 0.0, 0.0); + glClear(GL_COLOR_BUFFER_BIT); + } return; } + _neverRendered = false; + BOOL needsDeferredRendering = _nbContentTextures > 0 && !_autoRedraw; if (needsDeferredRendering && !_deferredRendering) { dispatch_async(dispatch_get_main_queue(), ^{ @@ -407,6 +429,11 @@ RCT_NOT_IMPLEMENTED(-init) recDraw(_renderData); glDisable(GL_BLEND); glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO); + + if (_dirtyOnLoad && ![self haveRemainingToPreload]) { + _dirtyOnLoad = false; + [self dispatchOnLoad]; + } } } @@ -414,22 +441,13 @@ RCT_NOT_IMPLEMENTED(-init) - (void)onImageLoad:(NSString *)loaded { - if (!_preloadingDone) { - [_preloaded addObject:loaded]; - int count = [self countPreloaded]; - int total = (int) [_imagesToPreload count]; - double progress = ((double) count) / ((double) total); - [self dispatchOnProgress:progress withLoaded:count withTotal:total]; - if (count == total) { - [self dispatchOnLoad]; - _preloadingDone = true; - [self requestSyncData]; - } - } - else { - // Any texture image load will trigger a future re-sync of data (if no preloaded) - [self requestSyncData]; - } + [_preloaded addObject:loaded]; + int count = [self countPreloaded]; + int total = (int) [_imagesToPreload count]; + double progress = ((double) count) / ((double) total); + [self dispatchOnProgress:progress withLoaded:count withTotal:total]; + _dirtyOnLoad = true; + [self requestSyncData]; } - (int)countPreloaded -- 2.26.2