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

TextGeometry changes and support in editor #27931

Open
wants to merge 11 commits into
base: dev
Choose a base branch
from
245 changes: 244 additions & 1 deletion build/three.cjs

Large diffs are not rendered by default.

246 changes: 244 additions & 2 deletions build/three.module.js

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion build/three.module.min.js

Large diffs are not rendered by default.

41 changes: 41 additions & 0 deletions editor/js/Menubar.Add.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import * as THREE from 'three';

import { FontLoader } from 'three/addons/loaders/FontLoader.js';
import { TextGeometry } from 'three/addons/geometries/TextGeometry.js';

import { UIPanel, UIRow, UIHorizontalRule } from './libs/ui.js';

import { AddObjectCommand } from './commands/AddObjectCommand.js';
Expand Down Expand Up @@ -248,6 +251,44 @@ function MenubarAdd( editor ) {
} );
options.add( option );

// Text

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

const loader = new FontLoader();
loader.load( '../examples/fonts/helvetiker_bold.typeface.json', function ( font ) {

const text = 'THREE.JS';

const geometry = new TextGeometry( text, {
text: text,
font,
size: 70,
depth: 20,
curveSegments: 4,

bevelEnabled: false,
bevelThickness: 10,
bevelSize: 8,
bevelOffset: 0,
bevelSegments: 3,
scale: 0.01

} );

const mesh = new THREE.Mesh( geometry, new THREE.MeshStandardMaterial() );
mesh.name = 'Text';

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

} );

} );
options.add( option );

// Torus

option = new UIRow();
Expand Down
150 changes: 150 additions & 0 deletions editor/js/Sidebar.Geometry.TextGeometry.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
import { TextGeometry } from 'three/addons/geometries/TextGeometry.js';

import { UIDiv, UIRow, UIText, UINumber, UIInteger, UIInput, UICheckbox } from './libs/ui.js';

import { SetGeometryCommand } from './commands/SetGeometryCommand.js';

function GeometryParametersPanel( editor, object ) {

const strings = editor.strings;

const container = new UIDiv();

const geometry = object.geometry;
const parameters = geometry.parameters.options;

// text

const textRow = new UIRow();
const text = new UIInput().setValue( parameters.text ).onChange( update );

textRow.add( new UIText( strings.getKey( 'sidebar/geometry/text_geometry/text' ) ).setClass( 'Label' ) );
textRow.add( text );

container.add( textRow );

// size

const sizeRow = new UIRow();
const size = new UINumber().setPrecision( 3 ).setValue( parameters.size ).onChange( update );

sizeRow.add( new UIText( strings.getKey( 'sidebar/geometry/text_geometry/size' ) ).setClass( 'Label' ) );
sizeRow.add( size );

container.add( sizeRow );

// depth

const depthRow = new UIRow();
const depth = new UINumber().setPrecision( 3 ).setValue( parameters.depth ).onChange( update );

depthRow.add( new UIText( strings.getKey( 'sidebar/geometry/text_geometry/depth' ) ).setClass( 'Label' ) );
depthRow.add( depth );

container.add( depthRow );

// curveSegments

const curveSegmentsRow = new UIRow();
const curveSegments = new UIInteger( parameters.curveSegments ).setRange( 1, Infinity ).onChange( update );

curveSegmentsRow.add( new UIText( strings.getKey( 'sidebar/geometry/text_geometry/curveseg' ) ).setClass( 'Label' ) );
curveSegmentsRow.add( curveSegments );

container.add( curveSegmentsRow );


// scale

const scaleRow = new UIRow();
const scale = new UINumber().setPrecision( 4 ).setValue( parameters.scale ).onChange( update );

scaleRow.add( new UIText( strings.getKey( 'sidebar/geometry/text_geometry/scale' ) ).setClass( 'Label' ) );
scaleRow.add( scale );

container.add( scaleRow );

// bevelEnabled

const bevelEnabledRow = new UIRow();
const bevelEnabled = new UICheckbox( parameters.bevelEnabled ).onChange( update );

bevelEnabledRow.add( new UIText( strings.getKey( 'sidebar/geometry/text_geometry/bevelenabled' ) ).setClass( 'Label' ) );
bevelEnabledRow.add( bevelEnabled );

container.add( bevelEnabledRow );

// bevelThickness

const bevelThicknessRow = new UIRow();
const bevelThickness = new UINumber( parameters.bevelThickness ).setPrecision( 3 ).setRange( 0, Infinity ).onChange( update );

bevelThicknessRow.add( new UIText( strings.getKey( 'sidebar/geometry/text_geometry/bevelthickness' ) ).setClass( 'Label' ) );
bevelThicknessRow.add( bevelThickness );

container.add( bevelThicknessRow );

// bevelSize

const bevelSizeRow = new UIRow();
const bevelSize = new UINumber( parameters.bevelSize ).setRange( 0, Infinity ).onChange( update );

bevelSizeRow.add( new UIText( strings.getKey( 'sidebar/geometry/text_geometry/bevelsize' ) ).setClass( 'Label' ) );
bevelSizeRow.add( bevelSize );

container.add( bevelSizeRow );

// bevelOffset

const bevelOffsetRow = new UIRow();
const bevelOffset = new UINumber( parameters.bevelOffset ).setRange( 0, Infinity ).onChange( update );

bevelOffsetRow.add( new UIText( strings.getKey( 'sidebar/geometry/text_geometry/bevelOffset' ) ).setClass( 'Label' ) );
bevelOffsetRow.add( bevelOffset );

container.add( bevelOffsetRow );


// bevelSegments

const bevelSegmentsRow = new UIRow();
const bevelSegments = new UIInteger( parameters.bevelSegments ).setRange( 0, Infinity ).onChange( update );

bevelSegmentsRow.add( new UIText( strings.getKey( 'sidebar/geometry/text_geometry/bevelseg' ) ).setClass( 'Label' ) );
bevelSegmentsRow.add( bevelSegments );

container.add( bevelSegmentsRow );

function update() {

const options = {

text: text.getValue(),
font: parameters.font,

size: size.getValue(),
depth: depth.getValue(),
curveSegments: curveSegments.getValue(),

bevelEnabled: bevelEnabled.getValue(),
bevelThickness: bevelThickness.getValue(),
bevelSize: bevelSize.getValue(),
bevelOffset: bevelOffset.getValue(),
bevelSegments: bevelSegments.getValue(),

scale: scale.getValue(),

};

const geometry = new TextGeometry( options.text, options );

editor.execute( new SetGeometryCommand( editor, object, geometry ) );

}

return container;

}

export { GeometryParametersPanel };

14 changes: 13 additions & 1 deletion editor/js/Strings.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ function Strings( config ) {
'menubar/add/icosahedron': 'Icosahedron',
'menubar/add/octahedron': 'Octahedron',
'menubar/add/tetrahedron': 'Tetrahedron',
'menubar/add/text': 'Text',
'menubar/add/torus': 'Torus',
'menubar/add/tube': 'Tube',
'menubar/add/torusknot': 'TorusKnot',
Expand Down Expand Up @@ -208,6 +209,17 @@ function Strings( config ) {
'sidebar/geometry/sphere_geometry/thetastart': 'Theta start',
'sidebar/geometry/sphere_geometry/thetalength': 'Theta length',

'sidebar/geometry/text_geometry/text': 'Text',
'sidebar/geometry/text_geometry/size': 'Font size',
'sidebar/geometry/text_geometry/depth': 'Extrude depth',
Fixed Show fixed Hide fixed
'sidebar/geometry/text_geometry/scale': 'Scale',
'sidebar/geometry/text_geometry/curveseg': 'Curve segments',
'sidebar/geometry/text_geometry/bevelenabled': 'Bevel enabled',
'sidebar/geometry/text_geometry/bevelthickness': 'Bevel thickness',
'sidebar/geometry/text_geometry/bevelsize': 'Bevel size',
'sidebar/geometry/text_geometry/bevelOffset': 'Bevel offset',
'sidebar/geometry/text_geometry/bevelseg': 'Bevel segments',

'sidebar/geometry/torus_geometry/radius': 'Radius',
'sidebar/geometry/torus_geometry/tube': 'Tube',
'sidebar/geometry/torus_geometry/radialsegments': 'Radial segments',
Expand Down Expand Up @@ -1059,7 +1071,7 @@ function Strings( config ) {

getKey: function ( key ) {

return values[ language ][ key ] || '???';
return values[ language ][ key ] || `???${key.split('/').pop().substring(0, 8)}`;

}

Expand Down
38 changes: 37 additions & 1 deletion examples/jsm/geometries/TextGeometry.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
* }
*/

import { Font } from '../loaders/FontLoader.js';
import {
ExtrudeGeometry
} from 'three';
Expand All @@ -35,7 +36,15 @@ class TextGeometry extends ExtrudeGeometry {

// translate parameters to ExtrudeGeometry API

parameters.depth = parameters.height !== undefined ? parameters.height : 50;
if ( parameters.depth === undefined && parameters.height !== undefined ) {
Copy link
Collaborator

@Mugen87 Mugen87 Mar 19, 2024

Choose a reason for hiding this comment

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

This PR does two things in one go. It adds support to the editor and renames the height parameter to depth.

Ideally, there is a single PR for each change since both changes are independent of each other.

Besides, if height is renamed, the example code (meaning webgl_geometry_text.html and others) should be updated in order to avoid deprecation warnings.

That said, I also favor depth since height was a confusing name for describing the thickness (or depth) of the text.

Would you be okay with moving the renaming change to a separate PR?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure I can do that. I'll wait on the confirmation of the loader.registerGeometry() api before making the changes.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

actually the change to extract is easier to do, so it's in #27949


console.warn( '.height in TextGeometry is now depreciated. Please use .depth instead' );

}

parameters.depth = parameters.depth !== undefined ?
parameters.depth : parameters.height !== undefined ?
parameters.height : 50;

// defaults

Expand All @@ -45,12 +54,39 @@ class TextGeometry extends ExtrudeGeometry {

super( shapes, parameters );

// for conversion of font to object units (ie. px -> m)

const scale = parameters.scale;

if ( scale !== undefined ) {

this.computeBoundingBox();
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why is the bounding box computed at this point? It will be automatically recomputed when calling BufferGeometry.scale()?

Copy link
Collaborator

Choose a reason for hiding this comment

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

BTW: Is the introduction of a scale parameter really necessary? Couldn't apps just use Object3D.scale instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

the reason to do it here is getting a scaled down (0.01) geometry mostly for connivence to be used in Editor.

the object.scale could be used, but I wasn't sure if it was a good idea to insert a TextGeometry at a custom object scale, hence having it in the geometry seems like a more convenient way.

Copy link
Collaborator

@Mugen87 Mugen87 Apr 10, 2024

Choose a reason for hiding this comment

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

In order to keep the parameters of TextGeometry to a minimum, it would be better to use Object3D.scale and not introduce an additional way for transforming geometry, imo.

this.scale( scale, scale, scale );

}

}

this.type = 'TextGeometry';

}

toJSON() {

const data = super.toJSON();
return data;

}

static fromJSON( data ) {

const options = data.options;

options.font = new Font( options.font.data );
return new TextGeometry( options.text, options );

}

}


Expand Down
1 change: 1 addition & 0 deletions src/geometries/Geometries.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@ export * from './TorusGeometry.js';
export * from './TorusKnotGeometry.js';
export * from './TubeGeometry.js';
export * from './WireframeGeometry.js';
export * from '../../examples/jsm/geometries/TextGeometry.js';
Mugen87 marked this conversation as resolved.
Show resolved Hide resolved