Skip to content

Commit

Permalink
add: onCreated to Scene
Browse files Browse the repository at this point in the history
fix: breaking change to SceneLoader.ImportMesh returning void
  • Loading branch information
brianzinn committed Dec 16, 2024
1 parent b9a40ed commit 56e33c9
Show file tree
Hide file tree
Showing 10 changed files with 1,972 additions and 2,069 deletions.
4 changes: 2 additions & 2 deletions devtool/loader/src/codesandbox-templates/ts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@
"devDependencies": {
"prettier": "2.6.1",
"prettier-plugin-organize-imports": "2.3.4",
"@types/react": "^18.0.21",
"@types/react-dom": "^18.0.6",
"@types/react": "^18.2.45",
"@types/react-dom": "^18.2.18",
"typescript": "4.4.2"
},
"scripts": {
Expand Down
5 changes: 2 additions & 3 deletions devtool/react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@
"react-bootstrap": "^2.1.1",
"react-cookie": "^4.1.1",
"react-icons": "^4.3.1",
"react-syntax-highlighter": "^15.4.5",
"react-tabs": "^3.2.3",
"react-syntax-highlighter": "^15.5.0",
"react-tabs": "^6.0.2",
"tslib": "^2.3.1",
"type-fest": "^2.9.0"
},
Expand All @@ -45,7 +45,6 @@
"@storybook/react": "^6.4.13",
"@types/prettier": "^2.4.3",
"@types/react-syntax-highlighter": "^15.5.5",
"@types/react-tabs": "^2.3.4",
"rimraf": "^3.0.2",
"typescript": "^4.5.4",
"webpack": "5"
Expand Down
7 changes: 6 additions & 1 deletion devtool/react/src/DevTool.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,17 @@ import Button from 'react-bootstrap/Button'
import ButtonGroup from 'react-bootstrap/ButtonGroup'
import Modal from 'react-bootstrap/Modal'
import { FaCog, FaExternalLinkAlt } from 'react-icons/fa'
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'
import { Prism, SyntaxHighlighterProps } from 'react-syntax-highlighter'
import { dark } from 'react-syntax-highlighter/dist/esm/styles/prism'
import { Tab, TabList, TabPanel, Tabs } from 'react-tabs'
import 'react-tabs/style/react-tabs.css'
import { createCookieHooker } from './cookieHook'

// Its instance type 'SyntaxHighlighter' is not a valid JSX element.
// Property 'refs' is missing in type 'Component<SyntaxHighlighterProps, {}, any>' but required in type 'ElementClass'.
// https://github.com/react-syntax-highlighter/react-syntax-highlighter/issues/539
const SyntaxHighlighter = Prism as unknown as typeof React.Component<SyntaxHighlighterProps>

const plugins = [typescript]

const PRETTIER_OPTS: Options = {
Expand Down
4 changes: 2 additions & 2 deletions packages/react-babylonjs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@
"@types/lodash.camelcase": "^4.3.6",
"@types/mocha": "^9.1.0",
"@types/node": "^14.18.21",
"@types/react": "^18.0.21",
"@types/react-dom": "^18.0.6",
"@types/react": "^18.2.45",
"@types/react-dom": "^18.2.18",
"@types/react-reconciler": "^0.28.0",
"@types/sinon": "^9.0.10",
"@typescript-eslint/eslint-plugin": "^4.29.1",
Expand Down
17 changes: 11 additions & 6 deletions packages/react-babylonjs/src/Scene.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@ type SceneProps = {
onScenePointerDown?: (evt: PointerInfo, scene: BabylonScene) => void
onScenePointerUp?: (evt: PointerInfo, scene: BabylonScene) => void
onScenePointerMove?: (evt: PointerInfo, scene: BabylonScene) => void
/**
* Called immediately after the Scene is created
*/
onCreated?: (scene: BabylonScene) => void
/**
* Called after props are applied
*/
onSceneMount?: (sceneEventArgs: SceneEventArgs) => void
children: React.ReactNode
sceneOptions?: SceneOptions
Expand Down Expand Up @@ -70,6 +77,10 @@ const Scene: React.FC<SceneProps> = (props: SceneProps, context?: any) => {
() => {
const newScene = new BabylonScene(engine!, props.sceneOptions)

if (typeof props.onCreated === 'function') {
props.onCreated(newScene)
}

// TODO: try to move the scene to parentComponent in updateContainer
const container: Container = {
scene: newScene,
Expand Down Expand Up @@ -144,12 +155,6 @@ const Scene: React.FC<SceneProps> = (props: SceneProps, context?: any) => {
// TODO: console.error if canvas is not attached. runRenderLoop() is expected to be part of onSceneMount().
}

// TODO: change enable physics to 'usePhysics' taking an object with a Vector3 and 'any'.
// NOTE: must be enabled for updating container (cannot add impostors w/o physics enabled)
if (Array.isArray(props.enablePhysics)) {
newScene.enablePhysics(props.enablePhysics[0], props.enablePhysics[1])
}

const sceneGraph = (
<SceneContext.Provider
value={{
Expand Down
4 changes: 4 additions & 0 deletions packages/react-babylonjs/src/hooks/loaders/loadedModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ export class LoadedModel implements ILoadedModel {
public status: LoaderStatus = LoaderStatus.Loading
public rootMesh?: Mesh
public errorMessage?: string
/**
* Not supported anymore:
* https://forum.babylonjs.com/t/potential-new-breaking-change-please-chime-in/54651/5
*/
public loaderName?: string
public meshes?: AbstractMesh[]
public particleSystems?: IParticleSystem[]
Expand Down
171 changes: 81 additions & 90 deletions packages/react-babylonjs/src/hooks/loaders/useSceneLoader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -158,104 +158,95 @@ const useSceneLoaderWithCache = (): ((
const loadedModel = new LoadedModel()

loadedModel.status = LoaderStatus.Loading

const loader: Nullable<ISceneLoaderPlugin | ISceneLoaderPluginAsync> =
SceneLoader.ImportMesh(
opts.meshNames,
rootUrl,
sceneFilename,
scene,
(
meshes: AbstractMesh[],
particleSystems: IParticleSystem[],
skeletons: Skeleton[],
animationGroups: AnimationGroup[]
): void => {
loadedModel.rootMesh = new Mesh(sceneFilename + '-root-model', scene)
if (opts.alwaysSelectAsActiveMesh === true) {
loadedModel.rootMesh.alwaysSelectAsActiveMesh = true
loadedModel.loaderName = 'no longer supported /BabylonJS/Babylon.js/pull/15798'

/* const loader: Nullable<ISceneLoaderPlugin | ISceneLoaderPluginAsync> = */
SceneLoader.ImportMeshAsync(
opts.meshNames,
rootUrl,
sceneFilename,
scene,
(event: ISceneLoaderProgressEvent): void => {
if (opts.reportProgress === true && sceneLoaderContext !== undefined) {
sceneLoaderContext!.updateProgress(event)
}
if (opts.onLoadProgress) {
opts.onLoadProgress(event)
}
},
pluginExtension
)
.then((result) => {
loadedModel.rootMesh = new Mesh(sceneFilename + '-root-model', scene)
if (opts.alwaysSelectAsActiveMesh === true) {
loadedModel.rootMesh.alwaysSelectAsActiveMesh = true
}

loadedModel.meshes = []
result.meshes.forEach((mesh) => {
loadedModel.meshes!.push(mesh)

// leave meshes already parented to maintain model hierarchy:
if (!mesh.parent) {
mesh.parent = loadedModel.rootMesh!
}

loadedModel.meshes = []
meshes.forEach((mesh) => {
loadedModel.meshes!.push(mesh)

// leave meshes already parented to maintain model hierarchy:
if (!mesh.parent) {
mesh.parent = loadedModel.rootMesh!
}

if (opts.receiveShadows === true) {
mesh.receiveShadows = true
if (opts.receiveShadows === true) {
mesh.receiveShadows = true
}
})
loadedModel.particleSystems = result.particleSystems
loadedModel.skeletons = result.skeletons
loadedModel.animationGroups = result.animationGroups

// NOTE: geometries, lights, spriteManagers, etc. can be added here
loadedModel.status = LoaderStatus.Loaded

if (opts.scaleToDimension) {
loadedModel.scaleTo(opts.scaleToDimension)
}

if (initialProps) {
const initPayload: PropertyUpdate[] = []
new FiberMesh().getPropsHandlers().forEach((propHandler: PropsHandler<any>) => {
const handlerUpdates: PropertyUpdate[] | null = propHandler.getPropertyUpdates(
{}, // Here we will reapply things like 'name', so we could get default props from 'babylonObject'.
initialProps
)
if (handlerUpdates !== null) {
initPayload.push(...handlerUpdates)
}
})
loadedModel.particleSystems = particleSystems
loadedModel.skeletons = skeletons
loadedModel.animationGroups = animationGroups

loadedModel.status = LoaderStatus.Loaded

if (opts.scaleToDimension) {
loadedModel.scaleTo(opts.scaleToDimension)
}

if (initialProps) {
const initPayload: PropertyUpdate[] = []
new FiberMesh().getPropsHandlers().forEach((propHandler: PropsHandler<any>) => {
const handlerUpdates: PropertyUpdate[] | null = propHandler.getPropertyUpdates(
{}, // Here we will reapply things like 'name', so we could get default props from 'babylonObject'.
initialProps
if (initPayload.length > 0) {
initPayload.forEach((update) => {
applyUpdateToInstance(
{ hostInstance: loadedModel.rootMesh } as CreatedInstance<Mesh>,
update
)
if (handlerUpdates !== null) {
initPayload.push(...handlerUpdates)
}
})

if (initPayload.length > 0) {
initPayload.forEach((update) => {
applyUpdateToInstance(
{ hostInstance: loadedModel.rootMesh } as CreatedInstance<Mesh>,
update
)
})
}
}

if (options?.onModelLoaded) {
options.onModelLoaded(loadedModel)
}

const originalDispose = loadedModel.dispose
loadedModel.dispose = () => {
// console.log('Clearing cache (cannot re-use meshes).');
suspenseCache[suspenseKey] = undefined
originalDispose.call(loadedModel)
}

resolve(loadedModel)
},
(event: ISceneLoaderProgressEvent): void => {
if (opts.reportProgress === true && sceneLoaderContext !== undefined) {
sceneLoaderContext!.updateProgress(event)
}
if (opts.onLoadProgress) {
opts.onLoadProgress(event)
}
},
(_: Scene, message: string, exception?: any): void => {
if (opts.onModelError) {
opts.onModelError(message, exception)
}
reject(exception ?? message)
},
pluginExtension
)

if (loader) {
loadedModel.loaderName = loader.name
} else {
loadedModel.loaderName = 'no loader found'
}
}

if (options?.onModelLoaded) {
options.onModelLoaded(loadedModel)
}

const originalDispose = loadedModel.dispose
loadedModel.dispose = () => {
// console.log('Clearing cache (cannot re-use meshes).');
suspenseCache[suspenseKey] = undefined
originalDispose.call(loadedModel)
}
resolve(loadedModel)
})
.catch((error) => {
if (opts.onModelError) {
opts.onModelError(error)
}
reject(error)
})
loadedModel.loaderName = 'Not supported for backwards compat'
})

let result: LoadedModel
Expand Down
4 changes: 0 additions & 4 deletions packages/static/content/examples/physics/Physics2.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,6 @@ import BouncySphere from './BouncySphere2'
import HavokPhysics, { HavokPhysicsWithBindings } from '@babylonjs/havok'
import { Color3 } from '@babylonjs/core'

// build error that 'window is not defined'
// window.CANNON = CANNON;

const gravityVector = new Vector3(0, -9.81, 0)
const RADIUS = 5
const NUMBER_OF_BOXES = 8

Expand Down
2 changes: 1 addition & 1 deletion packages/static/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@
"@emotion/babel-plugin": "^11.7.2",
"@emotion/babel-preset-css-prop": "^11.2.0",
"@types/earcut": "^2.1.1",
"@types/react": "^18.0.21",
"@types/react": "^18.2.45",
"babel-eslint": "^10.1.0",
"babel-preset-gatsby": "^2.5.2",
"concurrently": "^7.0.0",
Expand Down
Loading

0 comments on commit 56e33c9

Please sign in to comment.