Skip to content

Instantly share code, notes, and snippets.

@wonglok
Last active January 17, 2021 22:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wonglok/cdb7cf080f6263872b4042eeaae6f1ca to your computer and use it in GitHub Desktop.
Save wonglok/cdb7cf080f6263872b4042eeaae6f1ca to your computer and use it in GitHub Desktop.
EffectNode.js
let isFunction = function(obj) {
return typeof obj === 'function' || false;
}
class EventEmitter {
// https://gist.github.com/datchley/37353d6a2cb629687eb9
constructor() {
this.listeners = new Map();
}
on(label, callback) {
this.listeners.has(label) || this.listeners.set(label, []);
this.listeners.get(label).push(callback);
return () => {
this.off(label, callback)
}
}
off(label, callback) {
let listeners = this.listeners.get(label),
index;
if (listeners && listeners.length) {
index = listeners.reduce((i, listener, index) => {
return (isFunction(listener) && listener === callback) ?
i = index :
i;
}, -1);
if (index > -1) {
listeners.splice(index, 1);
this.listeners.set(label, listeners);
return true;
}
}
return false;
}
emit (label, ...args) {
let listeners = this.listeners.get(label);
if (listeners && listeners.length) {
listeners.forEach((listener) => {
listener(...args);
});
return true;
}
return false;
}
}
class Wire extends EventEmitter {
constructor () {
super()
}
}
export class AutoWire {
constructor () {
let map = new Map()
let proxy = new Proxy({}, {
get: (object, key) => {
if (map.has(key)) {
return map.get(key)
} else {
let wire = new Wire()
map.set(key, wire)
return wire
}
},
set: (object, key, val) => {
console.log('enWire is read only')
return true
}
})
return proxy
}
}
import { useState, useRef, useEffect, useMemo } from "react"
import { Canvas } from "react-three-fiber"
import { ACESFilmicToneMapping, sRGBEncoding } from "three"
import { AutoWire } from "./effectnode"
// let getID = () => `_${(Math.random() * 100000000).toFixed(0)}`
function useInput (input, event, fnc, memo = []) {
useEffect(() => {
let off = input.on(event, fnc)
return () => {
off()
}
}, memo)
}
export function BoxClicker ({ output, ...props }) {
let onClick = () => { output.emit('data', { rand: Math.random() }) }
let Html = require('drei').Html
return <mesh
{...props}
onClick={onClick}
>
<Html
center
>
<div onClick={onClick} className="w-32">Click Me</div>
</Html>
<boxBufferGeometry args={[1,1,1]}></boxBufferGeometry>
<meshStandardMaterial color={'#bababa'}></meshStandardMaterial>
</mesh>
}
export function BoxColor ({ input, ...props }) {
const [color, setColor] = useState(0xffffff)
let onClick = () => { props.output.emit('data', { rand: Math.random() }) }
useInput(input, 'data', ({ rand }) => {
setColor(0xffffff * rand)
})
return <mesh
{...props}
onClick={() => { onClick() }}
>
<boxBufferGeometry args={[1,1,1]}></boxBufferGeometry>
<meshStandardMaterial color={color}></meshStandardMaterial>
</mesh>
}
export function MyCanvasScene () {
let wire = useMemo(() => {
// Singleton + Lazy Instantiatoin
return new AutoWire()
}, [])
return <scene>
<BoxClicker position={[-1,0,0]} output={wire.lok}></BoxClicker>
<BoxColor position={[1,0,0]} input={wire.lok}></BoxColor>
<BoxColor position={[1,1.1,0]} input={wire.lok}></BoxColor>
<BoxColor position={[1,-1.1,0]} input={wire.lok}></BoxColor>
</scene>
}
export default function EffectNode () {
const mouse = useRef({ x: 0, y: 0 })
return <Canvas
shadowMap
pixelRatio={[1.2, 2.0]}
// onPointerMove={(e) => ( mouse.current = getMousePos(e)) }}
// onTouchMove={(e) => { mouse.current = getFirstTouchPos(e); }}
// onTouchStart={(e) => { mouse.current = getFirstTouchPos(e); }}
onCreated={({ gl }) => {
gl.toneMapping = ACESFilmicToneMapping
gl.outputEncoding = sRGBEncoding
mouse.current.x = gl.domElement.width / 2
mouse.current.y = gl.domElement.height / 2
}}
>
<ambientLight intensity={1}></ambientLight>
<MyCanvasScene dispose={null} mouse={mouse}></MyCanvasScene>
</Canvas>
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment