Add files via upload

This commit is contained in:
Steve Seguin 2021-09-19 00:27:01 -04:00 committed by GitHub
parent 491b41abca
commit 286bb5ef84
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
53 changed files with 1527 additions and 61 deletions

View File

@ -1,6 +1,4 @@
function effectsEngine(effectName){
var functions = {};
function loadScript(url){
var script = document.createElement('script');
script.type = 'text/javascript';
@ -13,61 +11,82 @@ function effectsEngine(effectName){
}
document.head.appendChild(script);
}
var loadList = [
"./thirdparty/jeeliz/jeelizFaceFilter.js",
"./thirdparty/jeeliz/three.min.js",
"./thirdparty/jeeliz/JeelizThreeHelper.js",
'./thirdparty/jeeliz/Tween.min.js'
];
loadList.reverse();
loadScript(loadList.pop());
var loadList = [];
if (typeof JEELIZFACEFILTER == 'undefined' || JEELIZFACEFILTER==null){
loadList.push("./thirdparty/jeeliz/jeelizFaceFilter.js");
}
if (typeof THREE == 'undefined' || THREE == null){
loadList.push("./thirdparty/jeeliz/three/v112/three.min.js");
} else {
console.log("typeof THREE:"+typeof THREE);
}
if (typeof JeelizThreeHelper == 'undefined' || JeelizThreeHelper==null){
loadList.push("./thirdparty/jeeliz/JeelizThreeHelper.js");
}
if (typeof TWEEN == 'undefined' || TWEEN == null){
loadList.push("./thirdparty/jeeliz/Tween.min.js");
}
if (loadList.length){
loadList.reverse();
loadScript(loadList.pop());
}
// some globals:
let THREECAMERA = null; // should be prop of window
let ANONYMOUSMESH = null;
let ANONYMOUSOBJ3D = null;
let isTransformed = false;
var pathname = window.location.pathname.split("/");
pathname.pop();
pathname = window.location.protocol + "//" + window.location.host + pathname.join("/");
// callback: launched if a face is detected or lost.
function detect_callback(isDetected) {
if (isDetected) {
console.log('INFO in detect_callback(): DETECTED');
} else {
console.log('INFO in detect_callback(): LOST');
}
// if (isDetected) {
// console.log('INFO in detect_callback(): DETECTED');
// } else {
// console.log('INFO in detect_callback(): LOST');
// }
}
// entry point:
function main(){
if (session.canvasSource && document.getElementById("effectsCanvasTarget") && JEELIZFACEFILTER){
//try {JEELIZFACEFILTER.destroy();}catch(e){}
try {
warnlog("LOADING JEELIZ");
THREECAMERA = null; // should be prop of window
ANONYMOUSMESH = null;
ANONYMOUSOBJ3D = null;
isTransformed = false;
init_faceFilter("effectsCanvasTarget", session.canvasSource);
} catch(e){
}
} else {
setTimeout(function(){main();},500);
errorlog("...");
warnlog("...retrying to load");
}
}
function init_faceFilter(canvasId, videoElement){
JEELIZFACEFILTER.init({
canvasId: canvasId,
NNCPath: 'https://stevesserver.com/neuralNets/',
NNCPath: pathname+'/thirdparty/jeeliz/neuralNets/',
videoSettings: {
videoElement: videoElement
},
callbackReady: function (errCode, spec) {
if (errCode) {
console.error(errCode);
try{
JEELIZFACEFILTER.toggle_pause(true,true);
} catch(e){}
errorlog(errCode);
try{
JEELIZFACEFILTER.destroy();
} catch(e){}
THREECAMERA = null; // should be prop of window
ANONYMOUSMESH = null;
ANONYMOUSOBJ3D = null;
isTransformed = false;
setTimeout(function(){main();},500);
return;
}
@ -100,16 +119,17 @@ function effectsEngine(effectName){
callbackTrack: function (detectState) {
if (effectName !== session.effects){
try{
JEELIZFACEFILTER.toggle_pause(true,true); // unload the filter when no longer active.
} catch(e){}
try{
JEELIZFACEFILTER.destroy();
} catch(e){}
JEELIZFACEFILTER.toggle_pause(true,false); // unload the filter when no longer active. Leaving the track active is required, else it breaks the app
} catch(e){errorlog(e);}
THREECAMERA = null; // should be prop of window
ANONYMOUSMESH = null;
ANONYMOUSOBJ3D = null;
isTransformed = false;
return;
}
warnlog("FOUND");
const isDetected = JeelizThreeHelper.get_isDetected();
//if (isDetected && detectState.expressions[0] >= 0.8 && !isTransformed) {
//if (isDetected && detectState.expressions[0] >= 0.8 && !isTransformed) { // If the person opens their mouth wide, then activate..
if (isDetected && !isTransformed){
isTransformed = true;
new TWEEN.Tween( ANONYMOUSMESH.material ).to({ opacity: 1}, 700).start(); // animation

357
filters/dog.js Normal file
View File

@ -0,0 +1,357 @@
function effectsEngine(effectName){
function loadScript(url){
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = url;
script.onload = function(){
this.remove();
if (loadList.length){
loadScript(loadList.pop());
}
}
document.head.appendChild(script);
}
var loadList = [];
if (typeof JEELIZFACEFILTER == 'undefined' || JEELIZFACEFILTER==null){
loadList.push("./thirdparty/jeeliz/jeelizFaceFilter.js");
}
if (typeof THREE == 'undefined' || THREE == null){
loadList.push("./thirdparty/jeeliz/three/v112/three.min.js");
} else {
console.log("typeof THREE:"+typeof THREE);
}
if (typeof JeelizThreeHelper == 'undefined' || JeelizThreeHelper==null){
loadList.push("./thirdparty/jeeliz/JeelizThreeHelper.js");
}
if (typeof TWEEN == 'undefined' || TWEEN == null){
loadList.push("./thirdparty/jeeliz/Tween.min.js");
}
loadList.push("./filters/dog/libs/glfx.js");
loadList.push("./thirdparty/jeeliz/three/customMaterials/FlexMaterial/ThreeFlexMaterial.js");
if (loadList.length){
loadList.reverse();
loadScript(loadList.pop());
}
var pathname = window.location.pathname.split("/");
pathname.pop();
pathname = window.location.protocol + "//" + window.location.host + pathname.join("/");
// some globals:
let THREECAMERA = null; // should be prop of window
let isTransformed = false;
let ISDETECTED = false;
let NOSEMESH = null, EARMESH = null;
let DOGOBJ3D = null, FRAMEOBJ3D = null;
let ISOVERTHRESHOLD = false, ISUNDERTRESHOLD = true;
let ISLOADED = false;
let MIXER = null;
let ACTION = null;
let ISANIMATING = false;
let ISOPAQUE = false;
let ISANIMATIONOVER = false;
let _flexParts = [];
let _videoGeometry = null;
// callback: launched if a face is detected or lost.
function detect_callback(isDetected) {
// if (isDetected) {
// console.log('INFO in detect_callback(): DETECTED');
// } else {
// console.log('INFO in detect_callback(): LOST');
// }
}
function create_mat2d(threeTexture, isTransparent){ // MT216: we put the creation of the video material in a func because we will also use it for the frame
return new THREE.RawShaderMaterial({
depthWrite: false,
depthTest: false,
transparent: isTransparent,
vertexShader: "attribute vec2 position;\n\
varying vec2 vUV;\n\
void main(void){\n\
gl_Position = vec4(position, 0., 1.);\n\
vUV = 0.5 + 0.5 * position;\n\
}",
fragmentShader: "precision lowp float;\n\
uniform sampler2D samplerVideo;\n\
varying vec2 vUV;\n\
void main(void){\n\
gl_FragColor = texture2D(samplerVideo, vUV);\n\
}",
uniforms:{
samplerVideo: { value: threeTexture }
}
});
}
function applyFilter() {
let canvas;
try {
canvas = fx.canvas();
} catch (e) {
alert('Ow no! WebGL isn\'t supported...')
return
}
const tempImage = new Image(512, 512);
tempImage.src = './filters/dog/images/texture_pink.jpg';
tempImage.onload = () => {
const texture = canvas.texture(tempImage);
// Create the effet
canvas.draw(texture).vignette(0.5, 0.6).update();
const canvasOpacity = document.createElement('canvas');
canvasOpacity.width = 512;
canvasOpacity.height = 512;
const ctx = canvasOpacity.getContext('2d');
ctx.globalAlpha = 0.2
ctx.drawImage(canvas, 0, 0, 512, 512);
// Add the effect
const calqueMesh = new THREE.Mesh(_videoGeometry, create_mat2d(new THREE.TextureLoader().load(canvasOpacity.toDataURL('image/png')), true))
calqueMesh.material.opacity = 0.2;
calqueMesh.material.transparent = true;
calqueMesh.renderOrder = 999; // render last
calqueMesh.frustumCulled = false;
FRAMEOBJ3D.add(calqueMesh);
}
}
// build the 3D. called once when Jeeliz Face Filter is OK
function init_threeScene(spec) {
// INIT THE THREE.JS context
const threeStuffs = JeelizThreeHelper.init(spec, detect_callback);
_videoGeometry = threeStuffs.videoMesh.geometry;
// CREATE OUR DOG EARS:
// let's begin by creating a loading manager that will allow us to
// have more control over the three parts of our dog model
const loadingManager = new THREE.LoadingManager();
const loaderEars = new THREE.BufferGeometryLoader(loadingManager);
loaderEars.load(
'./filters/dog/models/dog/dog_ears.json',
function (geometry) {
const mat = new THREE.FlexMaterial({
map: new THREE.TextureLoader().load('./filters/dog/models/dog/texture_ears.jpg'),
flexMap: new THREE.TextureLoader().load('./filters/dog/models/dog/flex_ears_256.jpg'),
alphaMap: new THREE.TextureLoader().load('./filters/dog/models/dog/alpha_ears_256.jpg'),
transparent: true,
opacity: 1,
bumpMap: new THREE.TextureLoader().load('./filters/dog/models/dog/normal_ears.jpg'),
bumpScale: 0.0075,
shininess: 1.5,
specular: 0xffffff,
});
EARMESH = new THREE.Mesh(geometry, mat);
EARMESH.scale.multiplyScalar(0.025);
EARMESH.position.setY(-0.3);
EARMESH.frustumCulled = false;
EARMESH.renderOrder = 10000;
EARMESH.material.opacity.value = 1;
}
);
// CREATE OUR DOG NOSE
const loaderNose = new THREE.BufferGeometryLoader(loadingManager);
loaderNose.load(
'./filters/dog/models/dog/dog_nose.json',
function (geometry) {
const mat = new THREE.MeshPhongMaterial({
map: new THREE.TextureLoader().load('./filters/dog/models/dog/texture_nose.jpg'),
shininess: 1.5,
specular: 0xffffff,
bumpMap: new THREE.TextureLoader().load('./filters/dog/models/dog/normal_nose.jpg'),
bumpScale: 0.005
});
NOSEMESH = new THREE.Mesh(geometry, mat);
NOSEMESH.scale.multiplyScalar(0.018);
NOSEMESH.position.setY(-0.05);
NOSEMESH.position.setZ(0.15);
NOSEMESH.frustumCulled = false;
NOSEMESH.renderOrder = 10000;
}
);
loadingManager.onLoad = () => {
DOGOBJ3D.add(EARMESH);
DOGOBJ3D.add(NOSEMESH);
threeStuffs.faceObject.add(DOGOBJ3D);
ISLOADED = true;
}
// CREATE AN AMBIENT LIGHT
const ambient = new THREE.AmbientLight(0xffffff, 0.8);
threeStuffs.scene.add(ambient);
// CREAT A DIRECTIONALLIGHT
const dirLight = new THREE.DirectionalLight(0xffffff, 0.5);
dirLight.position.set(100, 1000, 1000);
threeStuffs.scene.add(dirLight);
// CREATE THE CAMERA
THREECAMERA = JeelizThreeHelper.create_camera();
threeStuffs.scene.add(FRAMEOBJ3D);
// Add filter
applyFilter();
} // end init_threeScene()
function animateTongue (mesh, isReverse) {
mesh.visible = true;
if (isReverse) {
ACTION.timescale = -1;
ACTION.paused = false;
setTimeout(() => {
ACTION.paused = true;
ISOPAQUE = false;
ISANIMATING = false;
ISANIMATIONOVER = true;
new TWEEN.Tween(mesh.material.opacity)
.to({ value: 0 }, 150)
.start();
}, 150);
} else {
ACTION.timescale = 1;
ACTION.reset();
ACTION.paused = false;
new TWEEN.Tween(mesh.material.opacity)
.to({ value: 1 }, 100)
.onComplete(() => {
ISOPAQUE = true;
setTimeout(() => {
ACTION.paused = true;
ISANIMATING = false;
ISANIMATIONOVER = true;
}, 150);
})
.start();
}
}
// entry point:
function main(){
if (session.canvasSource && document.getElementById("effectsCanvasTarget") && JEELIZFACEFILTER){
try {
warnlog("LOADING JEELIZ");
THREECAMERA = null; // should be prop of window
isTransformed = false;
DOGOBJ3D = new THREE.Object3D();
FRAMEOBJ3D = new THREE.Object3D();
init_faceFilter("effectsCanvasTarget", session.canvasSource);
} catch(e){
}
} else {
setTimeout(function(){main();},500);
warnlog("...retrying to load");
}
}
function init_faceFilter(canvasId, videoElement){
JEELIZFACEFILTER.init({
canvasId: canvasId,
NNCPath: pathname+'/thirdparty/jeeliz/neuralNets/',
videoSettings: {
videoElement: videoElement
},
callbackReady: function (errCode, spec) {
if (errCode) {
errorlog(errCode);
try{
JEELIZFACEFILTER.destroy();
} catch(e){}
THREECAMERA = null; // should be prop of window
DOGOBJ3D=null;
FRAMEOBJ3D=null;
isTransformed = false;
setTimeout(function(){main();},500);
return;
}
init_threeScene(spec);
},
callbackTrack: function (detectState) {
if (effectName !== session.effects){
try{
JEELIZFACEFILTER.toggle_pause(true,false); // unload the filter when no longer active. Leaving the track active is required, else it breaks the app
} catch(e){errorlog(e);}
THREECAMERA = null; // should be prop of window
isTransformed = false;
DOGOBJ3D=null;
FRAMEOBJ3D=null;
return;
}
const ISDETECTED = JeelizThreeHelper.get_isDetected();
//if (isDetected && detectState.expressions[0] >= 0.8 && !isTransformed) { // If the person opens their mouth wide, then activate..
if (ISDETECTED){
const _quat = new THREE.Quaternion();
const _eul = new THREE.Euler();
_eul.setFromQuaternion(_quat);
// flex ears material:
if (EARMESH && EARMESH.material.set_amortized){
EARMESH.material.set_amortized(
EARMESH.getWorldPosition(new THREE.Vector3(0,0,0)),
EARMESH.getWorldScale(new THREE.Vector3(0,0,0)),
EARMESH.getWorldQuaternion(_eul),
false,
0.1
);
}
if (detectState.expressions[0] >= 0.85 && !ISOVERTHRESHOLD) {
ISOVERTHRESHOLD = true;
ISUNDERTRESHOLD = false;
ISANIMATIONOVER = false;
}
if (detectState.expressions[0] <= 0.1 && !ISUNDERTRESHOLD) {
ISOVERTHRESHOLD = false;
ISUNDERTRESHOLD = true;
ISANIMATIONOVER = false;
}
}
TWEEN.update();
if (ISOPAQUE) {
MIXER.update(0.16);
}
JeelizThreeHelper.render(detectState, THREECAMERA);
}
});
}
return main;
}

View File

@ -0,0 +1,132 @@
"use strict";
THREE.FlexMaterial = function(spec){
const _worldMatrixDelayed = new THREE['Matrix4']();
function mix(a,b,t){
a.set(
b.x*t+a.x*(1-t),
b.y*t+a.y*(1-t),
b.z*t+a.z*(1-t)
);
}
// tweak shaders helpers:
function tweak_shaderAdd(code, chunk, glslCode){
return code.replace(chunk, chunk+"\n"+glslCode);
}
function tweak_shaderDel(code, chunk){
return code.replace(chunk, '');
}
function tweak_shaderRepl(code, chunk, glslCode){
return code.replace(chunk, glslCode);
}
// get PHONG shader and tweak it :
const phongShader = THREE.ShaderLib.phong;
let vertexShaderSource = phongShader.vertexShader;
vertexShaderSource = tweak_shaderAdd(vertexShaderSource, '#include <common>',
'uniform mat4 modelMatrixDelayed;\n'
+'uniform sampler2D flexMap;\n'
);
vertexShaderSource = tweak_shaderDel(vertexShaderSource, '#include <worldpos_vertex>');
vertexShaderSource = tweak_shaderRepl(vertexShaderSource, '#include <project_vertex>',
"vec4 worldPosition = modelMatrix * vec4( transformed, 1.0 );\n\
vec4 worldPositionDelayed = modelMatrixDelayed * vec4( transformed, 1.0 );\n\
worldPosition = mix(worldPosition, worldPositionDelayed, texture2D(flexMap, uv).r);\n\
vec4 mvPosition = viewMatrix* worldPosition;\n\
gl_Position = projectionMatrix * mvPosition;");
const uniforms0 = {
'modelMatrixDelayed': {
'value': _worldMatrixDelayed
},
'flexMap': {
value: spec.flexMap
},
'opacity': {
value: (typeof(spec.opacity)!=='undefined')?spec.opacity:1
}
};
const uniforms = Object.assign({}, phongShader.uniforms, uniforms0);
const isMorphs = (spec.morphTargets) ? true : false;
const mat = new THREE.ShaderMaterial({
vertexShader: vertexShaderSource,
fragmentShader: phongShader.fragmentShader,
uniforms: uniforms,
transparent: (spec.transparent)?true:false,
lights: true,
morphTargets: isMorphs,
morphNormals: isMorphs
});
mat.flexMap = spec.flexMap;
mat.opacity = mat.uniforms.opacity; // shortcut
if (typeof(spec.map)!=='undefined') {
uniforms.map = {value: spec.map};
mat.map = spec.map;
}
if (typeof(spec.alphaMap)!=='undefined') {
uniforms.alphaMap = {value: spec.alphaMap};
mat.transparent = true;
mat.alphaMap = spec.alphaMap;
}
if (typeof(spec.bumpMap)!=='undefined') {
uniforms.bumpMap = {value: spec.bumpMap};
mat.bumpMap = spec.bumpMap;
}
if (typeof(spec.bumpScale)!=='undefined') {
uniforms.bumpScale = {value: spec.bumpScale};
mat.bumpScale = spec.bumpScale;
}
if (typeof(spec.shininess)!=='undefined') {
uniforms.shininess = {value: spec.shininess};
mat.shininess = spec.shininess;
}
const _positionDelayed = new THREE.Vector3();
const _scaleDelayed = new THREE.Vector3();
const _eulerDelayed = new THREE['Euler']();
let _initialized = false;
mat.set_amortized = function(positionTarget, scaleTarget, eulerTarget, parentMatrix, amortization){
if (!_initialized){
if (positionTarget){
_positionDelayed.copy(positionTarget);
}
if (scaleTarget){
_scaleDelayed.copy(scaleTarget);
}
if (eulerTarget){
_eulerDelayed.copy(eulerTarget);
}
_initialized = true;
}
if (eulerTarget){
mix( _eulerDelayed, eulerTarget, amortization );
_worldMatrixDelayed['makeRotationFromEuler'](_eulerDelayed);
}
if (positionTarget){
mix( _positionDelayed, positionTarget, amortization );
_worldMatrixDelayed['setPosition'](_positionDelayed);
}
if (scaleTarget){
mix(_scaleDelayed, scaleTarget, amortization );
_worldMatrixDelayed['scale'](_scaleDelayed);
}
if (parentMatrix){
_worldMatrixDelayed.multiplyMatrices(parentMatrix, _worldMatrixDelayed);
}
}
return mat;
};

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

87
filters/dog/index.html Normal file
View File

@ -0,0 +1,87 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="content-language" content="en-EN" />
<title>JEELIZ FACEFILTER: DOG</title>
<!-- INCLUDE JEELIZ FACEFILTER SCRIPT -->
<script src="../../../dist/jeelizFaceFilter.js"></script>
<!-- INCLUDE THREE.JS -->
<script src="../../../libs/three/v97/three.js"></script>
<!-- INCLUDE JEELIZRESIZER -->
<script src="../../../helpers/JeelizResizer.js"></script>
<!-- INCLUDE JEELIZTHREEJSHELPER -->
<script src="../../../helpers/JeelizThreeHelper.js"></script>
<!-- INCLUDE FLEXMATERIAL (CUSTOM DEV) -->
<script src="../../../libs/three/customMaterials/FlexMaterial/ThreeFlexMaterial.js"></script>
<!-- INCLUDE TWEEN.JS -->
<script src='../../../libs/tween/v16_3_5/Tween.min.js'></script>
<!-- INCLUDE JQUERY -->
<script src='../../../libs/jquery/jquery-3.3.1.min.js'></script>
<!-- INCLUDE GLFX -->
<script src='libs/glfx.js'></script>
<!-- INCLUDE DEMO SCRIPT -->
<script src="./main.js"></script>
<!-- INCLUDE ADDDRAGEVENTLISTENER.JS -->
<script src='../../../helpers/addDragEventListener.js'></script>
<!-- INCLUDE FORK ME ON GITHUB BANNER -->
<script src="../../appearance/widget.js"></script>
<link rel="stylesheet" href="../../appearance/style.css" type="text/css" />
<style>
.canvasContainer {
position: relative;
margin: 0 auto;
text-align: center;
}
#jeeFaceFilterCanvas {
z-index: 0;
max-height: 100%;
left: auto;
top: auto;
width: 100vmin;
transform: translate(0,0) rotateY(180deg);
position: static;
}
img {
max-width: 100%;
}
#filter {
position: absolute;
z-index: 0;
max-height: 100%;
width: 100vmin;
top: 0;
left: 50%;
transform: translate(-50%);
opacity: 0.15;
}
#filter canvas {
width: 100%;
height: 100%;
}
</style>
</head>
<body onload="main()">
<div class="canvasContainer">
<canvas width="600" height="600" id='jeeFaceFilterCanvas'></canvas>
<div id='filter'></div>
</div>
</body>
</html>

59
filters/dog/libs/glfx.js Normal file
View File

@ -0,0 +1,59 @@
/*
* glfx.js
* http://evanw.github.com/glfx.js/
*
* Copyright 2011 Evan Wallace
* Released under the MIT license
*/
var fx=function(){function q(a,d,c){return Math.max(a,Math.min(d,c))}function w(b){return{_:b,loadContentsOf:function(b){a=this._.gl;this._.loadContentsOf(b)},destroy:function(){a=this._.gl;this._.destroy()}}}function A(a){return w(r.fromElement(a))}function B(b,d){var c=a.UNSIGNED_BYTE;if(a.getExtension("OES_texture_float")&&a.getExtension("OES_texture_float_linear")){var e=new r(100,100,a.RGBA,a.FLOAT);try{e.drawTo(function(){c=a.FLOAT})}catch(g){}e.destroy()}this._.texture&&this._.texture.destroy();
this._.spareTexture&&this._.spareTexture.destroy();this.width=b;this.height=d;this._.texture=new r(b,d,a.RGBA,c);this._.spareTexture=new r(b,d,a.RGBA,c);this._.extraTexture=this._.extraTexture||new r(0,0,a.RGBA,c);this._.flippedShader=this._.flippedShader||new h(null,"uniform sampler2D texture;varying vec2 texCoord;void main(){gl_FragColor=texture2D(texture,vec2(texCoord.x,1.0-texCoord.y));}");this._.isInitialized=!0}function C(a,d,c){this._.isInitialized&&
a._.width==this.width&&a._.height==this.height||B.call(this,d?d:a._.width,c?c:a._.height);a._.use();this._.texture.drawTo(function(){h.getDefaultShader().drawRect()});return this}function D(){this._.texture.use();this._.flippedShader.drawRect();return this}function f(a,d,c,e){(c||this._.texture).use();this._.spareTexture.drawTo(function(){a.uniforms(d).drawRect()});this._.spareTexture.swapWith(e||this._.texture)}function E(a){a.parentNode.insertBefore(this,a);a.parentNode.removeChild(a);return this}
function F(){var b=new r(this._.texture.width,this._.texture.height,a.RGBA,a.UNSIGNED_BYTE);this._.texture.use();b.drawTo(function(){h.getDefaultShader().drawRect()});return w(b)}function G(){var b=this._.texture.width,d=this._.texture.height,c=new Uint8Array(4*b*d);this._.texture.drawTo(function(){a.readPixels(0,0,b,d,a.RGBA,a.UNSIGNED_BYTE,c)});return c}function k(b){return function(){a=this._.gl;return b.apply(this,arguments)}}function x(a,d,c,e,g,l,n,p){var m=c-g,h=e-l,f=n-g,k=p-l;g=a-c+g-n;l=
d-e+l-p;var q=m*k-f*h,f=(g*k-f*l)/q,m=(m*l-g*h)/q;return[c-a+f*c,e-d+f*e,f,n-a+m*n,p-d+m*p,m,a,d,1]}function y(a){var d=a[0],c=a[1],e=a[2],g=a[3],l=a[4],n=a[5],p=a[6],m=a[7];a=a[8];var f=d*l*a-d*n*m-c*g*a+c*n*p+e*g*m-e*l*p;return[(l*a-n*m)/f,(e*m-c*a)/f,(c*n-e*l)/f,(n*p-g*a)/f,(d*a-e*p)/f,(e*g-d*n)/f,(g*m-l*p)/f,(c*p-d*m)/f,(d*l-c*g)/f]}function z(a){var d=a.length;this.xa=[];this.ya=[];this.u=[];this.y2=[];a.sort(function(a,b){return a[0]-b[0]});for(var c=0;c<d;c++)this.xa.push(a[c][0]),this.ya.push(a[c][1]);
this.u[0]=0;this.y2[0]=0;for(c=1;c<d-1;++c){a=this.xa[c+1]-this.xa[c-1];var e=(this.xa[c]-this.xa[c-1])/a,g=e*this.y2[c-1]+2;this.y2[c]=(e-1)/g;this.u[c]=(6*((this.ya[c+1]-this.ya[c])/(this.xa[c+1]-this.xa[c])-(this.ya[c]-this.ya[c-1])/(this.xa[c]-this.xa[c-1]))/a-e*this.u[c-1])/g}this.y2[d-1]=0;for(c=d-2;0<=c;--c)this.y2[c]=this.y2[c]*this.y2[c+1]+this.u[c]}function u(a,d){return new h(null,a+"uniform sampler2D texture;uniform vec2 texSize;varying vec2 texCoord;void main(){vec2 coord=texCoord*texSize;"+
d+"gl_FragColor=texture2D(texture,coord/texSize);vec2 clampedCoord=clamp(coord,vec2(0.0),texSize);if(coord!=clampedCoord){gl_FragColor.a*=max(0.0,1.0-length(coord-clampedCoord));}}")}function H(b,d){a.brightnessContrast=a.brightnessContrast||new h(null,"uniform sampler2D texture;uniform float brightness;uniform float contrast;varying vec2 texCoord;void main(){vec4 color=texture2D(texture,texCoord);color.rgb+=brightness;if(contrast>0.0){color.rgb=(color.rgb-0.5)/(1.0-contrast)+0.5;}else{color.rgb=(color.rgb-0.5)*(1.0+contrast)+0.5;}gl_FragColor=color;}");
f.call(this,a.brightnessContrast,{brightness:q(-1,b,1),contrast:q(-1,d,1)});return this}function t(a){a=new z(a);for(var d=[],c=0;256>c;c++)d.push(q(0,Math.floor(256*a.interpolate(c/255)),255));return d}function I(b,d,c){b=t(b);1==arguments.length?d=c=b:(d=t(d),c=t(c));for(var e=[],g=0;256>g;g++)e.splice(e.length,0,b[g],d[g],c[g],255);this._.extraTexture.initFromBytes(256,1,e);this._.extraTexture.use(1);a.curves=a.curves||new h(null,"uniform sampler2D texture;uniform sampler2D map;varying vec2 texCoord;void main(){vec4 color=texture2D(texture,texCoord);color.r=texture2D(map,vec2(color.r)).r;color.g=texture2D(map,vec2(color.g)).g;color.b=texture2D(map,vec2(color.b)).b;gl_FragColor=color;}");
a.curves.textures({map:1});f.call(this,a.curves,{});return this}function J(b){a.denoise=a.denoise||new h(null,"uniform sampler2D texture;uniform float exponent;uniform float strength;uniform vec2 texSize;varying vec2 texCoord;void main(){vec4 center=texture2D(texture,texCoord);vec4 color=vec4(0.0);float total=0.0;for(float x=-4.0;x<=4.0;x+=1.0){for(float y=-4.0;y<=4.0;y+=1.0){vec4 sample=texture2D(texture,texCoord+vec2(x,y)/texSize);float weight=1.0-abs(dot(sample.rgb-center.rgb,vec3(0.25)));weight=pow(weight,exponent);color+=sample*weight;total+=weight;}}gl_FragColor=color/total;}");
for(var d=0;2>d;d++)f.call(this,a.denoise,{exponent:Math.max(0,b),texSize:[this.width,this.height]});return this}function K(b,d){a.hueSaturation=a.hueSaturation||new h(null,"uniform sampler2D texture;uniform float hue;uniform float saturation;varying vec2 texCoord;void main(){vec4 color=texture2D(texture,texCoord);float angle=hue*3.14159265;float s=sin(angle),c=cos(angle);vec3 weights=(vec3(2.0*c,-sqrt(3.0)*s-c,sqrt(3.0)*s-c)+1.0)/3.0;float len=length(color.rgb);color.rgb=vec3(dot(color.rgb,weights.xyz),dot(color.rgb,weights.zxy),dot(color.rgb,weights.yzx));float average=(color.r+color.g+color.b)/3.0;if(saturation>0.0){color.rgb+=(average-color.rgb)*(1.0-1.0/(1.001-saturation));}else{color.rgb+=(average-color.rgb)*(-saturation);}gl_FragColor=color;}");
f.call(this,a.hueSaturation,{hue:q(-1,b,1),saturation:q(-1,d,1)});return this}function L(b){a.noise=a.noise||new h(null,"uniform sampler2D texture;uniform float amount;varying vec2 texCoord;float rand(vec2 co){return fract(sin(dot(co.xy,vec2(12.9898,78.233)))*43758.5453);}void main(){vec4 color=texture2D(texture,texCoord);float diff=(rand(texCoord)-0.5)*amount;color.r+=diff;color.g+=diff;color.b+=diff;gl_FragColor=color;}");
f.call(this,a.noise,{amount:q(0,b,1)});return this}function M(b){a.sepia=a.sepia||new h(null,"uniform sampler2D texture;uniform float amount;varying vec2 texCoord;void main(){vec4 color=texture2D(texture,texCoord);float r=color.r;float g=color.g;float b=color.b;color.r=min(1.0,(r*(1.0-(0.607*amount)))+(g*(0.769*amount))+(b*(0.189*amount)));color.g=min(1.0,(r*0.349*amount)+(g*(1.0-(0.314*amount)))+(b*0.168*amount));color.b=min(1.0,(r*0.272*amount)+(g*0.534*amount)+(b*(1.0-(0.869*amount))));gl_FragColor=color;}");
f.call(this,a.sepia,{amount:q(0,b,1)});return this}function N(b,d){a.unsharpMask=a.unsharpMask||new h(null,"uniform sampler2D blurredTexture;uniform sampler2D originalTexture;uniform float strength;uniform float threshold;varying vec2 texCoord;void main(){vec4 blurred=texture2D(blurredTexture,texCoord);vec4 original=texture2D(originalTexture,texCoord);gl_FragColor=mix(blurred,original,1.0+strength);}");
this._.extraTexture.ensureFormat(this._.texture);this._.texture.use();this._.extraTexture.drawTo(function(){h.getDefaultShader().drawRect()});this._.extraTexture.use(1);this.triangleBlur(b);a.unsharpMask.textures({originalTexture:1});f.call(this,a.unsharpMask,{strength:d});this._.extraTexture.unuse(1);return this}function O(b){a.vibrance=a.vibrance||new h(null,"uniform sampler2D texture;uniform float amount;varying vec2 texCoord;void main(){vec4 color=texture2D(texture,texCoord);float average=(color.r+color.g+color.b)/3.0;float mx=max(color.r,max(color.g,color.b));float amt=(mx-average)*(-amount*3.0);color.rgb=mix(color.rgb,vec3(mx),amt);gl_FragColor=color;}");
f.call(this,a.vibrance,{amount:q(-1,b,1)});return this}function P(b,d){a.vignette=a.vignette||new h(null,"uniform sampler2D texture;uniform float size;uniform float amount;varying vec2 texCoord;void main(){vec4 color=texture2D(texture,texCoord);float dist=distance(texCoord,vec2(0.5,0.5));color.rgb*=smoothstep(0.8,size*0.799,dist*(amount+size));gl_FragColor=color;}");
f.call(this,a.vignette,{size:q(0,b,1),amount:q(0,d,1)});return this}function Q(b,d,c){a.lensBlurPrePass=a.lensBlurPrePass||new h(null,"uniform sampler2D texture;uniform float power;varying vec2 texCoord;void main(){vec4 color=texture2D(texture,texCoord);color=pow(color,vec4(power));gl_FragColor=vec4(color);}");var e="uniform sampler2D texture0;uniform sampler2D texture1;uniform vec2 delta0;uniform vec2 delta1;uniform float power;varying vec2 texCoord;"+
s+"vec4 sample(vec2 delta){float offset=random(vec3(delta,151.7182),0.0);vec4 color=vec4(0.0);float total=0.0;for(float t=0.0;t<=30.0;t++){float percent=(t+offset)/30.0;color+=texture2D(texture0,texCoord+delta*percent);total+=1.0;}return color/total;}";
a.lensBlur0=a.lensBlur0||new h(null,e+"void main(){gl_FragColor=sample(delta0);}");a.lensBlur1=a.lensBlur1||new h(null,e+"void main(){gl_FragColor=(sample(delta0)+sample(delta1))*0.5;}");a.lensBlur2=a.lensBlur2||(new h(null,e+"void main(){vec4 color=(sample(delta0)+2.0*texture2D(texture1,texCoord))/3.0;gl_FragColor=pow(color,vec4(power));}")).textures({texture1:1});for(var e=
[],g=0;3>g;g++){var l=c+2*g*Math.PI/3;e.push([b*Math.sin(l)/this.width,b*Math.cos(l)/this.height])}b=Math.pow(10,q(-1,d,1));f.call(this,a.lensBlurPrePass,{power:b});this._.extraTexture.ensureFormat(this._.texture);f.call(this,a.lensBlur0,{delta0:e[0]},this._.texture,this._.extraTexture);f.call(this,a.lensBlur1,{delta0:e[1],delta1:e[2]},this._.extraTexture,this._.extraTexture);f.call(this,a.lensBlur0,{delta0:e[1]});this._.extraTexture.use(1);f.call(this,a.lensBlur2,{power:1/b,delta0:e[2]});return this}
function R(b,d,c,e,g,l){a.tiltShift=a.tiltShift||new h(null,"uniform sampler2D texture;uniform float blurRadius;uniform float gradientRadius;uniform vec2 start;uniform vec2 end;uniform vec2 delta;uniform vec2 texSize;varying vec2 texCoord;"+s+"void main(){vec4 color=vec4(0.0);float total=0.0;float offset=random(vec3(12.9898,78.233,151.7182),0.0);vec2 normal=normalize(vec2(start.y-end.y,end.x-start.x));float radius=smoothstep(0.0,1.0,abs(dot(texCoord*texSize-start,normal))/gradientRadius)*blurRadius;for(float t=-30.0;t<=30.0;t++){float percent=(t+offset-0.5)/30.0;float weight=1.0-abs(percent);vec4 sample=texture2D(texture,texCoord+delta/texSize*percent*radius);sample.rgb*=sample.a;color+=sample*weight;total+=weight;}gl_FragColor=color/total;gl_FragColor.rgb/=gl_FragColor.a+0.00001;}");
var n=c-b,p=e-d,m=Math.sqrt(n*n+p*p);f.call(this,a.tiltShift,{blurRadius:g,gradientRadius:l,start:[b,d],end:[c,e],delta:[n/m,p/m],texSize:[this.width,this.height]});f.call(this,a.tiltShift,{blurRadius:g,gradientRadius:l,start:[b,d],end:[c,e],delta:[-p/m,n/m],texSize:[this.width,this.height]});return this}function S(b){a.triangleBlur=a.triangleBlur||new h(null,"uniform sampler2D texture;uniform vec2 delta;varying vec2 texCoord;"+s+"void main(){vec4 color=vec4(0.0);float total=0.0;float offset=random(vec3(12.9898,78.233,151.7182),0.0);for(float t=-30.0;t<=30.0;t++){float percent=(t+offset-0.5)/30.0;float weight=1.0-abs(percent);vec4 sample=texture2D(texture,texCoord+delta*percent);sample.rgb*=sample.a;color+=sample*weight;total+=weight;}gl_FragColor=color/total;gl_FragColor.rgb/=gl_FragColor.a+0.00001;}");
f.call(this,a.triangleBlur,{delta:[b/this.width,0]});f.call(this,a.triangleBlur,{delta:[0,b/this.height]});return this}function T(b,d,c){a.zoomBlur=a.zoomBlur||new h(null,"uniform sampler2D texture;uniform vec2 center;uniform float strength;uniform vec2 texSize;varying vec2 texCoord;"+s+"void main(){vec4 color=vec4(0.0);float total=0.0;vec2 toCenter=center-texCoord*texSize;float offset=random(vec3(12.9898,78.233,151.7182),0.0);for(float t=0.0;t<=40.0;t++){float percent=(t+offset)/40.0;float weight=4.0*(percent-percent*percent);vec4 sample=texture2D(texture,texCoord+toCenter*percent*strength/texSize);sample.rgb*=sample.a;color+=sample*weight;total+=weight;}gl_FragColor=color/total;gl_FragColor.rgb/=gl_FragColor.a+0.00001;}");
f.call(this,a.zoomBlur,{center:[b,d],strength:c,texSize:[this.width,this.height]});return this}function U(b,d,c,e){a.colorHalftone=a.colorHalftone||new h(null,"uniform sampler2D texture;uniform vec2 center;uniform float angle;uniform float scale;uniform vec2 texSize;varying vec2 texCoord;float pattern(float angle){float s=sin(angle),c=cos(angle);vec2 tex=texCoord*texSize-center;vec2 point=vec2(c*tex.x-s*tex.y,s*tex.x+c*tex.y)*scale;return(sin(point.x)*sin(point.y))*4.0;}void main(){vec4 color=texture2D(texture,texCoord);vec3 cmy=1.0-color.rgb;float k=min(cmy.x,min(cmy.y,cmy.z));cmy=(cmy-k)/(1.0-k);cmy=clamp(cmy*10.0-3.0+vec3(pattern(angle+0.26179),pattern(angle+1.30899),pattern(angle)),0.0,1.0);k=clamp(k*10.0-5.0+pattern(angle+0.78539),0.0,1.0);gl_FragColor=vec4(1.0-cmy-k,color.a);}");
f.call(this,a.colorHalftone,{center:[b,d],angle:c,scale:Math.PI/e,texSize:[this.width,this.height]});return this}function V(b,d,c,e){a.dotScreen=a.dotScreen||new h(null,"uniform sampler2D texture;uniform vec2 center;uniform float angle;uniform float scale;uniform vec2 texSize;varying vec2 texCoord;float pattern(){float s=sin(angle),c=cos(angle);vec2 tex=texCoord*texSize-center;vec2 point=vec2(c*tex.x-s*tex.y,s*tex.x+c*tex.y)*scale;return(sin(point.x)*sin(point.y))*4.0;}void main(){vec4 color=texture2D(texture,texCoord);float average=(color.r+color.g+color.b)/3.0;gl_FragColor=vec4(vec3(average*10.0-5.0+pattern()),color.a);}");
f.call(this,a.dotScreen,{center:[b,d],angle:c,scale:Math.PI/e,texSize:[this.width,this.height]});return this}function W(b){a.edgeWork1=a.edgeWork1||new h(null,"uniform sampler2D texture;uniform vec2 delta;varying vec2 texCoord;"+s+"void main(){vec2 color=vec2(0.0);vec2 total=vec2(0.0);float offset=random(vec3(12.9898,78.233,151.7182),0.0);for(float t=-30.0;t<=30.0;t++){float percent=(t+offset-0.5)/30.0;float weight=1.0-abs(percent);vec3 sample=texture2D(texture,texCoord+delta*percent).rgb;float average=(sample.r+sample.g+sample.b)/3.0;color.x+=average*weight;total.x+=weight;if(abs(t)<15.0){weight=weight*2.0-1.0;color.y+=average*weight;total.y+=weight;}}gl_FragColor=vec4(color/total,0.0,1.0);}");
a.edgeWork2=a.edgeWork2||new h(null,"uniform sampler2D texture;uniform vec2 delta;varying vec2 texCoord;"+s+"void main(){vec2 color=vec2(0.0);vec2 total=vec2(0.0);float offset=random(vec3(12.9898,78.233,151.7182),0.0);for(float t=-30.0;t<=30.0;t++){float percent=(t+offset-0.5)/30.0;float weight=1.0-abs(percent);vec2 sample=texture2D(texture,texCoord+delta*percent).xy;color.x+=sample.x*weight;total.x+=weight;if(abs(t)<15.0){weight=weight*2.0-1.0;color.y+=sample.y*weight;total.y+=weight;}}float c=clamp(10000.0*(color.y/total.y-color.x/total.x)+0.5,0.0,1.0);gl_FragColor=vec4(c,c,c,1.0);}");
f.call(this,a.edgeWork1,{delta:[b/this.width,0]});f.call(this,a.edgeWork2,{delta:[0,b/this.height]});return this}function X(b,d,c){a.hexagonalPixelate=a.hexagonalPixelate||new h(null,"uniform sampler2D texture;uniform vec2 center;uniform float scale;uniform vec2 texSize;varying vec2 texCoord;void main(){vec2 tex=(texCoord*texSize-center)/scale;tex.y/=0.866025404;tex.x-=tex.y*0.5;vec2 a;if(tex.x+tex.y-floor(tex.x)-floor(tex.y)<1.0)a=vec2(floor(tex.x),floor(tex.y));else a=vec2(ceil(tex.x),ceil(tex.y));vec2 b=vec2(ceil(tex.x),floor(tex.y));vec2 c=vec2(floor(tex.x),ceil(tex.y));vec3 TEX=vec3(tex.x,tex.y,1.0-tex.x-tex.y);vec3 A=vec3(a.x,a.y,1.0-a.x-a.y);vec3 B=vec3(b.x,b.y,1.0-b.x-b.y);vec3 C=vec3(c.x,c.y,1.0-c.x-c.y);float alen=length(TEX-A);float blen=length(TEX-B);float clen=length(TEX-C);vec2 choice;if(alen<blen){if(alen<clen)choice=a;else choice=c;}else{if(blen<clen)choice=b;else choice=c;}choice.x+=choice.y*0.5;choice.y*=0.866025404;choice*=scale/texSize;gl_FragColor=texture2D(texture,choice+center/texSize);}");
f.call(this,a.hexagonalPixelate,{center:[b,d],scale:c,texSize:[this.width,this.height]});return this}function Y(b){a.ink=a.ink||new h(null,"uniform sampler2D texture;uniform float strength;uniform vec2 texSize;varying vec2 texCoord;void main(){vec2 dx=vec2(1.0/texSize.x,0.0);vec2 dy=vec2(0.0,1.0/texSize.y);vec4 color=texture2D(texture,texCoord);float bigTotal=0.0;float smallTotal=0.0;vec3 bigAverage=vec3(0.0);vec3 smallAverage=vec3(0.0);for(float x=-2.0;x<=2.0;x+=1.0){for(float y=-2.0;y<=2.0;y+=1.0){vec3 sample=texture2D(texture,texCoord+dx*x+dy*y).rgb;bigAverage+=sample;bigTotal+=1.0;if(abs(x)+abs(y)<2.0){smallAverage+=sample;smallTotal+=1.0;}}}vec3 edge=max(vec3(0.0),bigAverage/bigTotal-smallAverage/smallTotal);gl_FragColor=vec4(color.rgb-dot(edge,edge)*strength*100000.0,color.a);}");
f.call(this,a.ink,{strength:b*b*b*b*b,texSize:[this.width,this.height]});return this}function Z(b,d,c,e){a.bulgePinch=a.bulgePinch||u("uniform float radius;uniform float strength;uniform vec2 center;","coord-=center;float distance=length(coord);if(distance<radius){float percent=distance/radius;if(strength>0.0){coord*=mix(1.0,smoothstep(0.0,radius/distance,percent),strength*0.75);}else{coord*=mix(1.0,pow(percent,1.0+strength*0.75)*radius/distance,1.0-percent);}}coord+=center;");
f.call(this,a.bulgePinch,{radius:c,strength:q(-1,e,1),center:[b,d],texSize:[this.width,this.height]});return this}function $(b,d,c){a.matrixWarp=a.matrixWarp||u("uniform mat3 matrix;uniform bool useTextureSpace;","if(useTextureSpace)coord=coord/texSize*2.0-1.0;vec3 warp=matrix*vec3(coord,1.0);coord=warp.xy/warp.z;if(useTextureSpace)coord=(coord*0.5+0.5)*texSize;");b=Array.prototype.concat.apply([],b);if(4==b.length)b=
[b[0],b[1],0,b[2],b[3],0,0,0,1];else if(9!=b.length)throw"can only warp with 2x2 or 3x3 matrix";f.call(this,a.matrixWarp,{matrix:d?y(b):b,texSize:[this.width,this.height],useTextureSpace:c|0});return this}function aa(a,d){var c=x.apply(null,d),e=x.apply(null,a),c=y(c);return this.matrixWarp([c[0]*e[0]+c[1]*e[3]+c[2]*e[6],c[0]*e[1]+c[1]*e[4]+c[2]*e[7],c[0]*e[2]+c[1]*e[5]+c[2]*e[8],c[3]*e[0]+c[4]*e[3]+c[5]*e[6],c[3]*e[1]+c[4]*e[4]+c[5]*e[7],c[3]*e[2]+c[4]*e[5]+c[5]*e[8],c[6]*e[0]+c[7]*e[3]+c[8]*e[6],
c[6]*e[1]+c[7]*e[4]+c[8]*e[7],c[6]*e[2]+c[7]*e[5]+c[8]*e[8]])}function ba(b,d,c,e){a.swirl=a.swirl||u("uniform float radius;uniform float angle;uniform vec2 center;","coord-=center;float distance=length(coord);if(distance<radius){float percent=(radius-distance)/radius;float theta=percent*percent*angle;float s=sin(theta);float c=cos(theta);coord=vec2(coord.x*c-coord.y*s,coord.x*s+coord.y*c);}coord+=center;");
f.call(this,a.swirl,{radius:c,center:[b,d],angle:e,texSize:[this.width,this.height]});return this}var v={};(function(){function a(b){if(!b.getExtension("OES_texture_float"))return!1;var c=b.createFramebuffer(),e=b.createTexture();b.bindTexture(b.TEXTURE_2D,e);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MAG_FILTER,b.NEAREST);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MIN_FILTER,b.NEAREST);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_S,b.CLAMP_TO_EDGE);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_T,b.CLAMP_TO_EDGE);
b.texImage2D(b.TEXTURE_2D,0,b.RGBA,1,1,0,b.RGBA,b.UNSIGNED_BYTE,null);b.bindFramebuffer(b.FRAMEBUFFER,c);b.framebufferTexture2D(b.FRAMEBUFFER,b.COLOR_ATTACHMENT0,b.TEXTURE_2D,e,0);c=b.createTexture();b.bindTexture(b.TEXTURE_2D,c);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MAG_FILTER,b.LINEAR);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MIN_FILTER,b.LINEAR);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_S,b.CLAMP_TO_EDGE);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_T,b.CLAMP_TO_EDGE);b.texImage2D(b.TEXTURE_2D,
0,b.RGBA,2,2,0,b.RGBA,b.FLOAT,new Float32Array([2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]));var e=b.createProgram(),d=b.createShader(b.VERTEX_SHADER),g=b.createShader(b.FRAGMENT_SHADER);b.shaderSource(d,"attribute vec2 vertex;void main(){gl_Position=vec4(vertex,0.0,1.0);}");b.shaderSource(g,"uniform sampler2D texture;void main(){gl_FragColor=texture2D(texture,vec2(0.5));}");b.compileShader(d);b.compileShader(g);b.attachShader(e,d);b.attachShader(e,
g);b.linkProgram(e);d=b.createBuffer();b.bindBuffer(b.ARRAY_BUFFER,d);b.bufferData(b.ARRAY_BUFFER,new Float32Array([0,0]),b.STREAM_DRAW);b.enableVertexAttribArray(0);b.vertexAttribPointer(0,2,b.FLOAT,!1,0,0);d=new Uint8Array(4);b.useProgram(e);b.viewport(0,0,1,1);b.bindTexture(b.TEXTURE_2D,c);b.drawArrays(b.POINTS,0,1);b.readPixels(0,0,1,1,b.RGBA,b.UNSIGNED_BYTE,d);return 127===d[0]||128===d[0]}function d(){}function c(a){"OES_texture_float_linear"===a?(void 0===this.$OES_texture_float_linear$&&Object.defineProperty(this,
"$OES_texture_float_linear$",{enumerable:!1,configurable:!1,writable:!1,value:new d}),a=this.$OES_texture_float_linear$):a=n.call(this,a);return a}function e(){var a=f.call(this);-1===a.indexOf("OES_texture_float_linear")&&a.push("OES_texture_float_linear");return a}try{var g=document.createElement("canvas").getContext("experimental-webgl")}catch(l){}if(g&&-1===g.getSupportedExtensions().indexOf("OES_texture_float_linear")&&a(g)){var n=WebGLRenderingContext.prototype.getExtension,f=WebGLRenderingContext.prototype.getSupportedExtensions;
WebGLRenderingContext.prototype.getExtension=c;WebGLRenderingContext.prototype.getSupportedExtensions=e}})();var a;v.canvas=function(){var b=document.createElement("canvas");try{a=b.getContext("experimental-webgl",{premultipliedAlpha:!1})}catch(d){a=null}if(!a)throw"This browser does not support WebGL";b._={gl:a,isInitialized:!1,texture:null,spareTexture:null,flippedShader:null};b.texture=k(A);b.draw=k(C);b.update=k(D);b.replace=k(E);b.contents=k(F);b.getPixelArray=k(G);b.brightnessContrast=k(H);
b.hexagonalPixelate=k(X);b.hueSaturation=k(K);b.colorHalftone=k(U);b.triangleBlur=k(S);b.unsharpMask=k(N);b.perspective=k(aa);b.matrixWarp=k($);b.bulgePinch=k(Z);b.tiltShift=k(R);b.dotScreen=k(V);b.edgeWork=k(W);b.lensBlur=k(Q);b.zoomBlur=k(T);b.noise=k(L);b.denoise=k(J);b.curves=k(I);b.swirl=k(ba);b.ink=k(Y);b.vignette=k(P);b.vibrance=k(O);b.sepia=k(M);return b};v.splineInterpolate=t;var h=function(){function b(b,c){var e=a.createShader(b);a.shaderSource(e,c);a.compileShader(e);if(!a.getShaderParameter(e,
a.COMPILE_STATUS))throw"compile error: "+a.getShaderInfoLog(e);return e}function d(d,l){this.texCoordAttribute=this.vertexAttribute=null;this.program=a.createProgram();d=d||c;l=l||e;l="precision highp float;"+l;a.attachShader(this.program,b(a.VERTEX_SHADER,d));a.attachShader(this.program,b(a.FRAGMENT_SHADER,l));a.linkProgram(this.program);if(!a.getProgramParameter(this.program,a.LINK_STATUS))throw"link error: "+a.getProgramInfoLog(this.program);}var c="attribute vec2 vertex;attribute vec2 _texCoord;varying vec2 texCoord;void main(){texCoord=_texCoord;gl_Position=vec4(vertex*2.0-1.0,0.0,1.0);}",
e="uniform sampler2D texture;varying vec2 texCoord;void main(){gl_FragColor=texture2D(texture,texCoord);}";d.prototype.destroy=function(){a.deleteProgram(this.program);this.program=null};d.prototype.uniforms=function(b){a.useProgram(this.program);for(var e in b)if(b.hasOwnProperty(e)){var c=a.getUniformLocation(this.program,e);if(null!==c){var d=b[e];if("[object Array]"==Object.prototype.toString.call(d))switch(d.length){case 1:a.uniform1fv(c,new Float32Array(d));break;
case 2:a.uniform2fv(c,new Float32Array(d));break;case 3:a.uniform3fv(c,new Float32Array(d));break;case 4:a.uniform4fv(c,new Float32Array(d));break;case 9:a.uniformMatrix3fv(c,!1,new Float32Array(d));break;case 16:a.uniformMatrix4fv(c,!1,new Float32Array(d));break;default:throw"dont't know how to load uniform \""+e+'" of length '+d.length;}else if("[object Number]"==Object.prototype.toString.call(d))a.uniform1f(c,d);else throw'attempted to set uniform "'+e+'" to invalid value '+(d||"undefined").toString();
}}return this};d.prototype.textures=function(b){a.useProgram(this.program);for(var c in b)b.hasOwnProperty(c)&&a.uniform1i(a.getUniformLocation(this.program,c),b[c]);return this};d.prototype.drawRect=function(b,c,e,d){var f=a.getParameter(a.VIEWPORT);c=void 0!==c?(c-f[1])/f[3]:0;b=void 0!==b?(b-f[0])/f[2]:0;e=void 0!==e?(e-f[0])/f[2]:1;d=void 0!==d?(d-f[1])/f[3]:1;null==a.vertexBuffer&&(a.vertexBuffer=a.createBuffer());a.bindBuffer(a.ARRAY_BUFFER,a.vertexBuffer);a.bufferData(a.ARRAY_BUFFER,new Float32Array([b,
c,b,d,e,c,e,d]),a.STATIC_DRAW);null==a.texCoordBuffer&&(a.texCoordBuffer=a.createBuffer(),a.bindBuffer(a.ARRAY_BUFFER,a.texCoordBuffer),a.bufferData(a.ARRAY_BUFFER,new Float32Array([0,0,0,1,1,0,1,1]),a.STATIC_DRAW));null==this.vertexAttribute&&(this.vertexAttribute=a.getAttribLocation(this.program,"vertex"),a.enableVertexAttribArray(this.vertexAttribute));null==this.texCoordAttribute&&(this.texCoordAttribute=a.getAttribLocation(this.program,"_texCoord"),a.enableVertexAttribArray(this.texCoordAttribute));
a.useProgram(this.program);a.bindBuffer(a.ARRAY_BUFFER,a.vertexBuffer);a.vertexAttribPointer(this.vertexAttribute,2,a.FLOAT,!1,0,0);a.bindBuffer(a.ARRAY_BUFFER,a.texCoordBuffer);a.vertexAttribPointer(this.texCoordAttribute,2,a.FLOAT,!1,0,0);a.drawArrays(a.TRIANGLE_STRIP,0,4)};d.getDefaultShader=function(){a.defaultShader=a.defaultShader||new d;return a.defaultShader};return d}();z.prototype.interpolate=function(a){for(var d=0,c=this.ya.length-1;1<c-d;){var e=c+d>>1;this.xa[e]>a?c=e:d=e}var e=this.xa[c]-
this.xa[d],g=(this.xa[c]-a)/e;a=(a-this.xa[d])/e;return g*this.ya[d]+a*this.ya[c]+((g*g*g-g)*this.y2[d]+(a*a*a-a)*this.y2[c])*e*e/6};var r=function(){function b(b,c,d,f){this.gl=a;this.id=a.createTexture();this.width=b;this.height=c;this.format=d;this.type=f;a.bindTexture(a.TEXTURE_2D,this.id);a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MAG_FILTER,a.LINEAR);a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MIN_FILTER,a.LINEAR);a.texParameteri(a.TEXTURE_2D,a.TEXTURE_WRAP_S,a.CLAMP_TO_EDGE);a.texParameteri(a.TEXTURE_2D,
a.TEXTURE_WRAP_T,a.CLAMP_TO_EDGE);b&&c&&a.texImage2D(a.TEXTURE_2D,0,this.format,b,c,0,this.format,this.type,null)}function d(a){null==c&&(c=document.createElement("canvas"));c.width=a.width;c.height=a.height;a=c.getContext("2d");a.clearRect(0,0,c.width,c.height);return a}b.fromElement=function(c){var d=new b(0,0,a.RGBA,a.UNSIGNED_BYTE);d.loadContentsOf(c);return d};b.prototype.loadContentsOf=function(b){this.width=b.width||b.videoWidth;this.height=b.height||b.videoHeight;a.bindTexture(a.TEXTURE_2D,
this.id);a.texImage2D(a.TEXTURE_2D,0,this.format,this.format,this.type,b)};b.prototype.initFromBytes=function(b,c,d){this.width=b;this.height=c;this.format=a.RGBA;this.type=a.UNSIGNED_BYTE;a.bindTexture(a.TEXTURE_2D,this.id);a.texImage2D(a.TEXTURE_2D,0,a.RGBA,b,c,0,a.RGBA,this.type,new Uint8Array(d))};b.prototype.destroy=function(){a.deleteTexture(this.id);this.id=null};b.prototype.use=function(b){a.activeTexture(a.TEXTURE0+(b||0));a.bindTexture(a.TEXTURE_2D,this.id)};b.prototype.unuse=function(b){a.activeTexture(a.TEXTURE0+
(b||0));a.bindTexture(a.TEXTURE_2D,null)};b.prototype.ensureFormat=function(b,c,d,f){if(1==arguments.length){var h=arguments[0];b=h.width;c=h.height;d=h.format;f=h.type}if(b!=this.width||c!=this.height||d!=this.format||f!=this.type)this.width=b,this.height=c,this.format=d,this.type=f,a.bindTexture(a.TEXTURE_2D,this.id),a.texImage2D(a.TEXTURE_2D,0,this.format,b,c,0,this.format,this.type,null)};b.prototype.drawTo=function(b){a.framebuffer=a.framebuffer||a.createFramebuffer();a.bindFramebuffer(a.FRAMEBUFFER,
a.framebuffer);a.framebufferTexture2D(a.FRAMEBUFFER,a.COLOR_ATTACHMENT0,a.TEXTURE_2D,this.id,0);if(a.checkFramebufferStatus(a.FRAMEBUFFER)!==a.FRAMEBUFFER_COMPLETE)throw Error("incomplete framebuffer");a.viewport(0,0,this.width,this.height);b();a.bindFramebuffer(a.FRAMEBUFFER,null)};var c=null;b.prototype.fillUsingCanvas=function(b){b(d(this));this.format=a.RGBA;this.type=a.UNSIGNED_BYTE;a.bindTexture(a.TEXTURE_2D,this.id);a.texImage2D(a.TEXTURE_2D,0,a.RGBA,a.RGBA,a.UNSIGNED_BYTE,c);return this};
b.prototype.toImage=function(b){this.use();h.getDefaultShader().drawRect();var f=4*this.width*this.height,k=new Uint8Array(f),n=d(this),p=n.createImageData(this.width,this.height);a.readPixels(0,0,this.width,this.height,a.RGBA,a.UNSIGNED_BYTE,k);for(var m=0;m<f;m++)p.data[m]=k[m];n.putImageData(p,0,0);b.src=c.toDataURL()};b.prototype.swapWith=function(a){var b;b=a.id;a.id=this.id;this.id=b;b=a.width;a.width=this.width;this.width=b;b=a.height;a.height=this.height;this.height=b;b=a.format;a.format=
this.format;this.format=b};return b}(),s="float random(vec3 scale,float seed){return fract(sin(dot(gl_FragCoord.xyz+seed,scale))*43758.5453+seed);}";return v}();

354
filters/dog/main.js Normal file
View File

@ -0,0 +1,354 @@
"use strict";
// some globalz:
let THREECAMERA = null;
let ISDETECTED = false;
let TONGUEMESH = null, NOSEMESH = null, EARMESH = null;
let DOGOBJ3D = null, FRAMEOBJ3D = null;
let ISOVERTHRESHOLD = false, ISUNDERTRESHOLD = true;
let ISLOADED = false;
let MIXER = null;
let ACTION = null;
let ISANIMATING = false;
let ISOPAQUE = false;
let ISTONGUEOUT = false;
let ISANIMATIONOVER = false;
let _flexParts = [];
let _videoGeometry = null;
// callback: launched if a face is detected or lost
function detect_callback(isDetected) {
if (isDetected) {
console.log('INFO in detect_callback(): DETECTED');
} else {
console.log('INFO in detect_callback(): LOST');
}
}
function create_mat2d(threeTexture, isTransparent){ // MT216: we put the creation of the video material in a func because we will also use it for the frame
return new THREE.RawShaderMaterial({
depthWrite: false,
depthTest: false,
transparent: isTransparent,
vertexShader: "attribute vec2 position;\n\
varying vec2 vUV;\n\
void main(void){\n\
gl_Position = vec4(position, 0., 1.);\n\
vUV = 0.5 + 0.5 * position;\n\
}",
fragmentShader: "precision lowp float;\n\
uniform sampler2D samplerVideo;\n\
varying vec2 vUV;\n\
void main(void){\n\
gl_FragColor = texture2D(samplerVideo, vUV);\n\
}",
uniforms:{
samplerVideo: { value: threeTexture }
}
});
}
function applyFilter() {
let canvas;
try {
canvas = fx.canvas();
} catch (e) {
alert('Ow no! WebGL isn\'t supported...')
return
}
const tempImage = new Image(512, 512);
tempImage.src = './images/texture_pink.jpg';
tempImage.onload = () => {
const texture = canvas.texture(tempImage);
// Create the effet
canvas.draw(texture).vignette(0.5, 0.6).update();
const canvasOpacity = document.createElement('canvas');
canvasOpacity.width = 512;
canvasOpacity.height = 512;
const ctx = canvasOpacity.getContext('2d');
ctx.globalAlpha = 0.2
ctx.drawImage(canvas, 0, 0, 512, 512);
// Add the effect
const calqueMesh = new THREE.Mesh(_videoGeometry, create_mat2d(new THREE.TextureLoader().load(canvasOpacity.toDataURL('image/png')), true))
calqueMesh.material.opacity = 0.2;
calqueMesh.material.transparent = true;
calqueMesh.renderOrder = 999; // render last
calqueMesh.frustumCulled = false;
FRAMEOBJ3D.add(calqueMesh);
}
}
// build the 3D. called once when Jeeliz Face Filter is OK
function init_threeScene(spec) {
// INIT THE THREE.JS context
const threeStuffs = JeelizThreeHelper.init(spec, detect_callback);
_videoGeometry = threeStuffs.videoMesh.geometry;
// CREATE OUR DOG EARS:
// let's begin by creating a loading manager that will allow us to
// have more control over the three parts of our dog model
const loadingManager = new THREE.LoadingManager();
const loaderEars = new THREE.BufferGeometryLoader(loadingManager);
loaderEars.load(
'./models/dog/dog_ears.json',
function (geometry) {
const mat = new THREE.FlexMaterial({
map: new THREE.TextureLoader().load('./models/dog/texture_ears.jpg'),
flexMap: new THREE.TextureLoader().load('./models/dog/flex_ears_256.jpg'),
alphaMap: new THREE.TextureLoader().load('./models/dog/alpha_ears_256.jpg'),
transparent: true,
opacity: 1,
bumpMap: new THREE.TextureLoader().load('./models/dog/normal_ears.jpg'),
bumpScale: 0.0075,
shininess: 1.5,
specular: 0xffffff,
});
EARMESH = new THREE.Mesh(geometry, mat);
EARMESH.scale.multiplyScalar(0.025);
EARMESH.position.setY(-0.3);
EARMESH.frustumCulled = false;
EARMESH.renderOrder = 10000;
EARMESH.material.opacity.value = 1;
}
);
// CREATE OUR DOG NOSE
const loaderNose = new THREE.BufferGeometryLoader(loadingManager);
loaderNose.load(
'./models/dog/dog_nose.json',
function (geometry) {
const mat = new THREE.MeshPhongMaterial({
map: new THREE.TextureLoader().load('./models/dog/texture_nose.jpg'),
shininess: 1.5,
specular: 0xffffff,
bumpMap: new THREE.TextureLoader().load('./models/dog/normal_nose.jpg'),
bumpScale: 0.005
});
NOSEMESH = new THREE.Mesh(geometry, mat);
NOSEMESH.scale.multiplyScalar(0.018);
NOSEMESH.position.setY(-0.05);
NOSEMESH.position.setZ(0.15);
NOSEMESH.frustumCulled = false;
NOSEMESH.renderOrder = 10000;
}
);
// CREATE OUR DOG TONGUE
const loaderTongue = new THREE.JSONLoader(loadingManager);
loaderTongue.load(
'models/dog/dog_tongue.json',
function (geometry) {
geometry.computeMorphNormals();
const mat = new THREE.FlexMaterial({
map: new THREE.TextureLoader().load('./models/dog/dog_tongue.jpg'),
flexMap: new THREE.TextureLoader().load('./models/dog/flex_tongue_256.png'),
alphaMap: new THREE.TextureLoader().load('./models/dog/tongue_alpha_256.jpg'),
transparent: true,
morphTargets: true,
opacity: 1
});
TONGUEMESH = new THREE.Mesh(geometry, mat);
TONGUEMESH.material.opacity.value = 0;
TONGUEMESH.scale.multiplyScalar(2);
TONGUEMESH.position.setY(-0.28);
TONGUEMESH.frustumCulled = false;
TONGUEMESH.visible = false;
if (!MIXER) {
// the mixer is declared globally so we can use it in the THREE renderer
MIXER = new THREE.AnimationMixer(TONGUEMESH);
const clips = TONGUEMESH.geometry.animations;
const clip = clips[0];
ACTION = MIXER.clipAction(clip);
ACTION.noLoop = true;
ACTION.play();
}
}
);
loadingManager.onLoad = () => {
DOGOBJ3D.add(EARMESH);
DOGOBJ3D.add(NOSEMESH);
DOGOBJ3D.add(TONGUEMESH);
addDragEventListener(DOGOBJ3D);
threeStuffs.faceObject.add(DOGOBJ3D);
ISLOADED = true;
}
// CREATE AN AMBIENT LIGHT
const ambient = new THREE.AmbientLight(0xffffff, 0.8);
threeStuffs.scene.add(ambient);
// CREAT A DIRECTIONALLIGHT
const dirLight = new THREE.DirectionalLight(0xffffff, 0.5);
dirLight.position.set(100, 1000, 1000);
threeStuffs.scene.add(dirLight);
// CREATE THE CAMERA
THREECAMERA = JeelizThreeHelper.create_camera();
threeStuffs.scene.add(FRAMEOBJ3D);
// Add filter
applyFilter();
} // end init_threeScene()
function animateTongue (mesh, isReverse) {
mesh.visible = true;
if (isReverse) {
ACTION.timescale = -1;
ACTION.paused = false;
setTimeout(() => {
ACTION.paused = true;
ISOPAQUE = false;
ISTONGUEOUT = false;
ISANIMATING = false;
ISANIMATIONOVER = true;
new TWEEN.Tween(mesh.material.opacity)
.to({ value: 0 }, 150)
.start();
}, 150);
} else {
ACTION.timescale = 1;
ACTION.reset();
ACTION.paused = false;
new TWEEN.Tween(mesh.material.opacity)
.to({ value: 1 }, 100)
.onComplete(() => {
ISOPAQUE = true;
setTimeout(() => {
ACTION.paused = true;
ISANIMATING = false;
ISTONGUEOUT = true;
ISANIMATIONOVER = true;
}, 150);
})
.start();
}
}
// Entry point: launched by body.onload()
function main(){
DOGOBJ3D = new THREE.Object3D();
FRAMEOBJ3D = new THREE.Object3D();
JeelizResizer.size_canvas({
canvasId: 'jeeFaceFilterCanvas',
callback: function(isError, bestVideoSettings){
init_faceFilter(bestVideoSettings);
}
});
}
function init_faceFilter(videoSettings){
JEELIZFACEFILTER.init({
canvasId: 'jeeFaceFilterCanvas',
NNCPath: '../../../neuralNets/', // root of NN_DEFAULT.json file
videoSettings: videoSettings,
callbackReady: function (errCode, spec) {
if (errCode) {
console.log('AN ERROR HAPPENS. SORRY BRO :( . ERR =', errCode);
return;
}
console.log('INFO: JEELIZFACEFILTER IS READY');
init_threeScene(spec);
}, // end callbackReady()
// called at each render iteration (drawing loop)
callbackTrack: function (detectState) {
ISDETECTED = JeelizThreeHelper.get_isDetected();
if (ISDETECTED) {
const _quat = new THREE.Quaternion();
const _eul = new THREE.Euler();
_eul.setFromQuaternion(_quat);
// flex ears material:
if (EARMESH && EARMESH.material.set_amortized){
EARMESH.material.set_amortized(
EARMESH.getWorldPosition(new THREE.Vector3(0,0,0)),
EARMESH.getWorldScale(new THREE.Vector3(0,0,0)),
EARMESH.getWorldQuaternion(_eul),
false,
0.1
);
}
if (TONGUEMESH && TONGUEMESH.material.set_amortized){
TONGUEMESH.material.set_amortized(
TONGUEMESH.getWorldPosition(new THREE.Vector3(0,0,0)),
TONGUEMESH.getWorldScale(new THREE.Vector3(0,0,0)),
TONGUEMESH.getWorldQuaternion(_eul),
false,
0.3
);
}
if (detectState.expressions[0] >= 0.85 && !ISOVERTHRESHOLD) {
ISOVERTHRESHOLD = true;
ISUNDERTRESHOLD = false;
ISANIMATIONOVER = false;
}
if (detectState.expressions[0] <= 0.1 && !ISUNDERTRESHOLD) {
ISOVERTHRESHOLD = false;
ISUNDERTRESHOLD = true;
ISANIMATIONOVER = false;
}
if (ISLOADED && ISOVERTHRESHOLD && !ISANIMATING && !ISANIMATIONOVER) {
if (!ISTONGUEOUT) {
ISANIMATING = true;
animateTongue(TONGUEMESH);
} else {
ISANIMATING = true;
animateTongue(TONGUEMESH, true);
}
}
}
TWEEN.update();
// Update the mixer on each frame:
if (ISOPAQUE) {
MIXER.update(0.16);
}
JeelizThreeHelper.render(detectState, THREECAMERA);
} // end callbackTrack()
}); // end JEELIZFACEFILTER.init call
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 378 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 367 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 196 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 195 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@ -54,7 +54,7 @@
transition: opacity .1s linear;
}
</style>
<link rel="stylesheet" href="./main.css?ver=124" />
<link rel="stylesheet" href="./main.css?ver=125" />
<script type="text/javascript" crossorigin="anonymous" src="./thirdparty/adapter.min.js"></script>
<style id="lightbox-animations" type="text/css"></style>
</head>

View File

@ -3349,7 +3349,9 @@ input:checked + .slider:before {
content: "\f00c"; }
.la-exclamation:before {
content: "\f12a"; }
.la-chevron-down:before {
content: "\f078"; }
@media (prefers-color-scheme: dark) {
:root {
--color-mode: dark;

73
media/camera_inkscape.svg Normal file
View File

@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="91.859253mm"
height="49.479435mm"
viewBox="0 0 91.859252 49.479436"
version="1.1"
id="svg4530"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
sodipodi:docname="camera_inkscape.svg">
<defs
id="defs4524" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1.3235466"
inkscape:cx="338.91574"
inkscape:cy="131.01428"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:snap-text-baseline="false"
inkscape:snap-bbox="false"
inkscape:snap-global="true"
inkscape:window-width="2560"
inkscape:window-height="1361"
inkscape:window-x="2391"
inkscape:window-y="-9"
inkscape:window-maximized="1" />
<metadata
id="metadata4527">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-4.0990803,-66.079714)">
<rect
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:6.29999971;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:22.7149601;stroke-opacity:1;paint-order:markers fill stroke"
id="rect5164"
width="65.568779"
height="43.179436"
x="7.2490802"
y="69.229713" />
<path
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:6.30000019;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 73.017762,94.91748 19.790574,15.89243 V 73.227808 L 73.117714,88.420574 Z"
id="path5172"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

88
media/grid_inkscape.svg Normal file
View File

@ -0,0 +1,88 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="90.680443mm"
height="86.222237mm"
viewBox="0 0 90.680443 86.222237"
version="1.1"
id="svg4530"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
sodipodi:docname="grid_inkscape.svg">
<defs
id="defs4524" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.9358888"
inkscape:cx="-118.37523"
inkscape:cy="171.46325"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:snap-text-baseline="false"
inkscape:snap-bbox="false"
inkscape:snap-global="true"
inkscape:window-width="1558"
inkscape:window-height="815"
inkscape:window-x="3042"
inkscape:window-y="342"
inkscape:window-maximized="0" />
<metadata
id="metadata4527">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-7.8547072,-50.964769)">
<rect
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:6.30000019;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:22.7149601;stroke-opacity:1"
id="rect5084"
width="37.378147"
height="35.23999"
x="11.004707"
y="54.115173" />
<rect
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:6.30000019;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:22.7149601;stroke-opacity:1"
id="rect5084-7"
width="37.378147"
height="35.23999"
x="58.006535"
y="54.114769" />
<rect
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:6.30000019;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:22.7149601;stroke-opacity:1"
id="rect5084-5"
width="37.378147"
height="35.23999"
x="11.005169"
y="98.797012" />
<rect
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:6.30000019;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:22.7149601;stroke-opacity:1"
id="rect5084-7-8"
width="37.378147"
height="35.23999"
x="58.007"
y="98.797005" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@ -0,0 +1,79 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="91.960541mm"
height="73.765312mm"
viewBox="0 0 91.960541 73.765313"
version="1.1"
id="svg4530"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
sodipodi:docname="monitor_inkscape.svg">
<defs
id="defs4524" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.66177331"
inkscape:cx="-137.92249"
inkscape:cy="195.10498"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:snap-text-baseline="false"
inkscape:snap-bbox="false"
inkscape:snap-global="true"
inkscape:window-width="2560"
inkscape:window-height="1361"
inkscape:window-x="2391"
inkscape:window-y="-9"
inkscape:window-maximized="1" />
<metadata
id="metadata4527">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-7.2490804,-50.638126)">
<rect
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:6.03970385;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:22.7149601;stroke-opacity:1"
id="rect5137"
width="85.920837"
height="54.398895"
x="10.268932"
y="53.657978" />
<path
style="fill:none;stroke:#000000;stroke-width:6.30000019;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers fill stroke"
d="m 42.85551,121.16499 c 9.824106,0.14136 21.8392,0.0707 21.8392,0.0707"
id="path5160"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#000000;stroke-width:6.30000019;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers fill stroke"
d="m 53.653201,124.1546 0.141785,-15.59616"
id="path5162"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

69
media/plane_inkscape.svg Normal file
View File

@ -0,0 +1,69 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="80.325882mm"
height="72.74617mm"
viewBox="0 0 80.325882 72.74617"
version="1.1"
id="svg8"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
sodipodi:docname="plane_inkscape.svg">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1.979899"
inkscape:cx="33.822827"
inkscape:cy="116.43405"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="2560"
inkscape:window-height="1361"
inkscape:window-x="2391"
inkscape:window-y="-9"
inkscape:window-maximized="1" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-42.368449,-95.595815)">
<path
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:6.01000023;stroke-opacity:1"
d="M 44.368022,146.86603 120.69438,97.595614 112.66457,160.95467 75.571391,148.5403 Z"
id="path3713"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
<path
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:6.01000023;stroke-opacity:1"
d="M 75.414599,166.34241 75.571391,148.5403 120.69438,97.595614 75.571391,148.5403 l 10.314217,3.3896 z"
id="path3715"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 299 KiB

View File

@ -218,9 +218,9 @@ ol {
margin:auto;
}
}
}
#statsdiv {display: none;}
#statsdiv {display: none;}

View File

@ -164,7 +164,8 @@
"the-camera-will-load-in-a-default-safe-mode-that-may-work-if-other-modes-fail-": "The camera will load in a default safe-mode that may work if other modes fail.",
"disable-animated-transitions-during-video-mixing": "Disable animated transitions during video mixing",
"allow-the-guest-to-select-a-file-to-upload-to-the-director-once-shared-it-will-show-in-the-chat-as-a-download-link-": "Allow the guest to select a file to upload to the director. Once shared, it will show in the chat as a download link.",
"set-a-countdown-timer-that-this-guest-sees": "Set a countdown timer that this guest sees"
"set-a-countdown-timer-that-this-guest-sees": "Set a countdown timer that this guest sees",
"enter-a-room-name-to-quick-join": "Enter a room name to quick join"
},
"innerHTML": {
"logo-header": "<font id=\"qos\" style=\"color: white;\">O</font>BS.Ninja ",
@ -354,7 +355,9 @@
"mirror-video": "Mirror",
"toggle-control-video": "Toggle control bar",
"picture-in-picture": "Picture-in-picture",
"chrome-cast": "Cast.."
"chrome-cast": "Cast..",
"join-room": "Join room",
"waiting-for-mic-to-load": "Waiting for mic to load"
},
"placeholders": {
"join-by-room-name-here": "Připojit se s názvem místnosti zde",

View File

@ -164,7 +164,8 @@
"the-camera-will-load-in-a-default-safe-mode-that-may-work-if-other-modes-fail-": "The camera will load in a default safe-mode that may work if other modes fail.",
"disable-animated-transitions-during-video-mixing": "Disable animated transitions during video mixing",
"allow-the-guest-to-select-a-file-to-upload-to-the-director-once-shared-it-will-show-in-the-chat-as-a-download-link-": "Allow the guest to select a file to upload to the director. Once shared, it will show in the chat as a download link.",
"set-a-countdown-timer-that-this-guest-sees": "Set a countdown timer that this guest sees"
"set-a-countdown-timer-that-this-guest-sees": "Set a countdown timer that this guest sees",
"enter-a-room-name-to-quick-join": "Enter a room name to quick join"
},
"innerHTML": {
"logo-header": "<font id=\"qos\" style=\"color: white;\">O</font>BS Ninja",
@ -354,7 +355,9 @@
"mirror-video": "Mirror",
"toggle-control-video": "Toggle control bar",
"picture-in-picture": "Picture-in-picture",
"chrome-cast": "Cast.."
"chrome-cast": "Cast..",
"join-room": "Join room",
"waiting-for-mic-to-load": "Waiting for mic to load"
},
"placeholders": {
"join-by-room-name-here": "Raum über Namen betreten",

50
translations/default.json Normal file
View File

@ -0,0 +1,50 @@
{
"logo-header": "<font id=\"qos\" style=\"color: white;\">O</font>BS.Ninja ",
"GO": "GO",
"copy-this-url": "Copy this URL into an OBS \"Browser Source\"",
"you-are-in-the-control-center": "You are in the room's control center",
"joining-room": "You are joining room",
"add-group-chat": "Add Group Chat to OBS",
"rooms-allow-for": "Rooms allow for simplified group-chat and the advanced management of multiple streams at once.",
"room-name": "Room Name",
"enter-the-rooms-control": "Enter the Room's Control Center",
"show-tips": "Show me some tips..",
"added-notes": "\n<u><i>Added Notes:</i></u>\n<li>Anyone can enter a room if they know the name, so keep it unique</li>\n<li>Invite only guests to the room you trust.</li>\n<li>iOS devices will share just their audio with other guests; this is mainly a hardware limitation</li>\n<li>The \"Recording\" option is considered experimental.</li>\n",
"back": "Back",
"add-your-camera": "Add your Camera to OBS",
"waiting-for-camera": "Waiting for Camera to Load",
"video-source": "Video source",
"max-resolution": "1080p (hi-def)",
"balanced": "720p (balanced)",
"smooth-cool": "360p (smooth)",
"select-audio-source": "Select Audio Source",
"no-audio": "No Audio",
"remote-screenshare-obs": "Remote Screenshare into OBS",
"note-share-audio": "\n<b>note</b>: Do not forget to click \"Share audio\" in Chrome.<br>(Firefox does not support audio sharing.)",
"select-screen-to-share": "SELECT SCREEN TO SHARE",
"audio-sources": "Audio Sources",
"create-reusable-invite": "Create Reusable Invite",
"here-you-can-pre-generate": "Here you can pre-generate a reusable Browser Source link and a related guest invite link.",
"generate-invite-link": "GENERATE THE INVITE LINK",
"advanced-paramaters": "Advanced Options:",
"unlock-video-bitrate": "Unlock Video Bitrate (20mbps)",
"force-vp9-video-codec": "Force VP9 Video Codec (less artifacting)",
"enable-stereo-and-pro": "Enable Stereo and Pro HD Audio",
"video-resolution": "Video Resolution: ",
"high-security-mode": "High Security Mode",
"hide-screen-share": "Hide Screenshare Option",
"allow-remote-control": "Remote Control Camera Zoom (android)",
"add-the-guest-to-a-room": " Add the guest to a room:",
"invite-group-chat-type": "This room guest can:",
"can-see-and-hear": "Can see and hear the group chat",
"can-hear-only": "Can only hear the group chat",
"cant-see-or-hear": "Cannot hear or see the group chat",
"info-blob": "\n<h2>What is OBS.Ninja</h2><br>\n<li>100% <b>free</b>; no downloads; no personal data collection; no sign-in</li>\n<li>Bring video from your smartphone, computer, or friends directly into your OBS video stream</li>\n<li>We use cutting edge Peer-to-Peer forwarding technology that offers privacy and ultra-low latency</li>\n<br>\n<li>Youtube video <i class=\"fa fa-youtube-play\" aria-hidden=\"true\"></i> <a href=\"https://www.youtube.com/watch?v=6R_sQKxFAhg\">Demoing it here</a> </li>\n<br>\n<i><font style=\"color:red\">Known issues:</font></i><br>\n<li><i class=\"fa fa-apple\" aria-hidden=\"true\"></i> <a href=\"https://github.com/steveseguin/obsninja/wiki/FAQ#mac-os\">MacOS users</a> need to use OBS v23 or resort to <a href=\"https://github.com/steveseguin/electroncapture\">Window Capturing</a> a browser with OBS v25</li>\n<li>Some users will have <a href=\"https://github.com/steveseguin/obsninja/wiki/FAQ#video-is-pixelated\">\"pixelation\" problems</a> with videos. Adding <b>&amp;codec=vp9</b> to the OBS links will often correct it.</li>\n<br>\n",
"remote-control-for-obs": "Remote Control for OBS",
"add-to-group": "Add to Group Scene",
"mute": "Mute",
"record": "Record",
"volume": "Volume",
"open-in-new-tab": "Open in new Tab",
"copy-to-clipboard": "Copy to Clipboard"
}

View File

@ -150,7 +150,8 @@
"the-camera-will-load-in-a-default-safe-mode-that-may-work-if-other-modes-fail-": "The camera will load in a default safe-mode that may work if other modes fail.",
"disable-animated-transitions-during-video-mixing": "Disable animated transitions during video mixing",
"allow-the-guest-to-select-a-file-to-upload-to-the-director-once-shared-it-will-show-in-the-chat-as-a-download-link-": "Allow the guest to select a file to upload to the director. Once shared, it will show in the chat as a download link.",
"set-a-countdown-timer-that-this-guest-sees": "Set a countdown timer that this guest sees"
"set-a-countdown-timer-that-this-guest-sees": "Set a countdown timer that this guest sees",
"enter-a-room-name-to-quick-join": "Enter a room name to quick join"
},
"innerHTML": {
"copy-this-url": "Copia esta URL como fuente \"Navegador\" de OBS",
@ -327,7 +328,17 @@
"mirror-video": "Mirror",
"toggle-control-video": "Toggle control bar",
"picture-in-picture": "Picture-in-picture",
"chrome-cast": "Cast.."
"chrome-cast": "Cast..",
"join-room": "Join room",
"join-room-with-mic": "Join room with Microphone",
"join-room-with-camera": "Join Room with Camera",
"share-screen-with-room": "Screenshare with Room",
"share-your-mic": "Share your Microphone",
"share-your-camera": "Share your Camera",
"share-your-screen": "Share your Screen",
"click-start-to-join": "Click Start to Join",
"waiting-for-mic-to-load": "Waiting for mic to load",
"waiting-for-camera-to-load": "Waiting for Camera to load"
},
"placeholders": {
"join-by-room-name-here": "Unirse por Nombre de Sala aquí",

View File

@ -164,7 +164,8 @@
"the-camera-will-load-in-a-default-safe-mode-that-may-work-if-other-modes-fail-": "The camera will load in a default safe-mode that may work if other modes fail.",
"disable-animated-transitions-during-video-mixing": "Disable animated transitions during video mixing",
"allow-the-guest-to-select-a-file-to-upload-to-the-director-once-shared-it-will-show-in-the-chat-as-a-download-link-": "Allow the guest to select a file to upload to the director. Once shared, it will show in the chat as a download link.",
"set-a-countdown-timer-that-this-guest-sees": "Set a countdown timer that this guest sees"
"set-a-countdown-timer-that-this-guest-sees": "Set a countdown timer that this guest sees",
"enter-a-room-name-to-quick-join": "Enter a room name to quick join"
},
"innerHTML": {
"logo-header": "<font id=\"qos\" style=\"color: white;\">O</font>BS.Ninja ",
@ -354,7 +355,9 @@
"mirror-video": "Mirror",
"toggle-control-video": "Toggle control bar",
"picture-in-picture": "Picture-in-picture",
"chrome-cast": "Cast.."
"chrome-cast": "Cast..",
"join-room": "Join room",
"waiting-for-mic-to-load": "Waiting for mic to load"
},
"placeholders": {
"join-by-room-name-here": "Rejoindre via le nom de salle ici",

View File

@ -164,7 +164,8 @@
"the-camera-will-load-in-a-default-safe-mode-that-may-work-if-other-modes-fail-": "The camera will load in a default safe-mode that may work if other modes fail.",
"disable-animated-transitions-during-video-mixing": "Disable animated transitions during video mixing",
"allow-the-guest-to-select-a-file-to-upload-to-the-director-once-shared-it-will-show-in-the-chat-as-a-download-link-": "Allow the guest to select a file to upload to the director. Once shared, it will show in the chat as a download link.",
"set-a-countdown-timer-that-this-guest-sees": "Set a countdown timer that this guest sees"
"set-a-countdown-timer-that-this-guest-sees": "Set a countdown timer that this guest sees",
"enter-a-room-name-to-quick-join": "Enter a room name to quick join"
},
"innerHTML": {
"logo-header": "<font id=\"qos\" style=\"color: white;\">O</font>BS.Ninja ",
@ -354,7 +355,9 @@
"mirror-video": "Mirror",
"toggle-control-video": "Toggle control bar",
"picture-in-picture": "Picture-in-picture",
"chrome-cast": "Cast.."
"chrome-cast": "Cast..",
"join-room": "Join room",
"waiting-for-mic-to-load": "Waiting for mic to load"
},
"placeholders": {
"join-by-room-name-here": "Join by Room Name here",

View File

@ -164,7 +164,8 @@
"the-camera-will-load-in-a-default-safe-mode-that-may-work-if-other-modes-fail-": "The camera will load in a default safe-mode that may work if other modes fail.",
"disable-animated-transitions-during-video-mixing": "Disable animated transitions during video mixing",
"allow-the-guest-to-select-a-file-to-upload-to-the-director-once-shared-it-will-show-in-the-chat-as-a-download-link-": "Allow the guest to select a file to upload to the director. Once shared, it will show in the chat as a download link.",
"set-a-countdown-timer-that-this-guest-sees": "Set a countdown timer that this guest sees"
"set-a-countdown-timer-that-this-guest-sees": "Set a countdown timer that this guest sees",
"enter-a-room-name-to-quick-join": "Enter a room name to quick join"
},
"innerHTML": {
"logo-header": "<font id=\"qos\" style=\"color: white;\">O</font>BS.Ninja ",
@ -354,7 +355,9 @@
"mirror-video": "Mirror",
"toggle-control-video": "Toggle control bar",
"picture-in-picture": "Picture-in-picture",
"chrome-cast": "Cast.."
"chrome-cast": "Cast..",
"join-room": "Join room",
"waiting-for-mic-to-load": "Waiting for mic to load"
},
"placeholders": {
"join-by-room-name-here": "Join by Room Name here",

View File

@ -164,7 +164,8 @@
"the-camera-will-load-in-a-default-safe-mode-that-may-work-if-other-modes-fail-": "The camera will load in a default safe-mode that may work if other modes fail.",
"disable-animated-transitions-during-video-mixing": "Disable animated transitions during video mixing",
"allow-the-guest-to-select-a-file-to-upload-to-the-director-once-shared-it-will-show-in-the-chat-as-a-download-link-": "Allow the guest to select a file to upload to the director. Once shared, it will show in the chat as a download link.",
"set-a-countdown-timer-that-this-guest-sees": "Set a countdown timer that this guest sees"
"set-a-countdown-timer-that-this-guest-sees": "Set a countdown timer that this guest sees",
"enter-a-room-name-to-quick-join": "Enter a room name to quick join"
},
"innerHTML": {
"logo-header": "<font id=\"qos\" style=\"color: white;\">O</font>BS Ninja",
@ -354,7 +355,9 @@
"mirror-video": "Mirror",
"toggle-control-video": "Toggle control bar",
"picture-in-picture": "Picture-in-picture",
"chrome-cast": "Cast.."
"chrome-cast": "Cast..",
"join-room": "Join room",
"waiting-for-mic-to-load": "Waiting for mic to load"
},
"placeholders": {
"join-by-room-name-here": "Ga binnen met een kamer naam",

View File

@ -164,7 +164,8 @@
"the-camera-will-load-in-a-default-safe-mode-that-may-work-if-other-modes-fail-": "The camera will load in a default safe-mode that may work if other modes fail.",
"disable-animated-transitions-during-video-mixing": "Disable animated transitions during video mixing",
"allow-the-guest-to-select-a-file-to-upload-to-the-director-once-shared-it-will-show-in-the-chat-as-a-download-link-": "Allow the guest to select a file to upload to the director. Once shared, it will show in the chat as a download link.",
"set-a-countdown-timer-that-this-guest-sees": "Set a countdown timer that this guest sees"
"set-a-countdown-timer-that-this-guest-sees": "Set a countdown timer that this guest sees",
"enter-a-room-name-to-quick-join": "Enter a room name to quick join"
},
"innerHTML": {
"logo-header": "<font id=\"qos\" style=\"color: white;\">O</font>BS Ninja - Pig Latin",
@ -354,7 +355,9 @@
"mirror-video": "Mirror",
"toggle-control-video": "Toggle control bar",
"picture-in-picture": "Picture-in-picture",
"chrome-cast": "Cast.."
"chrome-cast": "Cast..",
"join-room": "Join room",
"waiting-for-mic-to-load": "Waiting for mic to load"
},
"placeholders": {
"join-by-room-name-here": "Erehay ouyay ancay epray-enerategay",

View File

@ -164,7 +164,8 @@
"the-camera-will-load-in-a-default-safe-mode-that-may-work-if-other-modes-fail-": "The camera will load in a default safe-mode that may work if other modes fail.",
"disable-animated-transitions-during-video-mixing": "Disable animated transitions during video mixing",
"allow-the-guest-to-select-a-file-to-upload-to-the-director-once-shared-it-will-show-in-the-chat-as-a-download-link-": "Allow the guest to select a file to upload to the director. Once shared, it will show in the chat as a download link.",
"set-a-countdown-timer-that-this-guest-sees": "Set a countdown timer that this guest sees"
"set-a-countdown-timer-that-this-guest-sees": "Set a countdown timer that this guest sees",
"enter-a-room-name-to-quick-join": "Enter a room name to quick join"
},
"innerHTML": {
"logo-header": "<font id=\"qos\" style=\"color: white;\">O</font>BS.Ninja ",
@ -354,7 +355,9 @@
"mirror-video": "Mirror",
"toggle-control-video": "Toggle control bar",
"picture-in-picture": "Picture-in-picture",
"chrome-cast": "Cast.."
"chrome-cast": "Cast..",
"join-room": "Join room",
"waiting-for-mic-to-load": "Waiting for mic to load"
},
"placeholders": {
"join-by-room-name-here": "Introduza aqui numa sala pelo seu nome",

View File

@ -164,7 +164,8 @@
"the-camera-will-load-in-a-default-safe-mode-that-may-work-if-other-modes-fail-": "The camera will load in a default safe-mode that may work if other modes fail.",
"disable-animated-transitions-during-video-mixing": "Disable animated transitions during video mixing",
"allow-the-guest-to-select-a-file-to-upload-to-the-director-once-shared-it-will-show-in-the-chat-as-a-download-link-": "Allow the guest to select a file to upload to the director. Once shared, it will show in the chat as a download link.",
"set-a-countdown-timer-that-this-guest-sees": "Set a countdown timer that this guest sees"
"set-a-countdown-timer-that-this-guest-sees": "Set a countdown timer that this guest sees",
"enter-a-room-name-to-quick-join": "Enter a room name to quick join"
},
"innerHTML": {
"logo-header": "<font id=\"qos\" style=\"color: white;\">O</font>BS.Ninja (RU)",
@ -354,7 +355,9 @@
"mirror-video": "Mirror",
"toggle-control-video": "Toggle control bar",
"picture-in-picture": "Picture-in-picture",
"chrome-cast": "Cast.."
"chrome-cast": "Cast..",
"join-room": "Join room",
"waiting-for-mic-to-load": "Waiting for mic to load"
},
"placeholders": {
"join-by-room-name-here": "Join by Room Name here",

View File

@ -164,7 +164,8 @@
"the-camera-will-load-in-a-default-safe-mode-that-may-work-if-other-modes-fail-": "The camera will load in a default safe-mode that may work if other modes fail.",
"disable-animated-transitions-during-video-mixing": "Disable animated transitions during video mixing",
"allow-the-guest-to-select-a-file-to-upload-to-the-director-once-shared-it-will-show-in-the-chat-as-a-download-link-": "Allow the guest to select a file to upload to the director. Once shared, it will show in the chat as a download link.",
"set-a-countdown-timer-that-this-guest-sees": "Set a countdown timer that this guest sees"
"set-a-countdown-timer-that-this-guest-sees": "Set a countdown timer that this guest sees",
"enter-a-room-name-to-quick-join": "Enter a room name to quick join"
},
"innerHTML": {
"logo-header": "<font id=\"qos\" style=\"color: white;\">O</font>BS.Ninja ",
@ -354,7 +355,9 @@
"mirror-video": "Mirror",
"toggle-control-video": "Toggle control bar",
"picture-in-picture": "Picture-in-picture",
"chrome-cast": "Cast.."
"chrome-cast": "Cast..",
"join-room": "Join room",
"waiting-for-mic-to-load": "Waiting for mic to load"
},
"placeholders": {
"join-by-room-name-here": "Join by Room Name here",

View File

@ -69,10 +69,11 @@ function updateTranslation(filename) { // updates the website with a specific tr
}
const updateList = [
"blank", // must be first
"en",
"cs",
"cn",
"de",
"en",
"cn",
"es",
"fr",
"it",
@ -82,8 +83,7 @@ const updateList = [
"pt",
"ru",
"tr",
"uk",
"blank"
"uk"
]; // list of languages to update. Update this if you add a new language.
const allItems = document.querySelectorAll('[data-translate]');
@ -129,6 +129,21 @@ for (const i in updateList) {
const key = ele.dataset.translate;//.replace(/[\W]+/g, "-").toLowerCase();
newTrans[key] = ele.innerHTML;
});
if (lang == "blank" || lang == "en"){
console.log(newTrans);
for (var key in newTrans) {
if (!(key in defaultTrans)){
defaultTrans[key] = newTrans[key];
}
}
} else {
for (var key in defaultTrans){
if (!(key in newTrans)){
newTrans[key] = defaultTrans[key]
}
}
}
const newTransTitles = suceess[1].titles;
//const allTitles = document.querySelectorAll('[title]');
@ -136,6 +151,19 @@ for (const i in updateList) {
const key = ele.dataset.key;
newTransTitles[key] = ele.title;
});
if (lang == "blank" || lang == "en"){
for (var key in newTransTitles) {
if (!(key in defaultTransTitles)){
defaultTransTitles[key] = newTransTitles[key];
}
}
} else {
for (var key in defaultTransTitles){
if (!(key in newTransTitles)){
newTransTitles[key] = defaultTransTitles[key]
}
}
}
const newPlaceholders = suceess[1].placeholders;
// const allPlaceholders = document.querySelectorAll('[placeholder]');
@ -143,6 +171,19 @@ for (const i in updateList) {
const key = ele.dataset.key;
newPlaceholders[key] = ele.placeholder;
});
if (lang == "blank" || lang == "en"){
for (var key in newPlaceholders) {
if (!(key in defaultTransPlaceholders)){
defaultTransPlaceholders[key] = newPlaceholders[key];
}
}
} else {
for (var key in defaultTransPlaceholders){
if (!(key in newPlaceholders)){
newPlaceholders[key] = defaultTransPlaceholders[key]
}
}
}
var miscellaneous = {};
if ("miscellaneous" in suceess[1]){

View File

@ -156,7 +156,8 @@
"the-camera-will-load-in-a-default-safe-mode-that-may-work-if-other-modes-fail-": "The camera will load in a default safe-mode that may work if other modes fail.",
"disable-animated-transitions-during-video-mixing": "Disable animated transitions during video mixing",
"allow-the-guest-to-select-a-file-to-upload-to-the-director-once-shared-it-will-show-in-the-chat-as-a-download-link-": "Allow the guest to select a file to upload to the director. Once shared, it will show in the chat as a download link.",
"set-a-countdown-timer-that-this-guest-sees": "Set a countdown timer that this guest sees"
"set-a-countdown-timer-that-this-guest-sees": "Set a countdown timer that this guest sees",
"enter-a-room-name-to-quick-join": "Enter a room name to quick join"
},
"innerHTML": {
"logo-header": "\n\t\t\t\t\t<font id=\"qos\">O</font>BS.Ninja \n\t\t\t\t",
@ -335,7 +336,17 @@
"mirror-video": "Mirror",
"toggle-control-video": "Toggle control bar",
"picture-in-picture": "Picture-in-picture",
"chrome-cast": "Cast.."
"chrome-cast": "Cast..",
"join-room": "Join room",
"join-room-with-mic": "Join room with Microphone",
"join-room-with-camera": "Join Room with Camera",
"share-screen-with-room": "Screenshare with Room",
"share-your-mic": "Share your Microphone",
"share-your-camera": "Share your Camera",
"share-your-screen": "Share your Screen",
"click-start-to-join": "Click Start to Join",
"waiting-for-mic-to-load": "Waiting for mic to load",
"waiting-for-camera-to-load": "Waiting for Camera to load"
},
"placeholders": {
"join-by-room-name-here": "приєднано до кімнати тут ",