Skip to content

Commit

Permalink
added IsPaused engine parameter (#223)
Browse files Browse the repository at this point in the history
* added isPaused engine property
* added IsPaused explanation to storybook
  • Loading branch information
voronp authored May 26, 2022
1 parent c1fedc7 commit 1add55b
Show file tree
Hide file tree
Showing 2 changed files with 151 additions and 2 deletions.
14 changes: 12 additions & 2 deletions packages/react-babylonjs/src/Engine.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ const useCanvasObserver = (
return () => {
observer.unobserve(canvas)
}
}, [canvasRef, threshold])
}, [canvasRef, threshold, enabledOption])
}

export type EngineProps = {
Expand All @@ -51,6 +51,11 @@ export type EngineProps = {
adaptToDeviceRatio?: boolean
renderOptions?: RenderOptions

/**
* Skip rendering if set to true (takes precedence over RenderOptions.whenVisibleOnly)
*/
isPaused?: boolean

/**
* Attach resize event when canvas resizes (window resize may not occur).
* Defaults to true, so you need to opt-out.
Expand Down Expand Up @@ -91,6 +96,7 @@ const ReactBabylonjsEngine: React.FC<EngineProps> = (props: EngineProps, context

// const renderOptions: RenderOptions = props.renderOptions ?? {};
const {
isPaused,
touchActionNone,
canvasId,
engineOptions,
Expand All @@ -103,9 +109,13 @@ const ReactBabylonjsEngine: React.FC<EngineProps> = (props: EngineProps, context
...canvasProps
} = props

const observerEnabled = renderOptions !== undefined && renderOptions.whenVisibleOnly === true
const observerEnabled = renderOptions !== undefined && renderOptions.whenVisibleOnly === true && !isPaused
useCanvasObserver(canvasRef, shouldRenderRef, observerEnabled, 0)

useEffect(() => {
shouldRenderRef.current = !isPaused
}, [isPaused])

useEffect(() => {
if (canvasRef.current === null) {
return
Expand Down
139 changes: 139 additions & 0 deletions packages/storybook/stories/babylonjs/Basic/pauserender.stories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
import { Animation, Vector3 } from "@babylonjs/core";
import React, { useEffect, useRef, useState } from "react";
import { Engine, Scene, useScene } from "react-babylonjs";
import "../../style.css";

export default { title: "Babylon Basic" };

/**
* This is for optimizing animation when first mount application.
* But this story works well,Animation is smooth。
*/
function WithAnimation() {
// console.time('Timing');
const groupRef = useRef(null);
const scene = useScene();

const position = Vector3.Zero();

const playAnimation = () => {
if (groupRef.current) {
const group = groupRef.current;
const animations = getSlideUpAnimation(position, -2);
const animatable = scene.beginDirectAnimation(
group,
animations,
0,
120,
true
);
// console.timeLog('Timing', 'beginAnimation');
}
};

useEffect((_) => {
// console.timeLog('Timing', 'useEffect');
playAnimation();
}, []);

const onCreated = (_) => {
// console.timeLog('Timing', 'onCreated');
};

const spheres = getSpheres(10);

return (
<transformNode
name="group"
ref={groupRef}
position={position}
onCreated={onCreated}
>
{spheres}
</transformNode>
);
}

function getSpheres(count) {
const results = [];

for (let i = -count / 2; i < count / 2; i++) {
for (let j = -count / 2; j < count / 2; j++) {
const key = `sphere-${i}-${j}`;
results.push(
<sphere
name={key}
key={key}
diameter={0.5}
segments={16}
position={new Vector3(i, 1, j)}
/>
);
}
}

return results;
}

function getSlideUpAnimation(position, offsetY) {
const { y } = position;

const keys = [
{
frame: 0,
value: y + offsetY,
},
{
frame: 60,
value: y,
},
{
frame: 120,
value: y + offsetY,
},
];

const animation = new Animation("animation", "position.y", 60, 0, 1);
animation.setKeys(keys);

return [animation];
}

const renderOptions = {
whenVisibleOnly: true,
};

export const PauseRender = () => {
const [isPaused, setIsPaused] = useState(false);

useEffect(() => {
const seq = setInterval(() => {
setIsPaused((prev) => !prev);
}, 5000);
return () => clearInterval(seq);
}, []);

return <div style={{ flex: 1, display: "flex", flexFlow: 'column' }}>
<div style={{height: '1000px', color: 'white'}}>
<p>will render only if visible and not paused</p>
<p>Scroll down</p>
<p>{isPaused ? 'Paused' : 'Not Paused'}</p>
</div>
<Engine antialias adaptToDeviceRatio canvasId="babylonJS" isPaused={isPaused} renderOptions={renderOptions}>
<Scene>
<freeCamera
name="camera1"
position={new Vector3(0, 10, -20)}
setTarget={[Vector3.Zero()]}
/>
<hemisphericLight
name="light1"
intensity={0.7}
direction={Vector3.Up()}
/>
<WithAnimation />
</Scene>
</Engine>
</div>
};

0 comments on commit 1add55b

Please sign in to comment.