Commit 22ed9cf3 authored by Gaëtan Renaudeau's avatar Gaëtan Renaudeau

Bugfixes and Features of 2.17.x

parent f0c5426e
{
"parser": "babel-eslint",
"globals": {
"requestAnimationFrame": true
},
......
......@@ -78,7 +78,7 @@
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.facebook.fresco/fresco/0.8.1/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.facebook.fresco/imagepipeline-okhttp/0.8.1/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.facebook.fresco/imagepipeline/0.8.1/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.facebook.react/react-native/0.16.1/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.facebook.react/react-native/0.17.1/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/org.webkit/android-jsc/r174650/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" />
......@@ -97,15 +97,15 @@
<orderEntry type="library" exported="" name="okio-1.6.0" level="project" />
<orderEntry type="library" exported="" name="stetho-okhttp-1.2.0" level="project" />
<orderEntry type="library" exported="" name="okhttp-2.5.0" level="project" />
<orderEntry type="library" exported="" name="jsr305-3.0.0" level="project" />
<orderEntry type="library" exported="" name="stetho-1.2.0" level="project" />
<orderEntry type="library" exported="" name="jsr305-3.0.0" level="project" />
<orderEntry type="library" exported="" name="jackson-core-2.2.3" level="project" />
<orderEntry type="library" exported="" name="fbcore-0.8.1" level="project" />
<orderEntry type="library" exported="" name="commons-cli-1.2" level="project" />
<orderEntry type="library" exported="" name="recyclerview-v7-23.0.1" level="project" />
<orderEntry type="library" exported="" name="imagepipeline-0.8.1" level="project" />
<orderEntry type="library" exported="" name="react-native-0.17.1" level="project" />
<orderEntry type="library" exported="" name="android-jsc-r174650" level="project" />
<orderEntry type="library" exported="" name="react-native-0.16.1" level="project" />
<orderEntry type="library" exported="" name="fresco-0.8.1" level="project" />
<orderEntry type="library" exported="" name="imagepipeline-okhttp-0.8.1" level="project" />
<orderEntry type="library" exported="" name="bolts-android-1.1.4" level="project" />
......
......@@ -74,7 +74,7 @@ android {
dependencies {
compile fileTree(dir: "libs", include: ["*.jar"])
compile "com.android.support:appcompat-v7:23.0.1"
compile "com.facebook.react:react-native:0.16.+"
compile "com.facebook.react:react-native:0.17.+"
compile project(':RNGL')
}
......@@ -3,6 +3,7 @@ package com.advancedeffects;
import android.app.Activity;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
import com.facebook.react.LifecycleState;
import com.facebook.react.ReactInstanceManager;
......@@ -34,6 +35,8 @@ public class MainActivity extends Activity implements DefaultHardwareBackBtnHand
mReactRootView.startReactApplication(mReactInstanceManager, "AdvancedEffects", null);
setContentView(mReactRootView);
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN);
}
@Override
......
......@@ -9,6 +9,6 @@
"gl-react": "^2.0.2",
"gl-react-native": "file:../..",
"glsl-transitions": "^2015.11.8",
"react-native": "^0.16.0"
"react-native": "^0.17.0"
}
}
......@@ -27,7 +27,7 @@ void main( void ) {
class Banner extends React.Component {
render () {
const { width, height, time } = this.props;
return <Surface width={width} height={height} opaque={false}>
return <Surface width={width} height={height} opaque={false} onLoad={() => console.log("Banner onLoad")}>
<GL.Node shader={shaders.banner} uniforms={{ time: time }} />
</Surface>;
}
......
......@@ -34,7 +34,9 @@ class Slideshow extends React.Component {
const transitionUniforms = this._uniforms;
return <View style={styles.root}>
<Surface width={width} height={height}>
<Surface width={width} height={height}
onLoad={() => console.log("Slideshow onLoad")}
onProgress={e => console.log("Slideshow onProgress", e.nativeEvent)}>
<Transition
progress={transitionProgress}
from={transitionFrom}
......
......@@ -63,6 +63,7 @@ class Vignette extends React.Component {
preload
onStartShouldSetResponder={() => true}
onMoveShouldSetResponder={() => true}
onLoad={() => console.log("Vignette onLoad")}
onResponderMove={this.onResponderMove}>
<GL.Node
shader={shaders.imageVignette}
......
......@@ -77,7 +77,7 @@
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.facebook.fresco/fresco/0.8.1/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.facebook.fresco/imagepipeline-okhttp/0.8.1/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.facebook.fresco/imagepipeline/0.8.1/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.facebook.react/react-native/0.16.1/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.facebook.react/react-native/0.17.1/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/org.webkit/android-jsc/r174650/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" />
......@@ -96,15 +96,15 @@
<orderEntry type="library" exported="" name="okio-1.6.0" level="project" />
<orderEntry type="library" exported="" name="stetho-okhttp-1.2.0" level="project" />
<orderEntry type="library" exported="" name="okhttp-2.5.0" level="project" />
<orderEntry type="library" exported="" name="stetho-1.2.0" level="project" />
<orderEntry type="library" exported="" name="jsr305-3.0.0" level="project" />
<orderEntry type="library" exported="" name="stetho-1.2.0" level="project" />
<orderEntry type="library" exported="" name="jackson-core-2.2.3" level="project" />
<orderEntry type="library" exported="" name="fbcore-0.8.1" level="project" />
<orderEntry type="library" exported="" name="commons-cli-1.2" level="project" />
<orderEntry type="library" exported="" name="recyclerview-v7-23.0.1" level="project" />
<orderEntry type="library" exported="" name="imagepipeline-0.8.1" level="project" />
<orderEntry type="library" exported="" name="react-native-0.17.1" level="project" />
<orderEntry type="library" exported="" name="android-jsc-r174650" level="project" />
<orderEntry type="library" exported="" name="react-native-0.16.1" level="project" />
<orderEntry type="library" exported="" name="fresco-0.8.1" level="project" />
<orderEntry type="library" exported="" name="imagepipeline-okhttp-0.8.1" level="project" />
<orderEntry type="library" exported="" name="bolts-android-1.1.4" level="project" />
......
......@@ -74,7 +74,7 @@ android {
dependencies {
compile fileTree(dir: "libs", include: ["*.jar"])
compile "com.android.support:appcompat-v7:23.0.1"
compile "com.facebook.react:react-native:0.16.+"
compile "com.facebook.react:react-native:0.17.+"
compile project(":RNMaterialKit")
compile project(":RNGL")
......
const { AppRegistry } = require("react-native");
const { AppRegistry, StatusBarIOS } = require("react-native");
const Simple = require("./src");
StatusBarIOS.setHidden(true);
AppRegistry.registerComponent("Simple", () => Simple);
......@@ -8,7 +8,7 @@
"dependencies": {
"gl-react-native": "file:../..",
"gl-react": "^2.0.2",
"react-native": "^0.16.0",
"react-native": "^0.17.0",
"react-native-material-kit": "^0.2.2"
}
}
......@@ -2,6 +2,8 @@ const React = require("react-native");
const GL = require("gl-react");
const {Surface} = require("gl-react-native");
const {PanResponder, UIManager} = React;
const shaders = GL.Shaders.create({
oneFingerResponse: {
frag: `
......@@ -26,44 +28,57 @@ class OneFingerResponse extends React.Component {
super(props);
this.state = {
pressed: 0,
position: [ 0, 0 ]
position: [ 0, 0 ],
surfaceBound: [ 0, 0, 1, 1 ] // x, y, w, h
};
this.onTouchStart = this.onTouchStart.bind(this);
this.onTouchEnd = this.onTouchEnd.bind(this);
this.onTouchMove = this.onTouchMove.bind(this);
}
onTouchStart (evt) {
this.setState({
pressed: 1
});
this.onTouchMove(evt);
}
onTouchMove (evt) {
const { width, height } = this.props;
const { locationX, locationY } = evt.nativeEvent;
this.setState({
position: [
Math.max(0, Math.min(locationX/width, 1)),
Math.max(0, Math.min(1-locationY/height, 1))
]
});
}
onTouchEnd () {
this.setState({
pressed: 0
this._panResponder = PanResponder.create({
onStartShouldSetPanResponder: (evt, gestureState) => true,
onStartShouldSetPanResponderCapture: (evt, gestureState) => true,
onMoveShouldSetPanResponder: (evt, gestureState) => true,
onMoveShouldSetPanResponderCapture: (evt, gestureState) => true,
onPanResponderGrant: (evt, gestureState) =>
UIManager.measure(
React.findNodeHandle(this.refs.surface),
(a, b, w, h, x, y) =>
this.setState({
pressed: 1,
surfaceBound: [x,y,w,h],
position: [ gestureState.x0, gestureState.y0 ]
})),
onPanResponderMove: (evt, gestureState) =>
this.setState({
position: [ gestureState.x0 + gestureState.dx, gestureState.y0 + gestureState.dy ]
}),
onPanResponderTerminationRequest: (evt, gestureState) => true,
onPanResponderRelease: (evt, gestureState) =>
this.setState({
pressed: 0
}),
onPanResponderTerminate: (evt, gestureState) =>
this.setState({
pressed: 0
}),
onShouldBlockNativeResponder: (evt, gestureState) => true
});
}
render () {
const { width, height } = this.props;
const { pressed, position } = this.state;
const { pressed, position:[x,y], surfaceBound: [sx,sy,sw,sh] } = this.state;
const position = [
(x - sx) / sw,
1 - (y - sy) / sh
];
return <Surface
onStartShouldSetResponderCapture={() => true}
onMoveShouldSetResponderCapture={() => true}
onResponderTerminationRequest={() => false}
onResponderGrant={this.onTouchStart}
onResponderMove={this.onTouchMove}
onResponderRelease={this.onTouchEnd}
onResponderTerminate={this.onTouchEnd}
ref="surface"
{...this._panResponder.panHandlers}
width={width}
height={height}>
<GL.Node
......
......@@ -8,6 +8,7 @@ const {
Image,
TextInput,
Component,
TouchableOpacity
} = React;
const { Surface } = require("gl-react-native");
......@@ -84,10 +85,19 @@ class Simple extends Component {
captured: null
};
this.onCapture1 = this.onCapture1.bind(this);
/*
// Crazy stress mode
const self = this;
setTimeout(function loop () {
setTimeout(loop, 100 * Math.random());
self.setState({ current: Math.floor(8 * Math.random()) });
}, 100);
*/
}
onCapture1 () {
this.refs.helloGL.captureFrame(data64 => {
this.refs.helloGL.captureFrame().then(data64 => {
this.setState({ captured: data64 });
});
}
......@@ -108,21 +118,22 @@ class Simple extends Component {
return <View style={styles.container}>
<Text style={styles.title}>
Welcome to GL React Native!
gl-react-native > Simple
</Text>
<Demos onChange={current => this.setState({ current })} value={current}>
<Demo title="1. Hello GL">
<Demo id={1} title="1. Hello GL">
<Surface width={256} height={171} ref="helloGL">
<HelloGL />
</Surface>
<View style={{ paddingTop: 20, alignItems: "center", flexDirection: "row" }}>
<Button onPress={this.onCapture1}>captureFrame()</Button>
{captured && <Image source={{ uri:captured }} style={{ marginLeft: 20, width: 51, height: 34 }} />}
{captured && <Image source={{ uri: captured }} style={{ marginLeft: 20, width: 51, height: 34 }} />}
</View>
{captured && <Text style={{ marginTop: 10, fontSize: 10, fontFamily: "Cochin" }} numberOfLines={1}>{captured.slice(0, 100)}</Text>}
</Demo>
<Demo title="2. Saturate an Image">
<Demo id={2} title="2. Saturate an Image">
<Surface width={256} height={171}>
<Saturation
factor={saturationFactor}
......@@ -156,16 +167,19 @@ class Simple extends Component {
<Demo id={4} current={current} title="4. Progress Indicator">
<View style={{ position: "relative", width: 256, height: 180 }}>
<Image style={{
width: 256,
height: 180,
position: "absolute",
top: 0,
left: 0
}}
source={{ uri: "http://i.imgur.com/qM9BHCy.jpg" }}/>
<View style={{ position: "absolute", top: 0, left: 0 }}>
<Surface width={256} height={180} opaque={false}>
<TouchableOpacity>
<Image source={{ uri: "http://i.imgur.com/qM9BHCy.jpg" }}
style={{
width: 256,
height: 180,
position: "absolute",
top: 0,
left: 0
}}
/>
</TouchableOpacity>
<View pointerEvents="box-none" style={{ position: "absolute", top: 0, left: 0, backgroundColor: "transparent" }}>
<Surface width={256} height={180} opaque={false} eventsThrough>
<PieProgress progress={progress} width={256} height={180} />
</Surface>
</View>
......@@ -217,7 +231,7 @@ class Simple extends Component {
width={256}
height={160}
factor={factor/2}>
<View style={{ width: 256, height: 160, padding: 10, backgroundColor: "#F9F9F9" }}>
<View style={{ width: 256, height: 160, padding: 10, backgroundColor: "#f9f9f9" }}>
<Slider
style={{ height: 80 }}
max={2}
......@@ -235,6 +249,7 @@ class Simple extends Component {
</Blur>
</HueRotate>
</Surface>
<Text>Note: This is highly experimental and not yet performant enough.</Text>
</Demo>
<Demo id={9} current={current} title="9. Texture from array">
......
......@@ -77,7 +77,7 @@
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.facebook.fresco/fresco/0.8.1/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.facebook.fresco/imagepipeline-okhttp/0.8.1/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.facebook.fresco/imagepipeline/0.8.1/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.facebook.react/react-native/0.16.1/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.facebook.react/react-native/0.17.1/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/org.webkit/android-jsc/r174650/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" />
......@@ -96,15 +96,15 @@
<orderEntry type="library" exported="" name="okio-1.6.0" level="project" />
<orderEntry type="library" exported="" name="stetho-okhttp-1.2.0" level="project" />
<orderEntry type="library" exported="" name="okhttp-2.5.0" level="project" />
<orderEntry type="library" exported="" name="stetho-1.2.0" level="project" />
<orderEntry type="library" exported="" name="jsr305-3.0.0" level="project" />
<orderEntry type="library" exported="" name="stetho-1.2.0" level="project" />
<orderEntry type="library" exported="" name="jackson-core-2.2.3" level="project" />
<orderEntry type="library" exported="" name="fbcore-0.8.1" level="project" />
<orderEntry type="library" exported="" name="commons-cli-1.2" level="project" />
<orderEntry type="library" exported="" name="recyclerview-v7-23.0.1" level="project" />
<orderEntry type="library" exported="" name="imagepipeline-0.8.1" level="project" />
<orderEntry type="library" exported="" name="react-native-0.17.1" level="project" />
<orderEntry type="library" exported="" name="android-jsc-r174650" level="project" />
<orderEntry type="library" exported="" name="react-native-0.16.1" level="project" />
<orderEntry type="library" exported="" name="fresco-0.8.1" level="project" />
<orderEntry type="library" exported="" name="imagepipeline-okhttp-0.8.1" level="project" />
<orderEntry type="library" exported="" name="bolts-android-1.1.4" level="project" />
......
......@@ -74,7 +74,7 @@ android {
dependencies {
compile fileTree(dir: "libs", include: ["*.jar"])
compile "com.android.support:appcompat-v7:23.0.1"
compile "com.facebook.react:react-native:0.16.+"
compile "com.facebook.react:react-native:0.17.+"
compile project(":RNGL")
}
......@@ -21,7 +21,7 @@
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
146834051AC3E58100842450 /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 146834041AC3E56700842450 /* libReact.a */; };
3461EB301C132AA90003E4A2 /* libRNGL.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3461EB2F1C132A9F0003E4A2 /* libRNGL.a */; };
34562A0D1C26B83E0079DC6F /* libRNGL.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3461EB2F1C132A9F0003E4A2 /* libRNGL.a */; };
832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 832341B51AAA6A8300B99B32 /* libRCTText.a */; };
/* End PBXBuildFile section */
......@@ -149,7 +149,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
3461EB301C132AA90003E4A2 /* libRNGL.a in Frameworks */,
34562A0D1C26B83E0079DC6F /* libRNGL.a in Frameworks */,
146834051AC3E58100842450 /* libReact.a in Frameworks */,
00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */,
00C302E71ABCBA2D00DB3ED1 /* libRCTGeolocation.a in Frameworks */,
......
......@@ -8,6 +8,6 @@
"dependencies": {
"gl-react-native": "file:../..",
"gl-react": "^2.0.2",
"react-native": "^0.16.0"
"react-native": "^0.17.0"
}
}
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id=":RNGL" external.linked.project.path="$MODULE_DIR$/../../android" external.root.project.path="$MODULE_DIR$/../AdvancedEffects/android" external.system.id="GRADLE" external.system.module.group="AdvancedEffects" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="android-gradle" name="Android-Gradle">
<configuration>
<option name="GRADLE_PROJECT_PATH" value=":RNGL" />
</configuration>
</facet>
<facet type="android" name="Android">
<configuration>
<option name="SELECTED_BUILD_VARIANT" value="debug" />
<option name="SELECTED_TEST_ARTIFACT" value="_android_test_" />
<option name="ASSEMBLE_TASK_NAME" value="assembleDebug" />
<option name="COMPILE_JAVA_TASK_NAME" value="compileDebugSources" />
<option name="ASSEMBLE_TEST_TASK_NAME" value="assembleDebugAndroidTest" />
<option name="COMPILE_JAVA_TEST_TASK_NAME" value="compileDebugAndroidTestSources" />
<afterSyncTasks>
<task>generateDebugAndroidTestSources</task>
<task>generateDebugSources</task>
</afterSyncTasks>
<option name="ALLOW_USER_CONFIGURATION" value="false" />
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
<option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" />
<option name="RES_FOLDERS_RELATIVE_PATH" value="" />
<option name="ASSETS_FOLDER_RELATIVE_PATH" value="/src/main/assets" />
<option name="LIBRARY_PROJECT" value="true" />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="false">
<output url="file://$MODULE_DIR$/../../android/build/intermediates/classes/debug" />
<output-test url="file://$MODULE_DIR$/../../android/build/intermediates/classes/androidTest/debug" />
<exclude-output />
<content url="file://$MODULE_DIR$/../../android">
<sourceFolder url="file://$MODULE_DIR$/../../android/build/generated/source/r/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/../../android/build/generated/source/aidl/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/../../android/build/generated/source/buildConfig/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/../../android/build/generated/source/rs/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/../../android/build/generated/res/rs/debug" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/../../android/build/generated/res/resValues/debug" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/../../android/build/generated/source/r/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/../../android/build/generated/source/aidl/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/../../android/build/generated/source/buildConfig/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/../../android/build/generated/source/rs/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/../../android/build/generated/res/rs/androidTest/debug" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/../../android/build/generated/res/resValues/androidTest/debug" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/../../android/src/debug/res" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/../../android/src/debug/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/../../android/src/debug/assets" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/../../android/src/debug/aidl" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../android/src/debug/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../android/src/debug/jni" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../android/src/debug/rs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../android/src/main/res" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/../../android/src/main/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/../../android/src/main/assets" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/../../android/src/main/aidl" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../android/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../android/src/main/jni" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../android/src/main/rs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../android/src/androidTest/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/../../android/src/androidTest/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/../../android/src/androidTest/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/../../android/src/androidTest/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/../../android/src/androidTest/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/../../android/src/androidTest/jni" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/../../android/src/androidTest/rs" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/../../android/build/intermediates/annotations" />
<excludeFolder url="file://$MODULE_DIR$/../../android/build/intermediates/assets" />
<excludeFolder url="file://$MODULE_DIR$/../../android/build/intermediates/bundles" />
<excludeFolder url="file://$MODULE_DIR$/../../android/build/intermediates/classes" />
<excludeFolder url="file://$MODULE_DIR$/../../android/build/intermediates/dependency-cache" />
<excludeFolder url="file://$MODULE_DIR$/../../android/build/intermediates/incremental" />
<excludeFolder url="file://$MODULE_DIR$/../../android/build/intermediates/lint" />
<excludeFolder url="file://$MODULE_DIR$/../../android/build/intermediates/res" />
<excludeFolder url="file://$MODULE_DIR$/../../android/build/intermediates/rs" />
<excludeFolder url="file://$MODULE_DIR$/../../android/build/intermediates/symbols" />
<excludeFolder url="file://$MODULE_DIR$/../../android/build/outputs" />
<excludeFolder url="file://$MODULE_DIR$/../../android/build/tmp" />
</content>
<orderEntry type="jdk" jdkName="Android API 23 Platform" jdkType="Android SDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" exported="" name="okhttp-ws-2.5.0" level="project" />
<orderEntry type="library" exported="" name="library-2.4.0" level="project" />
<orderEntry type="library" exported="" name="okio-1.6.0" level="project" />
<orderEntry type="library" exported="" name="stetho-okhttp-1.2.0" level="project" />
<orderEntry type="library" exported="" name="okhttp-2.5.0" level="project" />
<orderEntry type="library" exported="" name="jsr305-3.0.0" level="project" />
<orderEntry type="library" exported="" name="stetho-1.2.0" level="project" />
<orderEntry type="library" exported="" name="jackson-core-2.2.3" level="project" />
<orderEntry type="library" exported="" name="fbcore-0.8.1" level="project" />
<orderEntry type="library" exported="" name="commons-cli-1.2" level="project" />
<orderEntry type="library" exported="" name="recyclerview-v7-23.0.1" level="project" />
<orderEntry type="library" exported="" name="imagepipeline-0.8.1" level="project" />
<orderEntry type="library" exported="" name="react-native-0.17.1" level="project" />
<orderEntry type="library" exported="" name="android-jsc-r174650" level="project" />
<orderEntry type="library" exported="" name="fresco-0.8.1" level="project" />
<orderEntry type="library" exported="" name="imagepipeline-okhttp-0.8.1" level="project" />
<orderEntry type="library" exported="" name="bolts-android-1.1.4" level="project" />
<orderEntry type="library" exported="" name="support-v4-23.0.1" level="project" />
<orderEntry type="library" exported="" name="drawee-0.8.1" level="project" />
<orderEntry type="library" exported="" name="appcompat-v7-23.0.1" level="project" />
<orderEntry type="library" exported="" name="support-annotations-23.0.1" level="project" />
</component>
</module>
\ No newline at end of file
**[Gitbook documentation](http://projectseptemberinc.gitbooks.io/gl-react/content/) / [Github](https://github.com/ProjectSeptemberInc/gl-react-native/) / [gl-react](https://github.com/ProjectSeptemberInc/gl-react/)** / [#gl-react on reactiflux](https://discordapp.com/channels/102860784329052160/106102146109325312)
# <img width="32" alt="icon" src="https://cloud.githubusercontent.com/assets/211411/9813786/eacfcc24-5888-11e5-8f9b-5a907a2cbb21.png"> gl-react-native ![](https://img.shields.io/badge/react--native-%3E=%200.16.0-05F561.svg)
# <img width="32" alt="icon" src="https://cloud.githubusercontent.com/assets/211411/9813786/eacfcc24-5888-11e5-8f9b-5a907a2cbb21.png"> gl-react-native ![](https://img.shields.io/badge/react--native-%200.17.x-05F561.svg)
OpenGL bindings for React Native to implement complex effects over images and components, in the descriptive VDOM paradigm.
......@@ -14,14 +14,38 @@ OpenGL bindings for React Native to implement complex effects over images and co
## Installation
a few steps are required to install `gl-react-native`:
**Install the dependency to your React Native application:**
```
npm i --save gl-react-native
```
**Configure your React Native Application:**
### Configure your React Native Application
**on iOS:**
![](https://github.com/ProjectSeptemberInc/gl-react-native/raw/master/docs/install-steps.png)
**on Android:**
1. `android/settings.gradle`:: Add the following snippet
```gradle
include ':RNGL'
project(':RNGL').projectDir = file('../node_modules/gl-react-native/android')
```
1. `android/app/build.gradle`: Add in dependencies block.
```gradle
compile project(':RNGL')
```
1. in your `MainActivity` (or equivalent):
```java
import com.projectseptember.RNGL.RNGLPackage;
...
mReactInstanceManager = ReactInstanceManager.builder()
.setApplication(getApplication())
...
.addPackage(new MainReactPackage())
.addPackage(new RNGLPackage())
...
.build();
```
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id=":RNGL" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/../Examples/Tests/android" external.system.id="GRADLE" external.system.module.group="Tests" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="android-gradle" name="Android-Gradle">
<configuration>
<option name="GRADLE_PROJECT_PATH" value=":RNGL" />
</configuration>
</facet>
<facet type="android" name="Android">
<configuration>
<option name="SELECTED_BUILD_VARIANT" value="debug" />
<option name="SELECTED_TEST_ARTIFACT" value="_android_test_" />
<option name="ASSEMBLE_TASK_NAME" value="assembleDebug" />
<option name="COMPILE_JAVA_TASK_NAME" value="compileDebugSources" />
<option name="ASSEMBLE_TEST_TASK_NAME" value="assembleDebugAndroidTest" />
<option name="COMPILE_JAVA_TEST_TASK_NAME" value="compileDebugAndroidTestSources" />
<afterSyncTasks>
<task>generateDebugAndroidTestSources</task>
<task>generateDebugSources</task>
</afterSyncTasks>
<option name="ALLOW_USER_CONFIGURATION" value="false" />
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
<option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" />
<option name="RES_FOLDERS_RELATIVE_PATH" value="" />
<option name="ASSETS_FOLDER_RELATIVE_PATH" value="/src/main/assets" />
<option name="LIBRARY_PROJECT" value="true" />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="false">
<output url="file://$MODULE_DIR$/build/intermediates/classes/debug" />
<output-test url="file://$MODULE_DIR$/build/intermediates/classes/androidTest/debug" />
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/debug" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/debug" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/androidTest/debug" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/androidTest/debug" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/res" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/assets" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/aidl" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/jni" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/rs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/res" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/main/assets" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/main/aidl" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/jni" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/rs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/jni" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/annotations" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/bundles" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dependency-cache" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/lint" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
<excludeFolder url="file://$MODULE_DIR$/build/outputs" />
<excludeFolder url="file://$MODULE_DIR$/build/tmp" />
</content>
<orderEntry type="jdk" jdkName="Android API 23 Platform" jdkType="Android SDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" exported="" name="okhttp-ws-2.5.0" level="project" />
<orderEntry type="library" exported="" name="library-2.4.0" level="project" />
<orderEntry type="library" exported="" name="okio-1.6.0" level="project" />
<orderEntry type="library" exported="" name="stetho-okhttp-1.2.0" level="project" />
<orderEntry type="library" exported="" name="okhttp-2.5.0" level="project" />
<orderEntry type="library" exported="" name="stetho-1.2.0" level="project" />
<orderEntry type="library" exported="" name="jsr305-3.0.0" level="project" />
<orderEntry type="library" exported="" name="jackson-core-2.2.3" level="project" />
<orderEntry type="library" exported="" name="fbcore-0.8.1" level="project" />
<orderEntry type="library" exported="" name="commons-cli-1.2" level="project" />
<orderEntry type="library" exported="" name="recyclerview-v7-23.0.1" level="project" />
<orderEntry type="library" exported="" name="imagepipeline-0.8.1" level="project" />
<orderEntry type="library" exported="" name="react-native-0.17.1" level="project" />
<orderEntry type="library" exported="" name="android-jsc-r174650" level="project" />
<orderEntry type="library" exported="" name="fresco-0.8.1" level="project" />
<orderEntry type="library" exported="" name="imagepipeline-okhttp-0.8.1" level="project" />
<orderEntry type="library" exported="" name="bolts-android-1.1.4" level="project" />
<orderEntry type="library" exported="" name="support-v4-23.0.1" level="project" />
<orderEntry type="library" exported="" name="drawee-0.8.1" level="project" />
<orderEntry type="library" exported="" name="appcompat-v7-23.0.1" level="project" />
<orderEntry type="library" exported="" name="support-annotations-23.0.1" level="project" />
</component>
</module>
\ No newline at end of file
......@@ -30,5 +30,5 @@ repositories {
}
dependencies {
compile 'com.facebook.react:react-native:0.16.+'
compile 'com.facebook.react:react-native:0.17.+'
}
......@@ -6,7 +6,9 @@ import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.PixelFormat;
import android.net.Uri;
import android.opengl.GLException;
import android.opengl.GLSurfaceView;
import android.util.Base64;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.View;
......@@ -19,9 +21,12 @@ import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.ReadableMapKeySetIterator;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.uimanager.PointerEvents;
import com.facebook.react.uimanager.ReactPointerEventsView;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.events.RCTEventEmitter;
import java.io.ByteArrayOutputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
......@@ -37,7 +42,8 @@ import java.util.concurrent.Executor;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
public class GLCanvas extends GLSurfaceView implements GLSurfaceView.Renderer, Executor {
public class GLCanvas extends GLSurfaceView
implements GLSurfaceView.Renderer, Executor, ReactPointerEventsView {
private ReactContext reactContext;
private RNGLContext rnglContext;
......@@ -60,6 +66,7 @@ public class GLCanvas extends GLSurfaceView implements GLSurfaceView.Renderer, E
private Map<Integer, GLFBO> fbos;
private ExecutorSupplier executorSupplier;
private final Queue<Runnable> mRunOnDraw = new LinkedList<>();
private boolean captureFrameRequested = false;
public GLCanvas(ThemedReactContext context, ExecutorSupplier executorSupplier) {
super(context);
......@@ -120,8 +127,6 @@ public class GLCanvas extends GLSurfaceView implements GLSurfaceView.Renderer, E
if (contentTextures.size() != this.nbContentTextures)
resizeUniformContentTextures(nbContentTextures);
syncEventsThrough(); // FIXME: need to do this here?
if (!preloadingDone) {
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
......@@ -144,6 +149,15 @@ public class GLCanvas extends GLSurfaceView implements GLSurfaceView.Renderer, E
if (shouldRenderNow) {
this.render();
deferredRendering = false;
if (captureFrameRequested) {
captureFrameRequested = false;
Bitmap capture = createSnapshot();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
capture.compress(Bitmap.CompressFormat.PNG, 100, baos);
String frame = "data:image/png;base64,"+
Base64.encodeToString(baos.toByteArray(), Base64.DEFAULT);
dispatchOnCaptureFrame(frame);
}
}
}
......@@ -174,36 +188,6 @@ public class GLCanvas extends GLSurfaceView implements GLSurfaceView.Renderer, E
this.setRenderMode(autoRedraw ? GLSurfaceView.RENDERMODE_CONTINUOUSLY : GLSurfaceView.RENDERMODE_WHEN_DIRTY);
}
public void setEventsThrough(boolean eventsThrough) {
syncEventsThrough();
}
public void setVisibleContent(boolean visibleContent) {
syncEventsThrough();
}
public void setCaptureNextFrameId(int captureNextFrameId) {
// FIXME move away from this pattern. just use a method, same to ObjC impl
this.requestRender();
}
private boolean ensureCompiledShader (List<GLData> data) {
for (GLData d: data) {
if (!ensureCompiledShader(d)) {
return false;
}
}
return true;
}
private boolean ensureCompiledShader (GLData data) {
GLShader shader = getShader(data.shader);
return shader != null &&
shader.ensureCompile() &&
ensureCompiledShader(data.children) &&
ensureCompiledShader(data.contextChildren);
}
public void setData (GLData data) {
this.data = data;
if (preloadingDone) syncContentBitmaps();
......@@ -247,9 +231,7 @@ public class GLCanvas extends GLSurfaceView implements GLSurfaceView.Renderer, E
public void requestSyncData () {
execute(new Runnable() {
public void run() {
if (ensureCompiledShader(data))
syncData();
else
if (!syncData())
requestSyncData();
}
});
......@@ -325,7 +307,6 @@ public class GLCanvas extends GLSurfaceView implements GLSurfaceView.Renderer, E
private int countPreloaded () {
int nb = 0;
for (Uri toload: imagesToPreload) {
Log.i("GLCanvas", "toload: "+toload.getPath()+" = "+preloaded.contains(toload));
if (preloaded.contains(toload)) {
nb++;
}
......@@ -383,6 +364,7 @@ public class GLCanvas extends GLSurfaceView implements GLSurfaceView.Renderer, E
Map<Uri, GLImage> prevImages = this.images;
GLShader shader = getShader(data.shader);
if (shader == null || !shader.ensureCompile()) return null;
Map<String, Integer> uniformsInteger = new HashMap<>();
Map<String, Float> uniformsFloat = new HashMap<>();
Map<String, IntBuffer> uniformsIntBuffer = new HashMap<>();
......@@ -392,11 +374,15 @@ public class GLCanvas extends GLSurfaceView implements GLSurfaceView.Renderer, E
List<GLRenderData> children = new ArrayList<>();
for (GLData child: data.contextChildren) {
contextChildren.add(recSyncData(child, images));
GLRenderData node = recSyncData(child, images);
if (node == null) return null;
contextChildren.add(node);
}
for (GLData child: data.children) {
children.add(recSyncData(child, images));
GLRenderData node = recSyncData(child, images);
if (node == null) return null;
children.add(node);
}
Map<String, Integer> uniformTypes = shader.getUniformTypes();
......@@ -595,11 +581,14 @@ public class GLCanvas extends GLSurfaceView implements GLSurfaceView.Renderer, E
}
}
private void syncData () {
if (data == null) return;
private boolean syncData () {
if (data == null) return true;
HashMap<Uri, GLImage> images = new HashMap<>();
renderData = recSyncData(data, images);
GLRenderData node = recSyncData(data, images);
if (node == null) return false;
renderData = node;
this.images = images;
return true;
}
private void recRender (GLRenderData renderData) {
......@@ -665,12 +654,16 @@ public class GLCanvas extends GLSurfaceView implements GLSurfaceView.Renderer, E
glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO);
}
private void syncEventsThrough () {
// TODO: figure out how to do this...
// For some reason, the click through is half working
private void dispatchOnCaptureFrame (String frame) {
WritableMap event = Arguments.createMap();
event.putString("frame", frame);
ReactContext reactContext = (ReactContext)getContext();
reactContext.getJSModule(RCTEventEmitter.class).receiveEvent(
getId(),
"captureFrame",
event);
}
private void dispatchOnProgress (double progress, int loaded, int total) {
WritableMap event = Arguments.createMap();
event.putDouble("progress", progress);
......@@ -691,4 +684,52 @@ public class GLCanvas extends GLSurfaceView implements GLSurfaceView.Renderer, E
"load",
event);
}
public void requestCaptureFrame() {
captureFrameRequested = true;
this.requestRender();
}
private Bitmap createSnapshot () {
return createSnapshot(0, 0, getWidth(), getHeight());
}
private Bitmap createSnapshot (int x, int y, int w, int h) {
int bitmapBuffer[] = new int[w * h];
int bitmapSource[] = new int[w * h];
IntBuffer intBuffer = IntBuffer.wrap(bitmapBuffer);
intBuffer.position(0);
try {
glReadPixels(x, y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, intBuffer);
int offset1, offset2;
for (int i = 0; i < h; i++) {
offset1 = i * w;
offset2 = (h - i - 1) * w;
for (int j = 0; j < w; j++) {
int texturePixel = bitmapBuffer[offset1 + j];
int blue = (texturePixel >> 16) & 0xff;
int red = (texturePixel << 16) & 0x00ff0000;
int pixel = (texturePixel & 0xff00ff00) | red | blue;
bitmapSource[offset2 + j] = pixel;
}
}
} catch (GLException e) {
return null;
}
return Bitmap.createBitmap(bitmapSource, w, h, Bitmap.Config.ARGB_8888);
}
private PointerEvents mPointerEvents = PointerEvents.AUTO;
@Override
public PointerEvents getPointerEvents() {
return mPointerEvents;
}
void setPointerEvents(PointerEvents pointerEvents) {
mPointerEvents = pointerEvents;
}
}
......@@ -6,13 +6,16 @@ import com.facebook.imagepipeline.core.DefaultExecutorSupplier;
import com.facebook.imagepipeline.core.ExecutorSupplier;
import com.facebook.imagepipeline.memory.PoolConfig;
import com.facebook.imagepipeline.memory.PoolFactory;
import com.facebook.infer.annotation.Assertions;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.common.MapBuilder;
import com.facebook.react.uimanager.PointerEvents;
import com.facebook.react.uimanager.SimpleViewManager;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.ReactProp;
import java.util.Locale;
import java.util.Map;
......@@ -20,12 +23,15 @@ public class GLCanvasManager extends SimpleViewManager<GLCanvas> {
public static final String REACT_CLASS = "GLCanvas";
public static final int COMMAND_CAPTURE_FRAME = 1;
private ExecutorSupplier executorSupplier;
@ReactProp(name="nbContentTextures")
public void setNbContentTextures (GLCanvas view, int nbContentTextures) {
view.setNbContentTextures(nbContentTextures);
}
@ReactProp(name="renderId")
public void setRenderId (GLCanvas view, int renderId) {
view.setRenderId(renderId);
......@@ -36,27 +42,20 @@ public class GLCanvasManager extends SimpleViewManager<GLCanvas> {
view.setOpaque(opaque);
}
@ReactProp(name="autoRedraw")
@ReactProp(name = "autoRedraw")
public void setAutoRedraw (GLCanvas view, boolean autoRedraw) {
view.setAutoRedraw(autoRedraw);
}
@ReactProp(name="eventsThrough")
public void setEventsThrough (GLCanvas view, boolean eventsThrough) {
view.setEventsThrough(eventsThrough);
}
@ReactProp(name="visibleContent")
public void setVisibleContent (GLCanvas view, boolean visibleContent) {
view.setVisibleContent(visibleContent);
}
@ReactProp(name="captureNextFrameId")
public void setCaptureNextFrameId (GLCanvas view, int captureNextFrameId) {
view.setCaptureNextFrameId(captureNextFrameId);
@ReactProp(name = "pointerEvents")
public void setPointerEvents(GLCanvas view, @Nullable String pointerEventsStr) {
if (pointerEventsStr != null) {
PointerEvents pointerEvents = PointerEvents.valueOf(pointerEventsStr.toUpperCase(Locale.US).replace("-", "_"));
view.setPointerEvents(pointerEvents);
}
}
@ReactProp(name="data")
@ReactProp(name = "data")
public void setData (GLCanvas view, @Nullable ReadableMap data) {
view.setData(data == null ? null : GLData.fromMap(data));
}
......@@ -81,13 +80,42 @@ public class GLCanvasManager extends SimpleViewManager<GLCanvas> {
return new GLCanvas(context, executorSupplier);
}
@Override
public void receiveCommand(
GLCanvas canvas,
int commandType,
@Nullable ReadableArray args) {
Assertions.assertNotNull(canvas);
Assertions.assertNotNull(args);
switch (commandType) {
case COMMAND_CAPTURE_FRAME: {
canvas.requestCaptureFrame();
return;
}
default:
throw new IllegalArgumentException(String.format(
"Unsupported command %d received by %s.",
commandType,
getClass().getSimpleName()));
}
}
@Override
public @Nullable Map getExportedCustomDirectEventTypeConstants() {
return MapBuilder.of(
"captureFrame",
MapBuilder.of("registrationName", "onGLCaptureFrame"),
"load",
MapBuilder.of("registrationName", "onLoad"),
MapBuilder.of("registrationName", "onGLLoad"),
"progress",
MapBuilder.of("registrationName", "onProgress")
MapBuilder.of("registrationName", "onGLProgress")
);
}
@Override
public Map<String,Integer> getCommandsMap() {
return MapBuilder.of(
"captureFrame",
COMMAND_CAPTURE_FRAME);
}
}
#import <GLKit/GLKit.h>
#import "GLData.h"
#import "RCTComponent.h"
@interface GLCanvas: GLKView
......@@ -11,12 +12,12 @@
@property (nonatomic) NSNumber *nbContentTextures;
@property (nonatomic) NSNumber *renderId;
@property (nonatomic) NSArray *imagesToPreload;
@property (nonatomic, assign) BOOL onProgress;
@property (nonatomic, assign) BOOL onLoad;
@property (nonatomic, assign) BOOL onChange;
@property (nonatomic, copy) RCTBubblingEventBlock onGLProgress;
@property (nonatomic, copy) RCTBubblingEventBlock onGLLoad;
@property (nonatomic, copy) RCTBubblingEventBlock onGLCaptureFrame;
- (instancetype)initWithBridge:(RCTBridge *)bridge;
- (void) capture:(RCTResponseSenderBlock)callback;
- (void) requestCaptureFrame;
@end
......@@ -12,7 +12,6 @@
#import "GLRenderData.h"
#import "UIView+React.h"
NSString* srcResource (id res)
{
NSString *src;
......@@ -33,9 +32,10 @@ NSString* srcResource (id res)
RCTBridge *_bridge;
GLRenderData *_renderData;
NSMutableArray *_captureListeners;
BOOL _captureFrameRequested;
NSArray *_contentData;
NSArray *_contentTextures;
NSDictionary *_images; // This caches the currently used images (imageSrc -> GLReactImage)
......@@ -49,8 +49,8 @@ NSString* srcResource (id res)
BOOL _preloadingDone;
NSTimer *animationTimer;
BOOL _needSync;
BOOL _needSync;
}
- (instancetype)initWithBridge:(RCTBridge *)bridge
......@@ -59,7 +59,7 @@ NSString* srcResource (id res)
_bridge = bridge;
_images = @{};
_preloaded = [[NSMutableArray alloc] init];
_captureListeners = [[NSMutableArray alloc] init];
_captureFrameRequested = false;
_preloadingDone = false;
self.context = [bridge.rnglContext getContext];
self.contentScaleFactor = RCTScreenScale();
......@@ -71,9 +71,9 @@ RCT_NOT_IMPLEMENTED(-init)
//// Props Setters
- (void) capture:(RCTResponseSenderBlock)callback
- (void) requestCaptureFrame
{
[_captureListeners addObject:callback];
_captureFrameRequested = true;
[self setNeedsDisplay];
}
......@@ -121,16 +121,12 @@ RCT_NOT_IMPLEMENTED(-init)
}
}
- (void)setEventsThrough:(BOOL)eventsThrough
- (void)setPointerEvents:(RCTPointerEvents)pointerEvents
{
_eventsThrough = eventsThrough;
[self syncEventsThrough];
}
-(void)setVisibleContent:(BOOL)visibleContent
{
_visibleContent = visibleContent;
[self syncEventsThrough];
self.userInteractionEnabled = (pointerEvents != RCTPointerEventsNone);
if (pointerEvents == RCTPointerEventsBoxNone) {
self.accessibilityViewIsModal = NO;
}
}
- (void)setData:(GLData *)data
......@@ -141,22 +137,15 @@ RCT_NOT_IMPLEMENTED(-init)
- (void)setNbContentTextures:(NSNumber *)nbContentTextures
{
[self resizeUniformContentTextures:[nbContentTextures intValue]];
_nbContentTextures = nbContentTextures;
}
//// Sync methods (called from props setters)
- (void) syncEventsThrough
{
self.userInteractionEnabled = !(_eventsThrough);
self.superview.userInteractionEnabled = !(_eventsThrough && !_visibleContent);
}
- (void)requestSyncData
{
_needSync = true;
[self setNeedsDisplay];
_needSync = true;
[self setNeedsDisplay];
}
- (void)syncData
......@@ -176,15 +165,20 @@ RCT_NOT_IMPLEMENTED(-init)
NSMutableArray *contextChildren = [[NSMutableArray alloc] init];
for (GLData *child in data.contextChildren) {
[contextChildren addObject:weak_traverseTree(child)];
GLRenderData *node = weak_traverseTree(child);
if (node == nil) return nil;
[contextChildren addObject:node];
}
NSMutableArray *children = [[NSMutableArray alloc] init];
for (GLData *child in data.children) {
[children addObject:weak_traverseTree(child)];
GLRenderData *node = weak_traverseTree(child);
if (node == nil) return nil;
[children addObject:node];
}
GLShader *shader = [_bridge.rnglContext getShader:data.shader];
if (shader == nil) return nil;
NSDictionary *uniformTypes = [shader uniformTypes];
NSMutableDictionary *uniforms = [[NSMutableDictionary alloc] init];
......@@ -194,12 +188,12 @@ RCT_NOT_IMPLEMENTED(-init)
id value = [data.uniforms objectForKey:uniformName];
GLenum type = [uniformTypes[uniformName] intValue];
if (type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE) {
uniforms[uniformName] = [NSNumber numberWithInt:units++];
if ([value isEqual:[NSNull null]]) {
GLTexture *emptyTexture = [[GLTexture alloc] init];
[emptyTexture setPixelsEmpty];
[emptyTexture setPixels:nil];
textures[uniformName] = emptyTexture;
}
else {
......@@ -271,25 +265,40 @@ RCT_NOT_IMPLEMENTED(-init)
withChildren:children];
};
_renderData = traverseTree(_data);
_images = images;
GLRenderData *res = traverseTree(_data);
if (res != nil) {
_renderData = traverseTree(_data);
_images = images;
}
}
}
- (void)syncContentTextures
- (void)syncContentData
{
int i = 0;
for (GLTexture *texture in _contentTextures) {
UIView* view = self.superview.subviews[i]; // We take siblings by index (closely related to the JS code)
NSMutableArray *contentData = [[NSMutableArray alloc] init];
int nb = [_nbContentTextures intValue];
for (int i = 0; i < nb; i++) {
UIView *view = self.superview.subviews[i]; // We take siblings by index (closely related to the JS code)
GLImageData *imgData = nil;
if (view) {
if ([view.subviews count] == 1)
[texture setPixelsWithView:view.subviews[0]];
else
[texture setPixelsWithView:view];
UIView *v = [view.subviews count] == 1 ?
view.subviews[0] :
view;
imgData = [GLImageData genPixelsWithView:v];
} else {
[texture setPixelsEmpty];
imgData = nil;
}
i ++;
contentData[i] = imgData;
}
_contentData = contentData;
}
- (void)syncContentTextures
{
unsigned long max = MIN([_contentData count], [_contentTextures count]);
for (int i=0; i<max; i++) {
[_contentTextures[i] setPixels:_contentData[i]];
}
}
......@@ -298,13 +307,13 @@ RCT_NOT_IMPLEMENTED(-init)
- (void)drawRect:(CGRect)rect
{
if (_needSync) {
_needSync = false;
[self syncData];
}
self.layer.opaque = _opaque;
[self syncEventsThrough];
__weak GLCanvas *weakSelf = self;
if (_needSync) {
_needSync = false;
[self syncData];
}
self.layer.opaque = _opaque;
if (!_preloadingDone) {
glClearColor(0.0, 0.0, 0.0, 0.0);
......@@ -316,6 +325,7 @@ RCT_NOT_IMPLEMENTED(-init)
dispatch_async(dispatch_get_main_queue(), ^{
if (!weakSelf) return;
_deferredRendering = true;
[self syncContentData];
[weakSelf setNeedsDisplay];
});
}
......@@ -323,22 +333,16 @@ RCT_NOT_IMPLEMENTED(-init)
[self render];
_deferredRendering = false;
unsigned long nbCaptureListeners = [_captureListeners count];
if (nbCaptureListeners > 0) {
NSArray *listeners = _captureListeners;
_captureListeners = [[NSMutableArray alloc] init];
if (_captureFrameRequested) {
_captureFrameRequested = false;
dispatch_async(dispatch_get_main_queue(), ^{ // snapshot not allowed in render tick. defer it.
if (!weakSelf) return;
UIImage *frameImage = [weakSelf snapshot];
NSData *frameData = UIImagePNGRepresentation(frameImage);
NSString *frame =
[NSString stringWithFormat:@"data:image/png;base64,%@",
[frameData base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength]];
for (int i = 0; i < nbCaptureListeners; i++) {
RCTResponseSenderBlock listener = listeners[i];
listener(@[[NSNull null], frame]);
}
[frameData base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength]];
if (weakSelf.onGLCaptureFrame) weakSelf.onGLCaptureFrame(@{ @"frame": frame });
});
}
}
......@@ -437,7 +441,6 @@ RCT_NOT_IMPLEMENTED(-init)
- (void)resizeUniformContentTextures:(int)n
{
[EAGLContext setCurrentContext:self.context];
int length = (int) [_contentTextures count];
if (length == n) return;
if (n < length) {
......@@ -454,25 +457,17 @@ RCT_NOT_IMPLEMENTED(-init)
- (void)dispatchOnLoad
{
[_bridge.eventDispatcher sendInputEventWithName:@"load" body:@{ @"target": self.reactTag }];
if (self.onGLLoad) self.onGLLoad(@{});
}
- (void)dispatchOnProgress: (double)progress withLoaded:(int)loaded withTotal:(int)total
{
NSDictionary *event =
if (self.onGLProgress) self.onGLProgress(
@{
@"target": self.reactTag,
@"progress": @(progress),
@"loaded": @(loaded),
@"total": @(total) };
[_bridge.eventDispatcher sendInputEventWithName:@"progress" body:event];
}
- (void)dispatchOnCapture: (NSString *)frame withId:(int)id
{
NSDictionary *event = @{ @"target": self.reactTag, @"frame": frame, @"id":@(id) };
// FIXME: using onChange is a hack before we use the new system to directly call callbacks. we will replace with: self.onCaptureNextFrame(...)
[_bridge.eventDispatcher sendInputEventWithName:@"change" body:event];
@"progress": @(RCTZeroIfNaN(progress)),
@"loaded": @(RCTZeroIfNaN(loaded)),
@"total": @(RCTZeroIfNaN(total))
});
}
@end
......@@ -20,26 +20,23 @@ RCT_EXPORT_MODULE();
RCT_EXPORT_VIEW_PROPERTY(nbContentTextures, NSNumber);
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(data, GLData);
RCT_EXPORT_VIEW_PROPERTY(renderId, NSNumber);
RCT_EXPORT_VIEW_PROPERTY(imagesToPreload, NSArray);
RCT_EXPORT_VIEW_PROPERTY(onLoad, BOOL);
RCT_EXPORT_VIEW_PROPERTY(onProgress, BOOL);
RCT_EXPORT_VIEW_PROPERTY(onChange, BOOL);
RCT_EXPORT_VIEW_PROPERTY(onGLLoad, RCTBubblingEventBlock);
RCT_EXPORT_VIEW_PROPERTY(onGLProgress, RCTBubblingEventBlock);
RCT_EXPORT_VIEW_PROPERTY(onGLCaptureFrame, RCTBubblingEventBlock);
RCT_EXPORT_METHOD(capture: (nonnull NSNumber *)reactTag callback:(RCTResponseSenderBlock)callback)
RCT_EXPORT_METHOD(capture: (nonnull NSNumber *)reactTag)
{
[self.bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
UIView *view = viewRegistry[reactTag];
if (![view isKindOfClass:[GLCanvas class]]) {
RCTLog(@"expecting UIView, got: %@", view);
callback(@[@"view is not a GLCanvas"]);
}
else {
GLCanvas *glCanvas = (GLCanvas *)view;
[glCanvas capture:callback];
[glCanvas requestCaptureFrame];
}
}];
}
......
......@@ -50,12 +50,12 @@ RCT_NOT_IMPLEMENTED(-init)
{
if (_image) {
if (!_data) {
_data = genPixelsWithImage(_image);
_data = [GLImageData genPixelsWithImage:_image];
}
[_texture setPixels:_data];
}
else {
[_texture setPixelsEmpty];
[_texture setPixels:nil];
}
return _texture;
}
......
......@@ -6,6 +6,11 @@
@property (nonatomic) int width;
@property (nonatomic) int height;
+ (GLImageData*) empty;
+ (GLImageData*) genPixelsWithImage: (UIImage *)image;
+ (GLImageData*) genPixelsWithView: (UIView *)view;
- (instancetype)initWithData: (GLubyte *)data withWidth:(int)width withHeight:(int)height;
@end
#import "GLImageData.h"
// TODO: rename to GLImageData
#import "RCTUtils.h"
#import "RCTLog.h"
// This structure aims to be used in an immutable way
@implementation GLImageData
......@@ -11,6 +11,65 @@
int _height;
}
GLImageData *EMPTY_PIXELS;
+ (GLImageData *)empty
{
if (!EMPTY_PIXELS) {
int width = 2, height = 2;
GLubyte* data = (GLubyte *) malloc(width*height*4*sizeof(GLubyte));
for (int i = 0; i < width * height * 4; i+=4) {
data[i] = data[i+1] = data[i+2] = 0;
data[i+3] = 0;
}
EMPTY_PIXELS = [[GLImageData alloc] initWithData:data withWidth:width withHeight:height];
}
return EMPTY_PIXELS;
}
+ (GLImageData *)genPixelsWithImage: (UIImage *)image
{
int width = image.size.width;
int height = image.size.height;
if (width == 0 || height == 0) {
RCTLogError(@"The image must be loaded in setPixelsWithImage call");
return nil;
}
GLubyte* data = malloc(width * height * 4);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef ctx = CGBitmapContextCreate(data, width, height, 8, width * 4, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
if (ctx == NULL) {
RCTLogError(@"unable to create the bitmap context");
CGColorSpaceRelease(colorSpace);
free(data);
return nil;
}
CGAffineTransform flipVertical = CGAffineTransformMake(1, 0, 0, -1, 0, height);
CGContextConcatCTM(ctx, flipVertical);
CGRect rect = CGRectMake(0.0, 0.0, width, height);
CGContextClearRect(ctx, rect);
CGContextDrawImage(ctx, rect, image.CGImage);
CGColorSpaceRelease(colorSpace);
CGContextRelease(ctx);
return [[GLImageData alloc] initWithData:data withWidth:width withHeight:height];
}
+ (GLImageData *)genPixelsWithView: (UIView *)view
{
float width = RCTScreenScale() * view.bounds.size.width;
float height = RCTScreenScale() * view.bounds.size.height;
GLubyte *data = (GLubyte *)malloc(4 * width * height);
CGColorSpaceRef colourSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef ctx = CGBitmapContextCreate(data, width, height, 8, 4 * width, colourSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
CGColorSpaceRelease(colourSpace);
CGContextClearRect(ctx, CGRectMake(0.0, 0.0, width, height));
CGContextScaleCTM(ctx, RCTScreenScale(), RCTScreenScale());
[view.layer renderInContext:ctx];
CGContextRelease(ctx);
return [[GLImageData alloc] initWithData:data withWidth:width withHeight:height];
}
- (instancetype)initWithData: (GLubyte *)data withWidth:(int)width withHeight:(int)height
{
self = [super init];
......
......@@ -2,8 +2,6 @@
#import "RCTBridge.h"
#import "GLImageData.h"
GLImageData* genPixelsWithImage (UIImage *image);
@interface GLTexture: NSObject
@property EAGLContext *context;
......@@ -16,9 +14,5 @@ GLImageData* genPixelsWithImage (UIImage *image);
- (void)setShapeWithWidth:(float)width withHeight:(float)height;
- (void)setPixels: (GLImageData *)data;
- (void)setPixelsEmpty;
- (void)setPixelsRandom: (int)width withHeight:(int)height;
- (void)setPixelsWithImage: (UIImage *)image;
- (void)setPixelsWithView: (UIView *)view;
@end
......@@ -2,84 +2,14 @@
#import "RCTLog.h"
#import "RCTUtils.h"
GLImageData* genPixelsEmpty (int width, int height)
{
GLubyte* data = (GLubyte *) malloc(width*height*4*sizeof(GLubyte));
for (int i = 0; i < width * height * 4; i+=4) {
data[i] = data[i+1] = data[i+2] = 0;
data[i+3] = 0;
}
return [[GLImageData alloc] initWithData:data withWidth:width withHeight:height];
}
GLImageData* genPixelsRandom (int width, int height)
{
GLubyte* data = (GLubyte *) malloc(width*height*4*sizeof(GLubyte));
for (int i = 0; i < width * height * 4; i+=4) {
data[i] = rand() % 255;
data[i+1] = rand() % 255;
data[i+2] = rand() % 255;
data[i+3] = 255;
}
return [[GLImageData alloc] initWithData:data withWidth:width withHeight:height];
}
GLImageData* genPixelsWithImage (UIImage *image)
{
int width = image.size.width;
int height = image.size.height;
if (width == 0 || height == 0) {
RCTLogError(@"The image must be loaded in setPixelsWithImage call");
return nil;
}
GLubyte* data = malloc(width * height * 4);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef ctx = CGBitmapContextCreate(data, width, height, 8, width * 4, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
if (ctx == NULL) {
RCTLogError(@"unable to create the bitmap context");
CGColorSpaceRelease(colorSpace);
free(data);
return nil;
}
CGAffineTransform flipVertical = CGAffineTransformMake(1, 0, 0, -1, 0, height);
CGContextConcatCTM(ctx, flipVertical);
CGRect rect = CGRectMake(0.0, 0.0, width, height);
CGContextClearRect(ctx, rect);
CGContextDrawImage(ctx, rect, image.CGImage);
CGColorSpaceRelease(colorSpace);
CGContextRelease(ctx);
return [[GLImageData alloc] initWithData:data withWidth:width withHeight:height];
}
GLImageData* genPixelsWithView (UIView *view)
{
float width = RCTScreenScale() * view.bounds.size.width;
float height = RCTScreenScale() * view.bounds.size.height;
GLubyte *data = (GLubyte *)malloc(4 * width * height);
CGColorSpaceRef colourSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef ctx = CGBitmapContextCreate(data, width, height, 8, 4 * width, colourSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
CGColorSpaceRelease(colourSpace);
CGContextClearRect(ctx, CGRectMake(0.0, 0.0, width, height));
CGContextScaleCTM(ctx, RCTScreenScale(), RCTScreenScale());
[view.layer renderInContext:ctx];
CGContextRelease(ctx);
return [[GLImageData alloc] initWithData:data withWidth:width withHeight:height];
}
@implementation GLTexture
{
GLuint _handle; // The identifier of the gl texture
GLImageData* dataCurrentlyUploaded; // The last set data (cache)
}
GLImageData *EMPTY_PIXELS;
- (instancetype)init
{
if (!EMPTY_PIXELS) {
EMPTY_PIXELS = genPixelsEmpty(2, 2);
}
self = [super init];
if (self) {
[self makeTexture];
......@@ -123,36 +53,12 @@ GLImageData *EMPTY_PIXELS;
- (void)setPixels: (GLImageData *)data
{
if (data != dataCurrentlyUploaded) {
dataCurrentlyUploaded = data;
GLImageData *d = data==nil ? [GLImageData empty] : data;
if (d != dataCurrentlyUploaded) {
dataCurrentlyUploaded = d;
[self bind];
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, data.width, data.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data.data);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, d.width, d.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, d.data);
}
}
- (void)setPixelsEmpty
{
[self setPixels:EMPTY_PIXELS];
}
- (void)setPixelsRandom: (int)width withHeight:(int)height // for testing
{
GLImageData* data = genPixelsRandom(width, height);
[self setPixels:data];
}
- (void)setPixelsWithImage: (UIImage *)image
{
GLImageData *data = genPixelsWithImage(image);
if (!data) return;
[self setPixels:data];
}
- (void)setPixelsWithView: (UIView *)view
{
GLImageData *data = genPixelsWithView(view);
[self setPixels:data];
}
@end
......@@ -44,17 +44,17 @@
346089C21BEFD0A500C90DB5 /* GLImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLImage.h; sourceTree = "<group>"; };
346089C31BEFD0A500C90DB5 /* GLImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GLImage.m; sourceTree = "<group>"; };
346089C41BEFD0A500C90DB5 /* GLImageData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLImageData.h; sourceTree = "<group>"; };
346089C51BEFD0A500C90DB5 /* GLImageData.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GLImageData.m; sourceTree = "<group>"; };
346089C51BEFD0A500C90DB5 /* GLImageData.m */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.objc; path = GLImageData.m; sourceTree = "<group>"; tabWidth = 2; };
346089C61BEFD0A500C90DB5 /* GLRenderData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLRenderData.h; sourceTree = "<group>"; };
346089C71BEFD0A500C90DB5 /* GLRenderData.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GLRenderData.m; sourceTree = "<group>"; };
346089C81BEFD0A500C90DB5 /* GLShader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLShader.h; sourceTree = "<group>"; };
346089C91BEFD0A500C90DB5 /* GLShader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GLShader.m; sourceTree = "<group>"; };
346089CA1BEFD0A500C90DB5 /* GLTexture.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLTexture.h; sourceTree = "<group>"; };
346089CB1BEFD0A500C90DB5 /* GLTexture.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GLTexture.m; sourceTree = "<group>"; };
346089CB1BEFD0A500C90DB5 /* GLTexture.m */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.objc; path = GLTexture.m; sourceTree = "<group>"; tabWidth = 2; };
346089CC1BEFD0A500C90DB5 /* RCTConvert+GLData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "RCTConvert+GLData.h"; sourceTree = "<group>"; };
346089CD1BEFD0A500C90DB5 /* RCTConvert+GLData.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "RCTConvert+GLData.m"; sourceTree = "<group>"; };
346089CE1BEFD0A500C90DB5 /* RNGLContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNGLContext.h; sourceTree = "<group>"; };
346089CF1BEFD0A500C90DB5 /* RNGLContext.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNGLContext.m; sourceTree = "<group>"; };
346089CF1BEFD0A500C90DB5 /* RNGLContext.m */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.objc; path = RNGLContext.m; sourceTree = "<group>"; tabWidth = 2; };
4107012F1ACB723B00C6AA39 /* libRNGL.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRNGL.a; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */
......
......@@ -64,7 +64,7 @@ RCT_EXPORT_METHOD(addShader:(nonnull NSNumber *)id withConfig:(NSDictionary *)co
- (RNGLContext *)rnglContext
{
return self.modules[RCTBridgeModuleNameForClass([RNGLContext class])];
return [self moduleForClass:[RNGLContext class]];
}
@end
\ No newline at end of file
......@@ -19,13 +19,14 @@
"author": "Project September <tech@projectseptember.com>",
"license": "MIT",
"peerDependencies": {
"react-native": ">= 0.16.0",
"gl-react": ">= 2.0.2"
"react-native": ">= 0.17.0 <0.18.0",
"gl-react": ">= 2.0.3 <2.1.0"
},
"dependencies": {
"invariant": "2.2.0"
},
"devDependencies": {
"babel-eslint": "^4.1.6",
"eslint": "^1.9.0",
"eslint-plugin-react": "^3.8.0"
}
......
const invariant = require("invariant");
const React = require("react-native");
const {
NativeModules: { UIManager }
} = React;
const {GLCanvas} = UIManager;
invariant(GLCanvas,
`gl-react-native: the native module is not available.
Make sure you have properly configured it.
See README install instructions.
React.NativeModules.UIManager.GLCanvas is %s`, GLCanvas);
const {Commands} = GLCanvas;
module.exports = handle => UIManager.dispatchViewManagerCommand(handle, Commands.captureFrame, []);
const invariant = require("invariant");
const React = require("react-native");
const {
NativeModules: { GLCanvasManager }
} = React;
invariant(GLCanvasManager,
`gl-react-native: the native module is not available.
Make sure you have properly configured it.
See README install instructions.
React.NativeModules.GLCanvasManager is %s`, GLCanvasManager);
module.exports = handle => GLCanvasManager.capture(handle);
const React = require("react-native");
const {
Component,
requireNativeComponent,
NativeModules: { GLCanvasManager }
requireNativeComponent
} = React;
const GLCanvasNative = requireNativeComponent("GLCanvas", GLCanvas);
const captureFrame = require("./GLCanvas.captureFrame");
class GLCanvas extends Component {
constructor (props) {
super(props);
const GLCanvasNative = requireNativeComponent("GLCanvas", GLCanvas, {
nativeOnly: {
onGLChange: true,
onGLProgress: true,
onGLCaptureFrame: true
}
});
function defer() {
const deferred = {};
const promise = new Promise(function(resolve, reject) {
deferred.resolve = resolve;
deferred.reject = reject;
});
deferred.promise = promise;
return deferred;
}
class GLCanvas extends Component {
captureFrame (cb) {
GLCanvasManager.capture(
React.findNodeHandle(this.refs.native),
(error, frame) => {
if (error) console.error(error); // eslint-disable-line no-console
else cb(frame);
});
const promise = (
this._pendingCaptureFrame || // use pending capture OR create a new captureFrame pending
(captureFrame(React.findNodeHandle(this.refs.native)), this._pendingCaptureFrame = defer())
).promise;
if (typeof cb === "function") {
console.warn("GLSurface: callback parameter of captureFrame is deprecated, use the returned promise instead"); // eslint-disable-line no-console
promise.then(cb);
}
return promise;
}
onGLCaptureFrame = ({ nativeEvent: {frame} }) => {
this._pendingCaptureFrame.resolve(frame);
this._pendingCaptureFrame = undefined;
}
render () {
const { width, height, ...restProps } = this.props;
const { width, height, onLoad, onProgress, eventsThrough, ...restProps } = this.props;
return <GLCanvasNative
ref="native"
{...restProps}
onGLLoad={onLoad ? onLoad : null}
onGLProgress={onProgress ? onProgress : null}
onGLCaptureFrame={this.onGLCaptureFrame}
pointerEvents={eventsThrough ? "none" : "auto"}
style={{ width, height }}
/>;
}
......
const invariant = require("invariant");
const {createSurface} = require("gl-react");
invariant(typeof createSurface === "function", "gl-react createSurface is not a function. Check your gl-react dependency");
const React = require("react-native");
const GLCanvas = require("./GLCanvas");
......@@ -13,7 +15,7 @@ function renderVcontent (width, height, id, children, { visibleContent }) {
left: 0,
width: width,
height: height,
overflow: "hidden"
overflow: "hidden",
};
return <View key={id} style={childrenStyle}>{children}</View>;
}
......@@ -22,15 +24,17 @@ function renderVGL (props) {
return <GLCanvas ref="canvas" {...props} />;
}
function renderVcontainer ({ style, width, height }, contents, renderer) {
function renderVcontainer ({ style, width, height, visibleContent, eventsThrough }, contents, renderer) {
const parentStyle = {
position: "relative",
...style,
width: width,
height: height,
overflow: "hidden"
overflow: "hidden",
};
return <View style={parentStyle}>
return <View
pointerEvents={!visibleContent && eventsThrough ? "none" : "auto"}
style={parentStyle}>
{contents}
{renderer}
</View>;
......
const invariant = require("invariant");
const { Shaders } = require("gl-react");
const Surface = require("./Surface");
const { NativeModules: { RNGLContext } } = require("react-native");
invariant(RNGLContext,
`gl-react-native: the native module is not available.
Make sure you have properly configured it.
See README install instructions.
React.NativeModules.RNGLContext is %s`, RNGLContext);
// Hook Shaders to RNGLContext
Shaders.list().map(id => RNGLContext.addShader(id, Shaders.get(id)));
......
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