Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Editor: add RectAreaLight #28187

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions editor/index.html
Expand Up @@ -61,6 +61,7 @@
<script type="module">

import * as THREE from 'three';
import { RectAreaLightUniformsLib } from 'three/addons/lights/RectAreaLightUniformsLib.js';

import { Editor } from './js/Editor.js';
import { Viewport } from './js/Viewport.js';
Expand All @@ -82,6 +83,8 @@

//

RectAreaLightUniformsLib.init();

const editor = new Editor();

window.editor = editor; // Expose editor to Console
Expand Down
5 changes: 5 additions & 0 deletions editor/js/Editor.js
@@ -1,4 +1,5 @@
import * as THREE from 'three';
import { RectAreaLightHelper } from 'three/addons/helpers/RectAreaLightHelper.js';

import { Config } from './Config.js';
import { Loader } from './Loader.js';
Expand Down Expand Up @@ -431,6 +432,10 @@ Editor.prototype = {

helper = new THREE.HemisphereLightHelper( object, 1 );

} else if ( object.isRectAreaLight ) {

helper = new RectAreaLightHelper( object );

} else if ( object.isSkinnedMesh ) {

helper = new THREE.SkeletonHelper( object.skeleton.bones[ 0 ] );
Expand Down
20 changes: 20 additions & 0 deletions editor/js/Menubar.Add.js
Expand Up @@ -385,6 +385,26 @@ function MenubarAdd( editor ) {
} );
options.add( option );

// RectAreaLight

option = new UIRow();
option.setClass( 'option' );
option.setTextContent( strings.getKey( 'menubar/add/rectarealight' ) );
option.onClick( function () {

const color = 0xffffff;
const intensity = 1;
const width = 10;
const height = 10;

const light = new THREE.RectAreaLight( color, intensity, width, height );
light.name = 'RectAreaLight';

editor.execute( new AddObjectCommand( editor, light ) );

} );
options.add( option );

// SpotLight

option = new UIRow();
Expand Down
46 changes: 46 additions & 0 deletions editor/js/Sidebar.Object.js
Expand Up @@ -214,6 +214,26 @@ function SidebarObject( editor ) {

container.add( objectFarRow );

// width

const objectWidthRow = new UIRow();
const objectWidth = new UINumber().onChange( update );

objectWidthRow.add( new UIText( strings.getKey( 'sidebar/object/width' ) ).setClass( 'Label' ) );
objectWidthRow.add( objectWidth );

container.add( objectWidthRow );

// height

const objectHeightRow = new UIRow();
const objectHeight = new UINumber().onChange( update );

objectHeightRow.add( new UIText( strings.getKey( 'sidebar/object/height' ) ).setClass( 'Label' ) );
objectHeightRow.add( objectHeight );

container.add( objectHeightRow );

// intensity

const objectIntensityRow = new UIRow();
Expand Down Expand Up @@ -508,6 +528,18 @@ function SidebarObject( editor ) {

}

if ( object.width !== undefined && Math.abs( object.width - objectWidth.getValue() ) >= 0.01 ) {

editor.execute( new SetValueCommand( editor, object, 'width', objectWidth.getValue() ) );

}

if ( object.height !== undefined && Math.abs( object.height - objectHeight.getValue() ) >= 0.01 ) {

editor.execute( new SetValueCommand( editor, object, 'height', objectHeight.getValue() ) );

}

if ( object.intensity !== undefined && Math.abs( object.intensity - objectIntensity.getValue() ) >= 0.01 ) {

editor.execute( new SetValueCommand( editor, object, 'intensity', objectIntensity.getValue() ) );
Expand Down Expand Up @@ -625,6 +657,8 @@ function SidebarObject( editor ) {
function updateRows( object ) {

const properties = {
'width': objectWidthRow,
'height': objectHeightRow,
'fov': objectFovRow,
'left': objectLeftRow,
'right': objectRightRow,
Expand Down Expand Up @@ -751,6 +785,18 @@ function SidebarObject( editor ) {
objectScaleY.setValue( object.scale.y );
objectScaleZ.setValue( object.scale.z );

if ( object.width !== undefined ) {

objectWidth.setValue( object.width );

}

if ( object.height !== undefined ) {

objectHeight.setValue( object.height );

}

if ( object.fov !== undefined ) {

objectFov.setValue( object.fov );
Expand Down
42 changes: 42 additions & 0 deletions editor/js/Sidebar.Project.App.js
Expand Up @@ -85,6 +85,14 @@ function SidebarProjectApp( editor ) {

const toZip = {};

const scene = editor.scene;
let hasRectAreaLight = false;
scene.traverse( function ( child ) {

if ( child.isRectAreaLight === true ) hasRectAreaLight = true;

} );

//

let output = editor.toJSON();
Expand Down Expand Up @@ -136,6 +144,30 @@ function SidebarProjectApp( editor ) {

content = content.replace( '\t\t\t/* edit button */', editButton );

const importAddonsScripts = [];
if ( hasRectAreaLight ) importAddonsScripts.push( '\t\t\timport { RectAreaLightUniformsLib } from \'three/addons/lights/RectAreaLightUniformsLib.js\';' );
if ( importAddonsScripts.length > 0 ) {

content = content.replace( '\t\t\t/* import addons js */', importAddonsScripts.join( '\n\t\t\t' ) );

} else {

content = content.replace( '\t\t\t/* import addons js */\r\n', '' );

}

const initAddonsScripts = [];
if ( hasRectAreaLight ) initAddonsScripts.push( '\t\t\tRectAreaLightUniformsLib.init();' );
if ( initAddonsScripts.length > 0 ) {

content = content.replace( '\t\t\t/* init addons js */', initAddonsScripts.join( '\n\t\t\t' ) );

} else {

content = content.replace( '\t\t\t/* init addons js */\r\n', '' );

}

toZip[ 'index.html' ] = strToU8( content );

} );
Expand All @@ -150,6 +182,16 @@ function SidebarProjectApp( editor ) {

} );

if ( hasRectAreaLight ) {

loader.load( '../examples/jsm/lights/RectAreaLightUniformsLib.js', function ( content ) {

toZip[ 'js/lights/RectAreaLightUniformsLib.js' ] = strToU8( content );

} );

}

} );
container.add( publishButton );

Expand Down
12 changes: 12 additions & 0 deletions editor/js/Strings.js
Expand Up @@ -45,6 +45,7 @@ function Strings( config ) {
'menubar/add/lathe': 'Lathe',
'menubar/add/sprite': 'Sprite',
'menubar/add/pointlight': 'PointLight',
'menubar/add/rectarealight': 'RectAreaLight',
'menubar/add/spotlight': 'SpotLight',
'menubar/add/directionallight': 'DirectionalLight',
'menubar/add/hemispherelight': 'HemisphereLight',
Expand Down Expand Up @@ -99,6 +100,8 @@ function Strings( config ) {
'sidebar/object/bottom': 'Bottom',
'sidebar/object/near': 'Near',
'sidebar/object/far': 'Far',
'sidebar/object/height': 'Height',
'sidebar/object/width': 'Width',
'sidebar/object/intensity': 'Intensity',
'sidebar/object/color': 'Color',
'sidebar/object/groundcolor': 'Ground Color',
Expand Down Expand Up @@ -398,6 +401,7 @@ function Strings( config ) {
'menubar/add/lathe': 'Tour',
'menubar/add/sprite': 'Sprite',
'menubar/add/pointlight': 'Lumière ponctuelle',
'menubar/add/rectarealight': 'RectAreaLight',
'menubar/add/spotlight': 'Projecteur',
'menubar/add/directionallight': 'Lumière directionnelle',
'menubar/add/hemispherelight': 'Lumière hémisphérique',
Expand Down Expand Up @@ -452,6 +456,8 @@ function Strings( config ) {
'sidebar/object/bottom': 'Bas',
'sidebar/object/near': 'Près',
'sidebar/object/far': 'Loin',
'sidebar/object/height': 'Height',
'sidebar/object/width': 'Width',
'sidebar/object/intensity': 'Intensité',
'sidebar/object/color': 'Couleur',
'sidebar/object/groundcolor': 'Couleur de fond',
Expand Down Expand Up @@ -751,6 +757,7 @@ function Strings( config ) {
'menubar/add/lathe': '酒杯',
'menubar/add/sprite': '精灵',
'menubar/add/pointlight': '点光源',
'menubar/add/rectarealight': 'RectAreaLight',
'menubar/add/spotlight': '聚光灯',
'menubar/add/directionallight': '平行光',
'menubar/add/hemispherelight': '半球光',
Expand Down Expand Up @@ -805,6 +812,8 @@ function Strings( config ) {
'sidebar/object/bottom': '下',
'sidebar/object/near': '近点',
'sidebar/object/far': '远点',
'sidebar/object/height': 'Height',
'sidebar/object/width': 'Width',
'sidebar/object/intensity': '强度',
'sidebar/object/color': '颜色',
'sidebar/object/groundcolor': '基色',
Expand Down Expand Up @@ -1104,6 +1113,7 @@ function Strings( config ) {
'menubar/add/lathe': '旋盤形',
'menubar/add/sprite': 'スプライト',
'menubar/add/pointlight': 'ポイントライト',
'menubar/add/rectarealight': 'RectAreaLight',
'menubar/add/spotlight': 'スポットライト',
'menubar/add/directionallight': 'ディレクショナルライト',
'menubar/add/hemispherelight': 'ヘミスフィアライト',
Expand Down Expand Up @@ -1158,6 +1168,8 @@ function Strings( config ) {
'sidebar/object/bottom': '下',
'sidebar/object/near': '範囲の開始',
'sidebar/object/far': '範囲の終了',
'sidebar/object/height': 'Height',
'sidebar/object/width': 'Width',
'sidebar/object/intensity': '強度',
'sidebar/object/color': '色',
'sidebar/object/groundcolor': '地面の色',
Expand Down
2 changes: 1 addition & 1 deletion editor/js/Viewport.js
Expand Up @@ -437,7 +437,7 @@ function Viewport( editor ) {

const helper = editor.helpers[ object.id ];

if ( helper !== undefined && helper.isSkeletonHelper !== true ) {
if ( helper !== undefined && helper.isSkeletonHelper !== true && helper.type !== 'RectAreaLightHelper' ) {

helper.update();

Expand Down
5 changes: 4 additions & 1 deletion editor/js/libs/app/index.html
Expand Up @@ -21,16 +21,19 @@
<script type="importmap">
{
"imports": {
"three": "./js/three.module.js"
"three": "./js/three.module.js",
"three/addons/": "./js/"
}
}
</script>
<script type="module">

import * as THREE from 'three';
/* import addons js */
import { APP } from './js/app.js';

window.THREE = THREE; // Used by APP Scripts.
/* init addons js */
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for giving this a shot!

I'm not sure yet how I feel about this solution. I understand the idea behind it but I wonder if we can inject imports and initialization code a bit cleaner. Need to think about this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure yet how I feel about this solution. I understand the idea behind it but I wonder if we can inject imports and initialization code a bit cleaner. Need to think about this.

Thank you for your response.

At present, I think of two other methods, but may not be what you expect, if you have a good idea please let me know.

  1. ES6 Template literals https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals
  2. Use existing libraries. I try to use MagicString ( https://github.com/rich-harris/magic-string ), this library may not be suitable, there may be a more suitable library, but I do not know at the moment...

Example code for Method 1:

const content = `<!DOCTYPE html>
<html lang="en">
	<head>
		<title>${title}</title>
		<meta charset="utf-8">
		<meta name="generator" content="Three.js Editor">
		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
		<style>
			body {
				font-family: sans-serif;
				font-size: 11px;
				background-color: #000;
				margin: 0px;
			}
			canvas {
				display: block;
			}
		</style>
	</head>
	<body ontouchstart="">
		<script type="importmap">
			{
				"imports": {
					"three": "./js/three.module.js",
					"three/addons/": "./js/"
				}
			}
		</script>
		<script type="module">

			import * as THREE from 'three';
			${ hasRectAreaLight ? 'import { RectAreaLightUniformsLib } from \'three/addons/lights/RectAreaLightUniformsLib.js\';' : '' }
			import { APP } from './js/app.js';

			window.THREE = THREE; // Used by APP Scripts.
			${ hasRectAreaLight ? 'RectAreaLightUniformsLib.init();' : '' }

			var loader = new THREE.FileLoader();
			loader.load( 'app.json', function ( text ) {

				var player = new APP.Player();
				player.load( JSON.parse( text ) );
				player.setSize( window.innerWidth, window.innerHeight );
				player.play();

				document.body.appendChild( player.dom );

				window.addEventListener( 'resize', function () {

					player.setSize( window.innerWidth, window.innerHeight );

				} );

			} );

			${editButton}

		</script>
	</body>
</html>`;

toZip[ 'index.html' ] = strToU8( content );

Example code for Method 2:

<!DOCTYPE html>
<html lang="en">

<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
</head>

<body>
	<script type="importmap">
        {
            "imports": {
                "magic-string": "https://unpkg.com/magic-string@0.30.10/dist/magic-string.es.mjs",
                "@jridgewell/sourcemap-codec": "https://unpkg.com/@jridgewell/sourcemap-codec@1.4.15/dist/sourcemap-codec.mjs"
            }
        }
    </script>
	<script type="module">
		import MagicString from 'magic-string';

		const htmlStr = `<!DOCTYPE html>
<html lang="en">
	<head>
		<title><!-- title --></title>
		<meta charset="utf-8">
		<meta name="generator" content="Three.js Editor">
		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
		<style>
			body {
				font-family: sans-serif;
				font-size: 11px;
				background-color: #000;
				margin: 0px;
			}
			canvas {
				display: block;
			}
		</style>
	</head>
	<body ontouchstart="">
		<script type="importmap">
			{
				"imports": {
					"three": "./js/three.module.js",
					"three/addons/": "./js/"
				}
			}
		<\/script>
		<script type="module">
		<\/script>
	</body>
</html>`;

		const html = new MagicString(htmlStr);
		html.replace('<!-- title -->', 'hello world');

		const modulejs = /* js */`
import * as THREE from 'three';
import { APP } from './js/app.js';

window.THREE = THREE; // Used by APP Scripts.

var loader = new THREE.FileLoader();
loader.load( 'app.json', function ( text ) {

	var player = new APP.Player();
	player.load( JSON.parse( text ) );
	player.setSize( window.innerWidth, window.innerHeight );
	player.play();

	document.body.appendChild( player.dom );

	window.addEventListener( 'resize', function () {

		player.setSize( window.innerWidth, window.innerHeight );

	} );

} );`;

		const js = new MagicString(modulejs);

		const hasRectAreaLight = true;
		const editable = true;

		if (hasRectAreaLight) {
			js.prependRight(33, `import { RectAreaLightUniformsLib } from 'three/addons/lights/RectAreaLightUniformsLib.js';\r\n\t\t\t`);
			js.prependRight(116, `RectAreaLightUniformsLib.init();\r\n\r\n\t\t\t`);
		}

		let button;

		if (editable) {

			button = new MagicString(`

\t\t\tlet button = document.createElement( 'a' );
button.href = 'https://threejs.org/editor/#file=' + location.href.split( '/' ).slice( 0, - 1 ).join( '/' ) + '/app.json';
button.style.cssText = 'position: absolute; bottom: 20px; right: 20px; padding: 10px 16px; color: #fff; border: 1px solid #fff; border-radius: 20px; text-decoration: none;';
button.target = '_blank';
button.textContent = 'EDIT';
document.body.appendChild( button );\t\t\t
`);

		}

		if (button) {
			js.append(button.toString());
		}

		console.log(js.toString());

		html.prependRight(626, js.indent().indent().indent().toString());
		console.log(html.toString());
	</script>
</body>

</html>


var loader = new THREE.FileLoader();
loader.load( 'app.json', function ( text ) {
Expand Down