I am a react developer. And my task is to connect a project from Babylon Editor. In search of a solution to this problem, I found only one question (How to incorporate project.editorproject (from Babylonjs Editor export) into React project?) and not a single tutorial. There are a lot of questions, including how to integrate a project with a creatreact app. Babylon the editor supplies the typescript. Do I need to translate the entire project into typescript? It would be desirable to see an example of the integration of such a project.
Adding @julien-moreau the editor daddy to the rescue.
Hi @Pavel_Bero !
You are right the link your shared is outdated and is related to an old version of the editor.
Once you have created a project (empty, or whatever), the only thing to do is to transform the Game
class as a React component. Here is a complete example with:
index.html:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Babylon.js Generated Template</title>
<script src="./dist/bundle.js" type="text/javascript"></script>
<style rel="stylesheet" type="text/css">
html,
body {
overflow: hidden;
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
#gameContainer {
position: absolute;
width: 100%;
height: 100%;
top: 0;
touch-action: none;
-ms-touch-action: none;
}
#renderCanvas {
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<div id="gameContainer"></div>
<script type="text/javascript">
game.initialize();
</script>
</body>
</html>
game.tsx (previously game.ts):
import { render } from "react-dom";
import * as React from "react";
import "@babylonjs/materials";
import { BabylonFileLoaderConfiguration, Engine, Nullable, Scene, SceneLoader } from "@babylonjs/core";
import * as CANNON from "cannon";
import { runScene } from "./scenes/scene";
/**
* Defines the function called in the index.html file that initializes the game
* as a React component.
*/
export function initialize(): void {
render(<Game />, document.getElementById("gameContainer"));
}
/**
* The class now becomes a react component.
*/
export class Game extends React.Component {
/**
* Defines the engine used to draw the game using Babylon.JS and WebGL
*/
public engine: Engine;
/**
* Defines the scene used to store and draw elements in the canvas.
*/
public scene: Scene;
private _canvasRef: Nullable<HTMLCanvasElement> = null;
/**
* Renders the component.
*/
public render(): React.ReactNode {
return (
<canvas ref={(r) => this._canvasRef = r} id="renderCanvas" />
);
}
/**
* Called on the component did mount.
*/
public componentDidMount(): void {
if (!this._canvasRef) {
throw new Error("Failed to get canvas reference.");
}
this.engine = new Engine(this._canvasRef, true);
this.scene = new Scene(this.engine);
this._bindEvents();
this._load();
}
/**
* Loads the first scene.
*/
private _load(): void {
const rootUrl = "./scenes/scene/";
BabylonFileLoaderConfiguration.LoaderInjectedPhysicsEngine = CANNON;
SceneLoader.Append(rootUrl, "scene.babylon", this.scene, () => {
this.scene.executeWhenReady(() => {
// Attach camera.
if (!this.scene.activeCamera) {
throw new Error("No camera defined in the scene. Please add at least one camera in the project or create one yourself in the code.");
}
this.scene.activeCamera.attachControl(this.engine.getRenderingCanvas(), false);
// Run the scene to attach scripts etc.
runScene(this.scene, rootUrl);
// Render.
this.engine.runRenderLoop(() => this.scene.render());
});
}, undefined, (_, message) => {
console.error(message);
}, "babylon");
}
/**
* Binds the required events for a full experience.
*/
private _bindEvents(): void {
window.addEventListener("resize", () => this.engine.resize());
}
}
package.json (using webpack 5)
{
"name": "babylonjs-editor-generated-template",
"version": "4.1.0",
"description": "Generated Template by BabylonJS Editor v4.1",
"scripts": {
"clean": "rimraf build declaration dist",
"compile": "tsc -p .",
"build": "webpack --mode production",
"watch": "webpack --mode development --watch",
"webserver": "http-server -p 1338 -c-1"
},
"license": "(Apache-2.0)",
"devDependencies": {
"@types/node": "17.0.0",
"@types/webpack": "5.28.0",
"@types/react": "17.0.37",
"@types/react-dom": "17.0.11",
"typescript": "4.5.4",
"http-server": "0.12.1",
"webpack": "5.65.0",
"webpack-cli": "4.9.1",
"ts-loader": "9.2.6",
"raw-loader": "4.0.2",
"babel-loader": "8.2.3",
"babylonjs-editor-webpack-progress": "1.0.1"
},
"dependencies": {
"rimraf": "3.0.2",
"@babylonjs/core": "4.2.0",
"@babylonjs/loaders": "4.2.0",
"@babylonjs/materials": "4.2.0",
"@babylonjs/post-processes": "4.2.0",
"@babylonjs/procedural-textures": "4.2.0",
"@babylonjs/gui": "4.2.0",
"cannon": "0.6.2",
"earcut": "2.2.3",
"react": "17.0.2",
"react-dom": "17.0.2"
}
}
and the new webpack.config.js to include .tsx files support:
const path = require("path");
const webpack = require("webpack");
const editor = require("babylonjs-editor-webpack-progress");
module.exports = (_, argv) => {
const entryPath = path.join(__dirname, "src/game.tsx");
const package = require("./package.json");
return {
// we output both a minified version & a non minified version on production build
entry: { "bundle": entryPath },
output: {
filename: `bundle.js`,
path: path.join(__dirname, "dist"),
library: "game",
libraryTarget: "umd",
},
module: {
rules: [
{
test: /\.ts(x?)?$/,
loader: "ts-loader",
exclude: [
path.join(__dirname, "node_modules"),
path.join(__dirname, "dist"),
path.join(__dirname, "projects"),
path.join(__dirname, "scenes"),
],
},
{
test: /\.fx?$/,
loader: "raw-loader",
},
],
},
resolve: {
extensions: [".ts", ".tsx", ".js"],
},
plugins: [
new webpack.BannerPlugin({
banner: `${package.name} ${package.version} ${new Date().toString()}`,
}),
new webpack.WatchIgnorePlugin({
paths: [/\.js$/, /\.d\.ts$/],
}),
editor.createProgressPlugin(new webpack.ProgressPlugin()),
],
optimization: {
minimize: false,
usedExports: true,
},
devtool: "source-map",
};
};
Don’t forget to add "jsx": "react"
(or other) in the tsconfig.json to add the support of JSX in your project
2 Likes