diff --git a/app/assets/images/Logo-Emergence.png b/app/assets/images/Logo-Emergence.png new file mode 100644 index 0000000..32484e0 Binary files /dev/null and b/app/assets/images/Logo-Emergence.png differ diff --git a/app/assets/images/logop42-intro_three-tokick.png b/app/assets/images/logop42-intro_three-tokick.png new file mode 100644 index 0000000..d6f9514 Binary files /dev/null and b/app/assets/images/logop42-intro_three-tokick.png differ diff --git a/app/assets/sfx/intro.js b/app/assets/sfx/intro.js index dcd3910..f4e88a5 100644 --- a/app/assets/sfx/intro.js +++ b/app/assets/sfx/intro.js @@ -11,6 +11,14 @@ class Intro{ constructor(){ this.canvas = document.querySelector('.intro3d') + + // Order : + // 1. Launch loading promises + // 2. When they are all completed, initScene + // 2.1 at the end of initScen, we add the class 'ready' to the canvas, which launches the CSS animation + // 3. When that CS animation is finished, we can launch the 3D animation (rendering already started to have textures) + this.canvas.addEventListener('animationend', this.launch3DAnim.bind(this)) + const loadHDR = () => new Promise((resolve, reject) => { new RGBELoader() @@ -18,14 +26,22 @@ class Intro{ .load('kloofendal_48d_partly_cloudy_puresky_2k.hdr', resolve, this.hdrProgress, reject) }) - const loadTexture = () => + const loadTexture1 = () => new Promise((resolve, reject) => { new THREE.TextureLoader() .setPath('/app/assets/images/') .load('logop42-intro_three.png', resolve, undefined, reject) }) - Promise.allSettled([loadHDR(), loadTexture()]).then(this.initScene.bind(this)) + const loadTexture2 = () => + new Promise((resolve, reject) => { + new THREE.TextureLoader() + .setPath('/app/assets/images/') + .load('Logo-Emergence.png', resolve, undefined, reject) + }) + + + Promise.allSettled([loadHDR(), loadTexture1(), loadTexture2()]).then(this.initScene.bind(this)) this.Xcorrection = -0.02 } @@ -38,17 +54,19 @@ class Intro{ } } - initScene(LoadersResults){ + initScene(LoadersResults){ console.log('initScene') let hdrTexture - const [hdrResult, texResult] = LoadersResults - if (hdrResult.status === 'fulfilled' && texResult.status === 'fulfilled') { + const [hdrResult, texResultP42, texResultEE] = LoadersResults + if((hdrResult.status === 'fulfilled') && (texResultP42.status === 'fulfilled') && (texResultEE.status === 'fulfilled')) { hdrTexture = hdrResult.value - this.backgroundTexture = texResult.value + this.backgroundTextureP42 = texResultP42.value + this.backgroundTextureEE = texResultEE.value hdrTexture.mapping = THREE.EquirectangularReflectionMapping - this.backgroundTexture.colorSpace = THREE.SRGBColorSpace + this.backgroundTextureP42.colorSpace = THREE.SRGBColorSpace + this.backgroundTextureEE.colorSpace = THREE.SRGBColorSpace } else { - console.error('Loading error:', hdrResult, texResult) + console.error('Loading error:', hdrResult, texResultP42, texResultEE) return } @@ -71,14 +89,22 @@ class Intro{ this.renderer.setClearColor(0x000000, 0) this.renderer.outputColorSpace = THREE.SRGBColorSpace - this.backgroundTexture.colorSpace = THREE.SRGBColorSpace - this.backgroundTexture.wrapS = THREE.ClampToEdgeWrapping - this.backgroundTexture.wrapT = THREE.ClampToEdgeWrapping - this.backgroundTexture.generateMipmaps = false - this.backgroundTexture.minFilter = THREE.LinearFilter - this.backgroundTexture.magFilter = THREE.LinearFilter - this.imageAspect = this.backgroundTexture.image.width / this.backgroundTexture.image.height - + this.backgroundTextureP42.colorSpace = THREE.SRGBColorSpace + this.backgroundTextureP42.wrapS = THREE.ClampToEdgeWrapping + this.backgroundTextureP42.wrapT = THREE.ClampToEdgeWrapping + this.backgroundTextureP42.generateMipmaps = false + this.backgroundTextureP42.minFilter = THREE.LinearFilter + this.backgroundTextureP42.magFilter = THREE.LinearFilter + this.aspectRatioP42 = this.backgroundTextureP42.image.width / this.backgroundTextureP42.image.height + + this.backgroundTextureEE.colorSpace = THREE.SRGBColorSpace + this.backgroundTextureEE.wrapS = THREE.ClampToEdgeWrapping + this.backgroundTextureEE.wrapT = THREE.ClampToEdgeWrapping + this.backgroundTextureEE.generateMipmaps = false + this.backgroundTextureEE.minFilter = THREE.LinearFilter + this.backgroundTextureEE.magFilter = THREE.LinearFilter + this.aspectRatioEE = this.backgroundTextureEE.image.width / this.backgroundTextureEE.image.height + this.makeOrResizePlane() this.#onResizeCallbacks.push(this.makeOrResizePlane.bind(this)) @@ -117,7 +143,10 @@ class Intro{ envMapIntensity: 1.5, attenuationColor: new THREE.Color(0x88ffcc), attenuationDistance: 2, - color: 0x88ffcc, + color: 0x88ffcc, + depthWrite: false, + depthTest: true, + transparent: true, }) for (let i = 0; i < text.length; i++) { @@ -130,7 +159,8 @@ class Intro{ bevelEnabled: true, bevelThickness: 0.03, bevelSize: 0.03, - bevelSegments: 32 + bevelSegments: 32, + renderOrder: 10, }) geo.center() @@ -151,8 +181,13 @@ class Intro{ this.#onResizeCallbacks.forEach(fn => fn()) }) + this.renderer.render(this.scene, this.camera) this.canvas.classList.add('ready') - this.nextAnim = Date.now()+2000 + + } + + launch3DAnim(){ console.log('CSs finished, launching 3D anim') + this.nextAnim = Date.now() this.animate() } @@ -163,32 +198,76 @@ class Intro{ const viewWidth = viewHeight * this.camera.aspect let planeWidth, planeHeight - if (viewWidth / viewHeight > this.imageAspect) { + if (viewWidth / viewHeight > this.aspectRatioP42) { planeHeight = viewHeight - planeWidth = planeHeight * this.imageAspect + planeWidth = planeHeight * this.aspectRatioP42 } else { planeWidth = viewWidth - planeHeight = planeWidth / this.imageAspect - } - - if (!this.plane) { + planeHeight = planeWidth / this.aspectRatioP42 + } + if (!this.planeP42) { const geo = new THREE.PlaneGeometry(planeWidth, planeHeight) - const mat = new THREE.MeshBasicMaterial({ map: this.backgroundTexture }) - this.plane = new THREE.Mesh(geo, mat) - this.plane.scale.set(1.44, 1.5, 1) - this.plane.position.x = this.Xcorrection - this.plane.position.z = 0 - this.plane.renderOrder = 0 - this.scene.add(this.plane) + const mat = new THREE.MeshBasicMaterial({ map: this.backgroundTextureP42, transparent: false, depthWrite:true, depthTest:true }) + this.planeP42 = new THREE.Mesh(geo, mat) + this.planeP42.scale.set(1.44, 1.5, 1) + this.planeP42.position.x = this.Xcorrection + this.planeP42.position.z = 0 + this.planeP42.renderOrder = 0 + this.scene.add(this.planeP42) } else { - this.plane.geometry.dispose() - this.plane.geometry = new THREE.PlaneGeometry(planeWidth, planeHeight) + this.planeP42.geometry.dispose() + this.planeP42.geometry = new THREE.PlaneGeometry(planeWidth, planeHeight) } + + if (viewWidth / viewHeight > this.aspectRatioEE) { + planeHeight = viewHeight + planeWidth = planeHeight * this.aspectRatioEE + } else { + planeWidth = viewWidth + planeHeight = planeWidth / this.aspectRatioEE + } + if (!this.planeEE) { + const geo = new THREE.PlaneGeometry(planeWidth, planeHeight) + this.matEE = new THREE.MeshBasicMaterial({ map: this.backgroundTextureEE, transparent: false, alphaTest: 0.01, depthWrite:true, depthTest:true }) + this.matEE.defines = this.matEE.defines || {} + this.matEE.defines.USE_UV = "" + this.matEE.onBeforeCompile = shader => { + shader.uniforms.uReveal = { value: 0 } + shader.fragmentShader = shader.fragmentShader + .replace( + `#include `, + `#include + uniform float uReveal;` + ) + .replace( + `#include `, + `#include + if (vUv.x > uReveal) discard; + ` + ) + this.matEE.userData.shader = shader + } + + this.planeEE = new THREE.Mesh(geo, this.matEE) + this.planeEE.scale.set(.2, .2, 1) + this.planeEE.position.set(0, -0.8, 0) + this.planeEE.renderOrder = 1 + this.scene.add(this.planeEE) + } else { + this.planeEE.geometry.dispose() + this.planeEE.geometry = new THREE.PlaneGeometry(planeWidth, planeHeight) + } + + } animate() { requestAnimationFrame(this.animate.bind(this)) - + if (this.matEE.userData.shader) { + if(this.matEE.userData.shader.uniforms.uReveal.value<1){ + this.matEE.userData.shader.uniforms.uReveal.value += 0.01 + } + } if(Date.now()>this.nextAnim){ this.#lettersZ += .005 for(const letter of this.glassLetters){ @@ -215,7 +294,6 @@ class Intro{ } } - this.renderer.render(this.scene, this.camera) } diff --git a/app/assets/styles/intro.css b/app/assets/styles/intro.css index 92458e0..6f0a807 100644 --- a/app/assets/styles/intro.css +++ b/app/assets/styles/intro.css @@ -19,6 +19,7 @@ canvas.intro3d{ background:transparent; pointer-events: none; z-index:99; + opacity: 1; transform: scale(1) } canvas.intro3d.ready{ diff --git a/app/thirdparty/buildoz/buildoz.css b/app/thirdparty/buildoz/buildoz.css index 31f86b6..e58b232 100644 --- a/app/thirdparty/buildoz/buildoz.css +++ b/app/thirdparty/buildoz/buildoz.css @@ -136,4 +136,41 @@ bz-toggler div.toggle-switch span.toggle-thumb { bz-toggler div.toggle-switch span.toggle-thumb.turned-on { left : 1em; +} + +bz-slidepane div.handle.top { + position: absolute; + top: 0; + left: 50%; + width: 40px; + height: 11px; + background: repeating-linear-gradient( to top, rgba(255,255,255,1) 0, rgba(255,255,255,1) 2px, rgba(0,0,0,0.2) 3px, rgba(0,0,0,0.2) 4px ); + transform: translateX(-50%); +} +bz-slidepane div.handle.bottom { + position: absolute; + bottom: 0; + left: 50%; + width: 40px; + height: 11px; + background: repeating-linear-gradient( to bottom, rgba(255,255,255,1) 0, rgba(255,255,255,1) 2px, rgba(0,0,0,0.2) 3px, rgba(0,0,0,0.2) 4px ); + transform: translateX(-50%); +} +bz-slidepane div.handle.left { + position: absolute; + left: 0; + top: 50%; + width: 11px; + height: 40px; + background: repeating-linear-gradient( to left, rgba(255,255,255,1) 0, rgba(255,255,255,1) 2px, rgba(0,0,0,0.2) 3px, rgba(0,0,0,0.2) 4px ); + transform: translateY(-50%); +} +bz-slidepane div.handle.right { + position: absolute; + right: 0; + top: 50%; + width: 11px; + height: 40px; + background: repeating-linear-gradient( to right, rgba(255,255,255,1) 0, rgba(255,255,255,1) 2px, rgba(0,0,0,0.2) 3px, rgba(0,0,0,0.2) 4px ); + transform: translateY(-50%); } \ No newline at end of file diff --git a/app/thirdparty/buildoz/buildoz.js b/app/thirdparty/buildoz/buildoz.js index 74d2f0a..37a0377 100644 --- a/app/thirdparty/buildoz/buildoz.js +++ b/app/thirdparty/buildoz/buildoz.js @@ -247,3 +247,59 @@ class BZtoggler extends Buildoz { } } Buildoz.define('toggler', BZtoggler) + + + +class BZslidePane extends Buildoz { + + constructor(){ + super() + this.open = false + this.defaultAttrs = { + side: 'bottom' + } + this.dragMove = this.dragMove.bind(this) + this.dragEnd = this.dragEnd.bind(this) + } + + connectedCallback(){ + super.connectedCallback() + this.handle = document.createElement('div') + this.handle.classList.add('handle') + this.handle.classList.add(this.getBZAttribute('side')) + this.prepend(this.handle) + this.handle.addEventListener('pointerdown', this.dragStart.bind(this)) + } + + dragStart(evt){ + evt.target.setPointerCapture(evt.pointerId) + this.dragStartX = evt.clientX + this.dragStartY = evt.clientY + this.handle.addEventListener('pointermove', this.dragMove) + this.handle.addEventListener('pointerup', this.dragEnd) + } + + dragMove(evt){ + const dx = evt.clientX - this.dragStartX + const dy = evt.clientY - this.dragStartY + + switch(this.getAttribute('side')){ + case 'top': + break + case 'bottom': + break + case 'left': + break + case'right': + break + } + } + + dragEnd(evt){ + evt.target.releasePointerCapture(evt.pointerId) + this.handle.removeEventListener('pointermove', this.dragMove) + this.handle.removeEventListener('pointerup', this.dragEnd) + } +} +Buildoz.define('slidepane', BZslidePane) + diff --git a/app/views/editors/KeyframeView.html b/app/views/editors/KeyframeView.html index 39b560d..06e6c6f 100644 --- a/app/views/editors/KeyframeView.html +++ b/app/views/editors/KeyframeView.html @@ -96,6 +96,10 @@
+ + + +
diff --git a/index.html b/index.html index 03fd732..368d41a 100644 --- a/index.html +++ b/index.html @@ -9,9 +9,9 @@ { "imports": { "three": "https://cdn.jsdelivr.net/npm/three@0.160.0/build/three.module.js", - "three/examples/jsm/loaders/FontLoader.js": "https://unpkg.com/three@0.158.0/examples/jsm/loaders/FontLoader.js", - "three/examples/jsm/geometries/TextGeometry.js": "https://unpkg.com/three@0.158.0/examples/jsm/geometries/TextGeometry.js", - "three/examples/jsm/loaders/RGBELoader.js": "https://unpkg.com/three@0.158.0/examples/jsm/loaders/RGBELoader.js" + "three/examples/jsm/loaders/FontLoader.js": "https://unpkg.com/three@0.160.0/examples/jsm/loaders/FontLoader.js", + "three/examples/jsm/geometries/TextGeometry.js": "https://unpkg.com/three@0.160.0/examples/jsm/geometries/TextGeometry.js", + "three/examples/jsm/loaders/RGBELoader.js": "https://unpkg.com/three@0.160.0/examples/jsm/loaders/RGBELoader.js" } }