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

initial version

parents
# OSX
#
.DS_Store
# Xcode
#
build/
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata
*.xccheckout
*.moved-aside
DerivedData
*.hmap
*.ipa
*.xcuserstate
project.xcworkspace
# node.js
#
node_modules/
npm-debug.log
# OSX
#
.DS_Store
# Xcode
#
build/
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata
*.xccheckout
*.moved-aside
DerivedData
*.hmap
*.ipa
*.xcuserstate
# node.js
#
node_modules/
npm-debug.log
{
"globals": {
"requestAnimationFrame": true
},
"rules": {
"indent": [
2,
2
],
"quotes": [
2,
"double"
],
"linebreak-style": [
2,
"unix"
],
"semi": [
2,
"always"
],
"comma-dangle": 0,
"no-var": 1,
"react/jsx-boolean-value": 1,
"react/jsx-no-undef": 1,
"react/jsx-quotes": 1,
"react/jsx-uses-react": 1,
"react/jsx-uses-vars": 1,
"react/no-danger": 1,
"react/no-did-mount-set-state": 1,
"react/no-did-update-set-state": 1,
"react/no-unknown-property": 1,
"react/react-in-jsx-scope": 1,
"react/require-extension": 1,
"react/sort-comp": 1
},
"env": {
"es6": true,
"node": true
},
"extends": "eslint:recommended",
"ecmaFeatures": {
"jsx": true,
"experimentalObjectRestSpread": true
},
"plugins": [
"react"
]
}
[ignore]
# We fork some components by platform.
.*/*.web.js
.*/*.android.js
# Some modules have their own node_modules with overlap
.*/node_modules/node-haste/.*
# Ignore react-tools where there are overlaps, but don't ignore anything that
# react-native relies on
.*/node_modules/react-tools/src/React.js
.*/node_modules/react-tools/src/renderers/shared/reconciler/ReactInstanceHandles.js
.*/node_modules/react-tools/src/renderers/shared/event/EventPropagators.js
.*/node_modules/react-tools/src/renderers/shared/event/eventPlugins/ResponderEventPlugin.js
.*/node_modules/react-tools/src/renderers/shared/event/eventPlugins/ResponderSyntheticEvent.js
.*/node_modules/react-tools/src/renderers/shared/event/eventPlugins/ResponderTouchHistoryStore.js
.*/node_modules/react-tools/src/shared/vendor/core/ExecutionEnvironment.js
# Ignore commoner tests
.*/node_modules/commoner/test/.*
# See https://github.com/facebook/flow/issues/442
.*/react-tools/node_modules/commoner/lib/reader.js
# Ignore jest
.*/react-native/node_modules/jest-cli/.*
[include]
[libs]
node_modules/react-native/Libraries/react-native/react-native-interface.js
[options]
module.system=haste
suppress_type=$FlowIssue
suppress_type=$FlowFixMe
suppress_type=$FixMe
suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(1[0-3]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)
suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(1[0-3]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)? #[0-9]+
suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy
[version]
0.13.1
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0620"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
BuildableName = "AdvancedEffects.app"
BlueprintName = "AdvancedEffects"
ReferencedContainer = "container:AdvancedEffects.xcodeproj">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "NO"
buildForArchiving = "NO"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "00E356ED1AD99517003FC87E"
BuildableName = "AdvancedEffectsTests.xctest"
BlueprintName = "AdvancedEffectsTests"
ReferencedContainer = "container:AdvancedEffects.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
buildConfiguration = "Debug">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "00E356ED1AD99517003FC87E"
BuildableName = "AdvancedEffectsTests.xctest"
BlueprintName = "AdvancedEffectsTests"
ReferencedContainer = "container:AdvancedEffects.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
BuildableName = "AdvancedEffects.app"
BlueprintName = "AdvancedEffects"
ReferencedContainer = "container:AdvancedEffects.xcodeproj">
</BuildableReference>
</MacroExpansion>
</TestAction>
<LaunchAction
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
buildConfiguration = "Debug"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
BuildableName = "AdvancedEffects.app"
BlueprintName = "AdvancedEffects"
ReferencedContainer = "container:AdvancedEffects.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
buildConfiguration = "Release"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
BuildableName = "AdvancedEffects.app"
BlueprintName = "AdvancedEffects"
ReferencedContainer = "container:AdvancedEffects.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
## Developing with the example
```
npm install react-native
npm install ../.. # everytime the lib code changes
```
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import <UIKit/UIKit.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (nonatomic, strong) UIWindow *window;
@end
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import "AppDelegate.h"
#import "RCTRootView.h"
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSURL *jsCodeLocation;
/**
* Loading JavaScript code - uncomment the one you want.
*
* OPTION 1
* Load from development server. Start the server from the repository root:
*
* $ npm start
*
* To run on device, change `localhost` to the IP address of your computer
* (you can get this by typing `ifconfig` into the terminal and selecting the
* `inet` value under `en0:`) and make sure your computer and iOS device are
* on the same Wi-Fi network.
*/
jsCodeLocation = [NSURL URLWithString:@"http://192.168.0.26:8081/index.ios.bundle"];
/**
* OPTION 2
* Load from pre-bundled file on disk. To re-generate the static bundle
* from the root of your project directory, run
*
* $ react-native bundle --minify
*
* see http://facebook.github.io/react-native/docs/runningondevice.html
*/
// jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
moduleName:@"AdvancedEffects"
launchOptions:launchOptions];
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
UIViewController *rootViewController = [[UIViewController alloc] init];
rootViewController.view = rootView;
self.window.rootViewController = rootViewController;
[self.window makeKeyAndVisible];
return YES;
}
@end
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="7702" systemVersion="14D136" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7701"/>
<capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view contentMode="scaleToFill" id="iN0-l3-epB">
<rect key="frame" x="0.0" y="0.0" width="480" height="480"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Powered by React Native" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" translatesAutoresizingMaskIntoConstraints="NO" id="8ie-xW-0ye">
<rect key="frame" x="20" y="439" width="441" height="21"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="AdvancedEffects" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" minimumFontSize="18" translatesAutoresizingMaskIntoConstraints="NO" id="kId-c2-rCX">
<rect key="frame" x="20" y="140" width="441" height="43"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="36"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
<constraints>
<constraint firstItem="kId-c2-rCX" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="bottom" multiplier="1/3" constant="1" id="5cJ-9S-tgC"/>
<constraint firstAttribute="centerX" secondItem="kId-c2-rCX" secondAttribute="centerX" id="Koa-jz-hwk"/>
<constraint firstAttribute="bottom" secondItem="8ie-xW-0ye" secondAttribute="bottom" constant="20" id="Kzo-t9-V3l"/>
<constraint firstItem="8ie-xW-0ye" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="20" symbolic="YES" id="MfP-vx-nX0"/>
<constraint firstAttribute="centerX" secondItem="8ie-xW-0ye" secondAttribute="centerX" id="ZEH-qu-HZ9"/>
<constraint firstItem="kId-c2-rCX" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="20" symbolic="YES" id="fvb-Df-36g"/>
</constraints>
<nil key="simulatedStatusBarMetrics"/>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<point key="canvasLocation" x="548" y="455"/>
</view>
</objects>
</document>
{
"images" : [
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<key>NSLocationWhenInUseUsageDescription</key>
<string></string>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
</dict>
</plist>
// Offline JS
// To re-generate the offline bundle, run this from the root of your project:
//
// $ react-native bundle --minify
//
// See http://facebook.github.io/react-native/docs/runningondevice.html for more details.
throw new Error('Offline JS file is empty. See iOS/main.jsbundle for instructions');
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
int main(int argc, char * argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
const { AppRegistry } = require("react-native");
const AdvancedEffects = require("./src");
AppRegistry.registerComponent("AdvancedEffects", () => AdvancedEffects);
{
"name": "AdvancedEffects",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "node_modules/react-native/packager/packager.sh"
},
"dependencies": {
"react-native": "^0.9.0",
"gl-react-native": "0.0.x"
},
"devDependencies": {
"eslint": "^1.1.0",
"eslint-plugin-react": "^3.2.3"
}
}
const React = require("react-native");
const GL = require("gl-react-native");
const shaders = GL.Shaders.create({
banner: {
frag: `
precision highp float;
varying vec2 uv;
uniform float time;
void main( void ) {
float color = 0.0;
color += sin( uv.x * cos( time / 15.0 ) * 80.0 ) + cos( uv.y * cos( time / 15.0 ) * 10.0 );
color += sin( uv.y * sin( time / 10.0 ) * 40.0 ) + cos( uv.x * sin( time / 25.0 ) * 40.0 );
color += sin( uv.x * sin( time / 5.0 ) * 10.0 ) + sin( uv.y * sin( time / 35.0 ) * 80.0 );
color *= sin( time / 10.0 ) * 0.5;
gl_FragColor = vec4(
smoothstep(0.0, 1.5, color),
smoothstep(0.0, 0.5, color),
smoothstep(1.0, 0.6, color) - smoothstep(0.1, 0.0, color),
color
) * (pow(uv.y, 2.0));
}
`
}
});
class Banner extends React.Component {
render () {
const { width, height, time } = this.props;
return <GL.View
shader={shaders.banner}
style={{ width, height }}
uniforms={{ time: time }}
opaque={false}
/>;
}
}
module.exports = Banner;
const React = require("react-native");
const {
View,
Text,
} = React;
const GL = require("gl-react-native");
const shaders = GL.Shaders.create({
drunkEffect: {
frag: `
precision highp float;
varying vec2 uv;
uniform float time;
uniform float amp;
uniform float freq;
uniform float colorSeparation;
uniform sampler2D texture;
uniform float moving;
vec2 lookup (vec2 offset) {
return mod(
uv + amp * vec2(cos(freq*(uv.x+offset.x)+time),sin(freq*(uv.y+offset.x)+time)) + vec2(moving * time/10.0, 0.0),
vec2(1.0));
}
void main() {
gl_FragColor = vec4(
vec3(
texture2D(texture, lookup(vec2(colorSeparation))).r,
texture2D(texture, lookup(vec2(-colorSeparation))).g,
texture2D(texture, lookup(vec2(0.0))).b),
1.0);
}
`
}
});
class Intro extends React.Component {
render () {
const { time, fps, width, height } = this.props;
return <GL.View
shader={shaders.drunkEffect}
style={{ width, height }}
opaque={false}
uniforms={{
time: time,
freq: 12 - 9 * Math.sin(time / 7),
amp: 0.04 - 0.03 * Math.cos(time / 4),
colorSeparation: 0.02,
moving: 1
}}>
<GL.Target uniform="texture" style={{ justifyContent: "center" }}>
<Text style={{ color: "#00BDF3", fontSize: 24, letterSpacing: -2.0 }}>
GL REACT NATIVE
</Text>
<View style={{ flex: 1, flexDirection: "row", alignItems: "center", justifyContent: "center" }}>
<View style={{ backgroundColor: "#00FF66", marginRight: 8, width: 14, height: 14, borderRadius: 7, opacity: time%1 < 0.6 ? 1 : 0 }} />
<Text style={{ flex: 1, color: "#00FF66", fontSize: 14 }}>
{time.toFixed(2)}s
</Text>
<Text style={{ flex: 1, color: "#fff", fontSize: 14 }}>
{(fps).toFixed(0)} fps
</Text>
<Text style={{ flex: 1, color: "#999", fontSize: 14 }}>
{"<Text />"}
</Text>
</View>
</GL.Target>
</GL.View>;
}
}
module.exports = Intro;
const React = require("react-native");
const GL = require("gl-react-native");
const Transition = require("./Transition");
const shaders = GL.Shaders.create({
transitionDirectionalWipe: {
frag: `
precision highp float;
varying vec2 uv;
uniform sampler2D from;
uniform sampler2D to;
uniform float progress;
uniform vec2 direction;
uniform float smoothness;
const vec2 center = vec2(0.5, 0.5);
void main() {
vec2 v = normalize(direction);
v /= abs(v.x)+abs(v.y);
float d = v.x * center.x + v.y * center.y;
float m = smoothstep(-smoothness, 0.0, v.x * uv.x + v.y * uv.y - (d-0.5+progress*(1.+smoothness)));
gl_FragColor = mix(texture2D(to, uv), texture2D(from, uv), m);
}
`
},
transitionRandomSquares: {
frag: `
precision highp float;
varying vec2 uv;
uniform sampler2D from;
uniform sampler2D to;
uniform float progress;
uniform ivec2 size;
uniform float smoothness;
float rand (vec2 co) {
return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);
}
void main() {
float r = rand(floor(vec2(size) * uv));
float m = smoothstep(0.0, -smoothness, r - (progress * (1.0 + smoothness)));
gl_FragColor = mix(texture2D(from, uv), texture2D(to, uv), m);
}
`
},
transitionWind: {
frag: `
precision highp float;
varying vec2 uv;
uniform sampler2D from, to;
uniform float progress;
uniform float size;
float rand (vec2 co) {
return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);
}
void main() {
float r = rand(vec2(0, uv.y));
float m = smoothstep(0.0, -size, uv.x*(1.0-size) + size*r - (progress * (1.0 + size)));
gl_FragColor = mix(texture2D(from, uv), texture2D(to, uv), m);
}
`
}
});
class Slideshow extends React.Component {
render () {
const { duration, width, height, time, images } = this.props;
const slide = time / duration;
let transitionProgress = slide % 1;
let transitionFrom = images[Math.floor(slide) % images.length];
let transitionTo = images[Math.floor(slide+1) % images.length];
let transitionShader, transitionUniforms;
switch (Math.floor(slide/4) % 3) {
case 0:
transitionShader = shaders.transitionRandomSquares;
const w = 3 * (1 + Math.floor(slide % 8));
transitionUniforms = {
size: [w, w * 2 / 3],
smoothness: 0.5
};
break;
case 1:
transitionShader = shaders.transitionDirectionalWipe;
transitionUniforms = {
direction: [Math.cos(time/2), Math.sin(time/2)],
smoothness: 0.5
};
break;
case 2:
transitionShader = shaders.transitionWind;
transitionUniforms = {
size: 0.2
};
break;
}
return <Transition
width={width}
height={height}
progress={transitionProgress}
from={transitionFrom}
to={transitionTo}
shader={transitionShader}
uniforms={transitionUniforms}
/>;
}
}
module.exports = Slideshow;
const React = require("react-native");
const GL = require("gl-react-native");
class Transition extends React.Component {
render () {
const { width, height, shader, progress, from, to, uniforms } = this.props;
return <GL.View
shader={shader}
style={{ width, height }}
opaque={false}
uniforms={{
progress,
from,
to,
...uniforms
}}
/>;
}
}
module.exports = Transition;
const React = require("react-native");
const GL = require("gl-react-native");
const shaders = GL.Shaders.create({
imageVignette: {
frag: `
precision highp float;
varying vec2 uv;
uniform float time;
uniform float amp;
uniform float freq;
uniform float colorSeparation;
uniform sampler2D texture;
uniform float moving;
const vec2 center = vec2(0.5);
vec2 lookup (vec2 offset) {
return mod(
uv + amp * vec2(cos(freq*(uv.x+offset.x)+time),sin(freq*(uv.y+offset.x)+time)) + vec2(moving * time/10.0, 0.0),
vec2(1.0));
}
void main() {
gl_FragColor = vec4(
vec3(
texture2D(texture, lookup(vec2(colorSeparation))).r,
texture2D(texture, lookup(vec2(-colorSeparation))).g,
texture2D(texture, lookup(vec2(0.0))).b),
1.0-min(1.0, pow(1.9 * distance(uv, center), 4.0) + 0.5 * pow(distance(fract(50.0 * uv.y), 0.5), 2.0)));
}
`
}
});
class Vignette extends React.Component {
render () {
const { width, height, time, i, source } = this.props;
return <GL.View
shader={shaders.imageVignette}
style={{ width, height }}
opaque={false}
uniforms={{
time: time,
freq: (10+i)*(1+Math.sin(0.7*time + i)),
texture: source,
amp: 0.02 + Math.max(0, 0.05*i*Math.cos(time + 2*i)),
colorSeparation: 0.03,
moving: 0
}}
/>;
}
}
module.exports = Vignette;
const React = require("react-native");
const {
StyleSheet,
View,
StatusBarIOS,
} = React;
const { width: viewportW, height: viewportH } = require("Dimensions").get("window");
const Banner = require("./Banner");
const Intro = require("./Intro");
const Vignette = require("./Vignette");
const Slideshow = require("./Slideshow");
class AdvancedEffects extends React.Component {
constructor (props) {
super(props);
this.state = {
time: 0.02,
frames: 1,
images:
//"MQtLWbD,N8a9CkZ,adCmISK,AedZQ4N,y9qRJR3,brzKTYZ,NSyk07l,EaZiWfn,I1KZdnl,DoQBdzT,slIt2Ww,DA12puU,IYLdRFW,oqmO4Po,T6NaLyI,6XAPrAY,thYzbif,4qmqo3o,8xT2J96,ZCa2pWq,loQfDN2,oabfA68,uOXqDRY,MyyS4vK,fhNYTX4"
"ljVkFzQ,ljVkFzQ,qM9BHCy,F7NKlQF,rYcweR7,IE8T6UX,3On9QEu"
.split(",")
.map(id => ({ uri: `http://imgur.com/${id}.jpg` }))
};
StatusBarIOS.setHidden(true);
}
componentDidMount () {
let startTime;
const loop = t => {
requestAnimationFrame(loop);
if (!startTime) startTime = t;
const time = (t - startTime) / 1000;
this.setState({ time: time, frames: this.state.frames+1 });
};
requestAnimationFrame(loop);
}
render () {
const {time, frames, images} = this.state;
const nbVignettes = 1;
const imgW = Math.floor(viewportW/nbVignettes);
const imgH = Math.floor((2/3)*viewportW/nbVignettes);
const introH = 100;
const transitionH = Math.floor((2/3)*viewportW);
return (
<View style={styles.root}>
<Banner
time={time}
width={viewportW}
height={viewportH - introH - imgH - transitionH}
/>
<Intro
time={time}
fps={frames/time}
width={viewportW}
height={introH}
/>
<View style={{ flex: 1, flexWrap: "wrap", flexDirection: "row" }}>
{images.slice(0, nbVignettes).map((source, i) =>
<Vignette key={i}
time={time}
width={imgW}
height={imgH}
i={i}
source={source}
/>
)}
</View>
<Slideshow
time={time}
width={viewportW}
height={transitionH}
images={images.slice(2)}
duration={3}
/>
</View>
);
}
}
const styles = StyleSheet.create({
root: {
flex: 1,
backgroundColor: "#111"
}
});
module.exports = AdvancedEffects;
## Installation
a few steps are required to install gl-react-native:
### install the dependency from your React Native application.
```
npm i --save gl-react-native
```
### Configure your React Native Application
![](docs/install-steps.png)
## Credits / Inspiration
- [stack.gl](http://stack.gl/) approach
- [GLSL.io](http://glsl.io/) and [Diaporama](https://github.com/gre/diaporama)
- Source code of [React Native](https://github.com/facebook/react-native)
This diff is collapsed.
#import "RCTBridge.h"
#import "ImageData.h"
@interface GLReactImage: NSObject
@property (nonatomic, copy) NSString *src;
@property (nonatomic) UIImage *image;
- (instancetype)initWithBridge:(RCTBridge *)bridge withOnLoad:(void (^)(void))onload NS_DESIGNATED_INITIALIZER;
- (ImageData *) getImageData;
@end
#import "GLReactImage.h"
#import "GLUtils.h"
#import "ImageData.h"
#import "RCTBridge.h"
#import "RCTImageLoader.h"
#import "RCTLog.h"
@implementation GLReactImage
{
RCTBridge *_bridge; // React's bridge allow to access the imageLoader
UIImage *_image; // The currently loaded image (nil if no image fully loaded yet)
ImageData *_data; // Cache of the _data related to this image (computed by getImageData)
void (^_onload)(void); // called everytime an image loads
RCTImageLoaderCancellationBlock _loading; // the current loading cancellation function
}
- (instancetype)initWithBridge:(RCTBridge *)bridge withOnLoad:(void (^)(void))onload
{
if ((self = [super init])) {
_bridge = bridge;
_onload = onload;
_image = nil;
_loading = nil;
}
return self;
}
- (void)dealloc
{
[self clearImage];
if (_loading) _loading();
_onload = nil;
_loading = nil;
_bridge = nil;
}
RCT_NOT_IMPLEMENTED(-init)
- (void) clearImage
{
_image = nil;
_data = nil;
}
- (ImageData *) getImageData
{
if (!_data) {
_data = genPixelsWithImage(_image);
}
return _data;
}
- (void)setSrc:(NSString *)src
{
if (![src isEqual:_src]) {
_src = [src copy];
[self reloadImage];
}
}
- (void)reloadImage
{
if (_loading) _loading();
_loading = nil;
if (!_src) {
[self clearImage];
} else {
// Load the image (without resizing it)
if (![_src hasPrefix:@"http://"] && ![_src hasPrefix:@"http://"]) {
self.image = [UIImage imageNamed:_src];
if(_onload) _onload();
} else {
_loading = [_bridge.imageLoader loadImageWithTag:_src
size:CGSizeZero
scale:0
resizeMode:UIViewContentModeScaleToFill
progressBlock:nil
completionBlock:^(NSError *error, id image) {
_loading = nil;
[self clearImage];
if (error) {
NSLog(@"Image failed to load: %@", error);
} else {
self.image = image;
if(_onload) _onload();
}
}];
}
}
}
@end
#import <GLKit/GLKit.h>
#import "RCTBridgeModule.h"
@interface GLShader: NSObject
@property EAGLContext *context;
@property NSString *vert;
@property NSString *frag;
@property NSDictionary *uniformTypes;
/**
* Create a new shader with a vertex and fragment
*/
- (instancetype)initWithContext: (EAGLContext*)context withVert:(NSString *)vert withFrag:(NSString *)frag;
/**
* Bind the shader program as the current one
*/
- (void) bind;
/**
* Check the shader validity
*/
- (void) validate;
/**
* Set the value of an uniform
*/
- (void) setUniform: (NSString *)name withValue:(id)obj;
@end
This diff is collapsed.
#import <UIKit/UIKit.h>
#import "RCTBridgeModule.h"
#import "GLShader.h"
@interface GLShadersRegistry : NSObject <RCTBridgeModule>
/**
* Get the global shader for a given id.
*/
+ (GLShader*) getShader: (NSNumber *)ctxid;
@property NSMutableDictionary *shaders;
@end
#import <UIKit/UIKit.h>
#import "RCTBridgeModule.h"
#import "RCTConvert.h"
#import "RCTLog.h"
#import "GLShadersRegistry.h"
@implementation GLShadersRegistry
{
NSMutableDictionary *_shaders;
EAGLContext *_context;
}
GLShadersRegistry *GLShadersRegistry_instance; // FIXME is that the proper way to do singleton?
RCT_EXPORT_MODULE();
+ (GLShader*) getShader: (NSNumber *)ctxid
{
return [GLShadersRegistry_instance shaders][ctxid];
}
- (instancetype)init
{
self = [super init];
if (self) {
_context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
if (!_context) {
RCTLogError(@"Failed to initialize OpenGLES 2.0 context");
}
_shaders = @{}.mutableCopy;
GLShadersRegistry_instance = self;
}
return self;
}
static NSString* fullViewportVert = @"attribute vec2 position;varying vec2 uv;void main() {gl_Position = vec4(position,0.0,1.0);uv = vec2(0.5, 0.5) * (position+vec2(1.0, 1.0));}";
RCT_EXPORT_METHOD(register:(nonnull NSNumber *)id withConfig:(NSDictionary *)config) {
NSString *frag = [RCTConvert NSString:config[@"frag"]];
GLShader *shader = [[GLShader alloc] initWithContext:_context withVert:fullViewportVert withFrag:frag];
_shaders[id] = shader;
}
@end
#import <GLKit/GLKit.h>
#import "RCTBridge.h"
#import "ImageData.h"
@interface GLTexture: NSObject
@property EAGLContext *context;
- (instancetype)init;
- (int)bind: (int)unit;
- (void)setPixels: (ImageData *)data;
- (void)setPixelsEmpty;
- (void)setPixelsRandom: (int)width withHeight:(int)height;
- (void)setPixelsWithImage: (UIImage *)image;
- (void)setPixelsWithView: (UIView *)view;
@end
#import "GLTexture.h"
#import "GLUtils.h"
#import "RCTLog.h"
@implementation GLTexture
{
GLuint handle; // The identifier of the gl texture
ImageData* dataCurrentlyUploaded; // The last set data (cache)
}
- (instancetype)init
{
self = [super init];
if (self) {
[self makeTexture];
}
return self;
}
- (void)dealloc
{
glDeleteTextures(1, &handle);
dataCurrentlyUploaded = nil;
}
- (void) makeTexture
{
glGenTextures(1, &handle);
glBindTexture(GL_TEXTURE_2D, handle);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
- (bool) ensureContext
{
if (![EAGLContext setCurrentContext:_context]) {
RCTLogError(@"Failed to set current OpenGL context");
return false;
}
return true;
}
- (int)bind: (int)unit
{
glActiveTexture(GL_TEXTURE0 + unit);
glBindTexture(GL_TEXTURE_2D, handle);
return unit;
}
- (void)setPixels: (ImageData *)data
{
if (data != dataCurrentlyUploaded) {
dataCurrentlyUploaded = data;
glBindTexture(GL_TEXTURE_2D, handle);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, data.width, data.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data.data);
}
}
- (void)setPixelsEmpty
{
ImageData* data = genPixelsEmpty(2, 2);
[self setPixels:data];
}
- (void)setPixelsRandom: (int)width withHeight:(int)height // for testing
{
ImageData* data = genPixelsRandom(width, height);
[self setPixels:data];
}
- (void)setPixelsWithImage: (UIImage *)image
{
ImageData *data = genPixelsWithImage(image);
if (!data) return;
[self setPixels:data];
}
- (void)setPixelsWithView: (UIView *)view
{
ImageData *data = genPixelsWithView(view);
[self setPixels:data];
}
@end
#import <GLKit/GLKit.h>
#import "ImageData.h"
GLuint compileShader (NSString* shaderString, GLenum shaderType);
ImageData* genPixelsEmpty (int width, int height);
ImageData* genPixelsRandom (int width, int height);
ImageData* genPixelsWithImage (UIImage *image);
ImageData* genPixelsWithView (UIView *view);
\ No newline at end of file
#import "GLUtils.h"
#import "RCTLog.h"
GLuint compileShader (NSString* shaderString, GLenum shaderType) {
GLuint shaderHandle = glCreateShader(shaderType);
const char * shaderStringUTF8 = [shaderString UTF8String];
int shaderStringLength = (int) [shaderString length];
glShaderSource(shaderHandle, 1, &shaderStringUTF8, &shaderStringLength);
glCompileShader(shaderHandle);
GLint compileSuccess;
glGetShaderiv(shaderHandle, GL_COMPILE_STATUS, &compileSuccess);
if (compileSuccess == GL_FALSE) {
GLchar messages[256];
glGetShaderInfoLog(shaderHandle, sizeof(messages), 0, &messages[0]);
NSString *messageString = [NSString stringWithUTF8String:messages];
RCTLogError(@"GL: Shader Failed to compile: %@", messageString);
return -1;
}
return shaderHandle;
}
ImageData* 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 [[ImageData alloc] initWithData:data withWidth:width withHeight:height];
}
ImageData* 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 [[ImageData alloc] initWithData:data withWidth:width withHeight:height];
}
ImageData* 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 [[ImageData alloc] initWithData:data withWidth:width withHeight:height];
}
ImageData* genPixelsWithView (UIView *view)
{
int width = view.bounds.size.width;
int height = 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, view.bounds);
[view.layer renderInContext:ctx];
CGContextRelease(ctx);
return [[ImageData alloc] initWithData:data withWidth:width withHeight:height];
}
\ No newline at end of file
#import <GLKit/GLKit.h>
@interface GLView : GLKView
@property (nonatomic) NSNumber *shader;
@property (nonatomic) NSDictionary *uniforms;
@property (nonatomic) NSArray *targetUniforms;
@property (nonatomic) BOOL opaque;
- (instancetype)initWithBridge:(RCTBridge *)bridge;
@end
#import "RCTBridge.h"
#import "RCTUtils.h"
#import "RCTConvert.h"
#import "RCTLog.h"
#import "GLView.h"
#import "GLUtils.h"
#import "GLShader.h"
#import "GLShadersRegistry.h"
#import "GLTexture.h"
#import "GLReactImage.h"
@implementation GLView
{
RCTBridge *_bridge; // bridge is required to instanciate GLReactImage
GLShader *glShader; // The current GLShader used by the view
NSDictionary *_uniforms; // The current uniforms bound to the shader (name -> value)
NSArray *_targetUniforms; // When using GL.Target, this defines the uniform names to render into
NSDictionary *_textures; // This allocate the sampler2D uniforms of the shaders (name -> glTexture)
NSDictionary *_textureUnits; // This stores the image unit for a given sampler2D uniform (name -> int)
NSDictionary *_images; // This caches the currently used images (imageSrc -> GLReactImage)
BOOL _opaque; // opaque prop (if false, the GLView will become transparent)
BOOL _deferredRendering; // This flag indicates a render has been deferred to the next frame (when using GL.Target)
}
- (instancetype)initWithBridge:(RCTBridge *)bridge
{
if ((self = [super init])) {
_bridge = bridge;
_images = @{};
}
return self;
}
RCT_NOT_IMPLEMENTED(-init)
- (void)setShader:(NSNumber *)ctxid
{
glShader = [GLShadersRegistry getShader:ctxid];
if (!glShader) {
return; // the shader might not have been uploaded yet from the JS (invalid ctxid are checked on JS side to avoid concurrency issues)
}
[glShader bind];
// Cache the textures
NSMutableDictionary *textures = @{}.mutableCopy;
NSMutableDictionary *textureUnits = @{}.mutableCopy;
int unit = 0;
NSDictionary *uniformTypes = [glShader uniformTypes];
for (NSString *uniformName in [uniformTypes allKeys]) {
GLenum type = [uniformTypes[uniformName] intValue];
if (type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE) {
textures[uniformName] = [[GLTexture alloc] init];
textureUnits[uniformName] = [NSNumber numberWithInt: unit ++];
}
}
int maxTextureUnits;
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
if (unit > maxTextureUnits) {
RCTLogError(@"Maximum number of texture reach. got %i >= max %i", unit, maxTextureUnits);
}
_textures = textures;
_textureUnits = textureUnits;
// use the shader's context (currently it is the same for all shaders)
[self setContext:glShader.context];
[self setNeedsDisplay];
}
NSString* srcResource (id res)
{
BOOL isStatic = [RCTConvert BOOL:res[@"isStatic"]];
NSString *src = [RCTConvert NSString:res[@"path"]];
if (!src || isStatic) src = [RCTConvert NSString:res[@"uri"]];
return src;
}
- (void)setUniforms:(NSDictionary *)uniforms
{
/// Diff logic on texture uniforms to manage the _images cache.
NSMutableSet *currentResources = [[NSMutableSet alloc] init];
NSMutableDictionary *images = _images.mutableCopy;
for (NSString *name in [_uniforms allKeys]) {
id uniformValue = _uniforms[name];
GLTexture *texture = _textures[name];
if (texture) {
// Texture uniform
NSString *src = srcResource(uniformValue);
if (!src) {
RCTLogError(@"resource is not valid.");
return;
}
GLReactImage *image = _images[src];
if (!image) {
image = [[GLReactImage alloc] initWithBridge:_bridge withOnLoad:^{
[self setNeedsDisplay];
}];
images[src] = image;
}
image.src = src;
[currentResources addObject:src];
}
}
// remove old resources (that are not anymore used in new uniforms)
NSMutableSet *toDelete = [NSMutableSet setWithArray:[images allKeys]];
[toDelete minusSet:currentResources];
for (NSString *src in toDelete) {
GLReactImage *image = images[src];
image.src = nil;
}
[images removeObjectsForKeys:[toDelete allObjects]];
// Finally set the new state and request a rendering.
_images = images;
_uniforms = uniforms;
[self setNeedsDisplay];
}
- (void)setTargetUniforms:(NSArray *)targetUniforms
{
_targetUniforms = targetUniforms;
[self setNeedsDisplay];
}
- (void)setOpaque:(BOOL)opaque
{
_opaque = opaque;
[self setNeedsDisplay];
}
- (void)drawRect:(CGRect)rect
{
BOOL needsDeferredRendering = _targetUniforms != nil;
if (needsDeferredRendering && !_deferredRendering) {
dispatch_async(dispatch_get_main_queue(), ^{
_deferredRendering = true;
[self setNeedsDisplay];
});
}
else {
[self render:rect];
_deferredRendering = false;
}
}
- (void)render:(CGRect)rect
{
if (!glShader) {
return;
}
self.layer.opaque = _opaque;
[glShader bind];
// Setting uniforms
for (NSString *name in [_uniforms allKeys]) {
id uniformValue = _uniforms[name];
GLTexture *texture = _textures[name];
if (texture) {
// Texture uniform
int unit = [_textureUnits[name] intValue];
GLReactImage *image = _images[srcResource(uniformValue)];
NSNumber *value = [NSNumber numberWithInt: [texture bind:unit]];
if (image.image) {
[texture setPixels:[image getImageData]];
} else {
[texture setPixelsEmpty];
}
[glShader setUniform:name withValue:value];
} else {
// Simple uniform
[glShader setUniform:name withValue:uniformValue];
}
}
// Handling <GL.Target /> children rasterisation
if (_targetUniforms) {
int i = 0;
for (NSString *uniformName in _targetUniforms) {
GLTexture *texture = _textures[uniformName];
if (!texture) {
RCTLogError(@"There is no sampler uniform called '%@' in your shader", uniformName);
return;
}
UIView* view = self.superview.subviews[i]; // We take siblings by index (closely related to the JS code)
int unit = [_textureUnits[uniformName] intValue];
NSNumber *value = [NSNumber numberWithInt: [texture bind:unit]];
if (view) {
[texture setPixelsWithView:view];
} else {
[texture setPixelsEmpty];
}
[glShader setUniform:uniformName withValue:value];
i ++;
}
}
glClear(GL_COLOR_BUFFER_BIT);
glClearColor(0.0, 0.0, 0.0, 0.0);
CGFloat scale = RCTScreenScale();
glViewport(0, 0, scale * self.frame.size.width, scale * self.frame.size.height);
glScissor(scale * rect.origin.x, scale * rect.origin.y, scale * rect.size.width, scale * rect.size.height);
glDrawArrays(GL_TRIANGLES, 0, 6);
}
@end
\ No newline at end of file
#import "RCTViewManager.h"
@interface GLViewManager : RCTViewManager
@end
#import "GLViewManager.h"
#import "GLView.h"
#import "RCTLog.h"
#import <UIKit/UIKit.h>
@implementation GLViewManager
RCT_EXPORT_MODULE();
- (instancetype)init
{
self = [super init];
if (self) {
}
return self;
}
RCT_EXPORT_VIEW_PROPERTY(uniforms, NSDictionary);
RCT_EXPORT_VIEW_PROPERTY(shader, NSNumber);
RCT_EXPORT_VIEW_PROPERTY(targetUniforms, NSArray);
RCT_EXPORT_VIEW_PROPERTY(opaque, BOOL);
- (UIView *)view
{
GLView * v;
v = [[GLView alloc] initWithBridge:self.bridge];
return v;
}
@end
\ No newline at end of file
#import <GLKit/GLKit.h>
@interface ImageData: NSObject
@property (nonatomic) GLubyte *data;
@property (nonatomic) int width;
@property (nonatomic) int height;
- (instancetype)initWithData: (GLubyte *)data withWidth:(int)width withHeight:(int)height;
@end
#import "ImageData.h"
// This structure aims to be used in an immutable way
@implementation ImageData
{
GLubyte *_data;
int _width;
int _height;
}
- (instancetype)initWithData: (GLubyte *)data withWidth:(int)width withHeight:(int)height
{
self = [super init];
if (self) {
_data = data;
_width = width;
_height = height;
}
return self;
}
- (void)dealloc
{
if (_data) {
free(_data);
_data = nil;
_width = 0;
_height = 0;
}
}
@end
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>com.projectseptember.$(PRODUCT_NAME:rfc1034identifier)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
</dict>
</plist>
const invariant = require("invariant");
const React = require("react-native");
const {
NativeModules: { GLShadersRegistry },
requireNativeComponent,
Component,
PropTypes,
View,
} = React;
let _uid = 1;
const Shaders = {
create: function (obj) {
invariant(typeof obj === "object", "config must be an object");
const result = {};
for (let key in obj) {
// TODO : validate first
const id = _uid ++;
GLShadersRegistry.register(id, obj[key]);
result[key] = id;
}
return result;
},
exists: function (id) {
return typeof id === "number" && id >= 1 && id < _uid;
}
};
class Target extends Component {
render () {
invariant(
false,
"GL.Target elements are for GL.View configuration only and should not be rendered"
);
}
}
Target.displayName = "GL.Target";
Target.propTypes = {
children: PropTypes.any.isRequired,
uniform: PropTypes.string.isRequired
};
const GLViewNative = requireNativeComponent("GLView", GLView);
class GLView extends Component {
setNativeProps (props) {
this.refs.native.setNativeProps(props);
}
render() {
const props = this.props;
const { style, width, height, children, shader } = props;
invariant(Shaders.exists(shader), "Shader #%s does not exists", shader);
const nativeStyle = {
width: width,
height: height,
...style
};
if (children) {
const parentStyle = {
position: "relative",
width: nativeStyle.width,
height: nativeStyle.height,
overflow: "hidden"
};
const childrenStyle = {
position: "absolute",
top: 0,
left: 0,
width: nativeStyle.width,
height: nativeStyle.height
};
const targetUniforms = [];
const targets = React.Children.map(children, child => {
invariant(child.type === Target, "GL.View can only contains children of type GL.Target. Got '%s'", child.type && child.type.displayName || child);
const uniform = child.props.uniform;
targetUniforms.push(uniform);
return <View style={[ childrenStyle, child.props.style ]}>{child.props.children}</View>;
});
return <View style={parentStyle}>
{targets}
<GLViewNative ref="native" {...props} style={nativeStyle} children={undefined} targetUniforms={targetUniforms} />
</View>;
}
else {
return <GLViewNative ref="native" {...props} style={nativeStyle} />;
}
}
}
GLView.displayName = "GL.View";
GLView.propTypes = {
shader: PropTypes.number.isRequired,
width: PropTypes.number,
height: PropTypes.number,
uniforms: PropTypes.object,
childrenUniform: PropTypes.string,
opaque: PropTypes.bool
};
GLView.defaultProps = {
opaque: true
};
module.exports = {
View: GLView,
Target,
Shaders
};
{
"name": "gl-react-native",
"version": "0.0.1",
"description": "OpenGL bindings for react-native for complex effects on images and components",
"main": "index.js",
"repository": {
"type": "git",
"url": "github.com:ProjectSeptemberInc/gl-react-native.git"
},
"keywords": [
"gl",
"react-native"
],
"author": "Project September <tech@projectseptember.com>",
"license": "MIT",
"devDependencies": {
"react-native": "^0.9.0"
},
"peerDependencies": {
"react-native": "^0.9.0"
},
"dependencies": {
"invariant": "^2.1.0"
}
}
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