diff --git a/README.md b/README.md index 6afa2342..9fa2cf09 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,7 @@ Supported Languages: 中文 / [繁體中文](README-tw.md) / [English](README-en 4. `Web.config`中增加`.json`的`MIME-Type`,避免去掉`.*`和`.`的`MIME-Type`后,由于部分iis缺少`.json`的`MIME-Type`导致整个后端报500错误。 5. 禁用资源、上传、备份目录的执行权限。 6. 修复添加不缩放文字,点击关闭按钮无法关闭窗口的bug。 +7. 添加三维文字。(支持英文、汉字) ## v0.4.0更新【[更新日志](docs-dev/update/UpdateLog.md)】 @@ -106,14 +107,7 @@ net start MongoDB 注意:发布网站部署,Web目录外面需要多加一层文件夹,用于存放日志、数据库备份等不能公开的资源。 -6. 为了保存各种类型文件能正常下载,会在iis上添加以下两个MIME类型,正式部署请注意安全。 - -| 文件扩展名 | MIME类型 | 说明 | -| --------- | -------- | ---- | -| .* | application/octet-stream | 各种格式后缀文件 | -| . | application/octet-stream | 无后缀文件 | - -7. 编译文档,请安装gitbook。 +6. 编译文档,请安装gitbook。 ```bash npm install -g gitbook-cli diff --git a/ShadowEditor.Web/locales/zh-CN.json b/ShadowEditor.Web/locales/zh-CN.json index 25129ccb..ed1e7087 100644 --- a/ShadowEditor.Web/locales/zh-CN.json +++ b/ShadowEditor.Web/locales/zh-CN.json @@ -427,7 +427,7 @@ "Label": "标签", "Darker": "变暗", "DefaultCamera": "默认相机", - "Sone Words": "一些文字", + "Some Words": "一些文字", "Body": "身体", "Pie Chart": "饼状图", "Gamma Input": "γ输入", @@ -974,7 +974,7 @@ ".ttc to .ttf": ".ttc转.ttf", "Convert successfully!": "转换成功!", "Unscaled Text": "不缩放文字", - "3D Text": "3D文字", + "3D Text": "三维文字", "Basic Geometry": "基本几何体", "Curve": "曲线", "Mark": "标注", @@ -988,6 +988,5 @@ "Only font file (.ttf) is allowed to upload.": "只允许上传字体文件(.ttf)。", "The file is already existed.": "文件已经存在。", "Create Time": "创建时间", - "Pleast upload typeface first.": "请先上传字体。", - "Message": "消息" + "Pleast upload typeface first.": "请先上传字体。" } \ No newline at end of file diff --git a/ShadowEditor.Web/src/editor/menu/ObjectMenu.jsx b/ShadowEditor.Web/src/editor/menu/ObjectMenu.jsx index c1ca8f84..e1b23666 100644 --- a/ShadowEditor.Web/src/editor/menu/ObjectMenu.jsx +++ b/ShadowEditor.Web/src/editor/menu/ObjectMenu.jsx @@ -207,7 +207,7 @@ class ObjectMenu extends React.Component { handleAddUnscaledText() { app.prompt({ title: _t('Please input'), - value: _t('Sone Words'), + value: _t('Some Words'), onOK: (value) => { app.editor.execute(new AddObjectCommand(new UnscaledText(value))); } diff --git a/ShadowEditor.Web/src/editor/menu/window/Add3DTextWindow.jsx b/ShadowEditor.Web/src/editor/menu/window/Add3DTextWindow.jsx index 37ba9319..bd6d49ed 100644 --- a/ShadowEditor.Web/src/editor/menu/window/Add3DTextWindow.jsx +++ b/ShadowEditor.Web/src/editor/menu/window/Add3DTextWindow.jsx @@ -2,6 +2,7 @@ import './css/Add3DTextWindow.css'; import { Window, Content, Buttons, Form, FormControl, Label, Input, Button, CheckBox, Select } from '../../../third_party'; import ThreeDText from '../../../object/text/ThreeDText'; import AddObjectCommand from '../../../command/AddObjectCommand'; +import TypefaceUtils from '../../../utils/TypefaceUtils'; /** * 添加3D文字窗口 @@ -17,11 +18,11 @@ class Add3DTextWindow extends React.Component { text: _t('Some Words'), fonts: {}, // 所有字体 font: '', // 字体 - size: 20, // 尺寸 - height: 24, // 厚度 + size: 16, // 尺寸 + height: 4, // 厚度 bevelEnabled: true, // 倒角 - bevelSize: 2, // 倒角尺寸 - bevelThickness: 2 // 倒角厚度 + bevelSize: 0.5, // 倒角尺寸 + bevelThickness: 0.5 // 倒角厚度 }; this.handleChange = this.handleChange.bind(this); @@ -131,7 +132,8 @@ class Add3DTextWindow extends React.Component { }); this.setState({ - fonts + fonts, + font: this.fonts[0].ID }); }); }); @@ -146,14 +148,28 @@ class Add3DTextWindow extends React.Component { handleSave() { const { text, font, size, height, bevelEnabled, bevelSize, bevelThickness } = this.state; - app.editor.execute(new AddObjectCommand(new ThreeDText(text, { - font, - size, - height, - bevelEnabled, - bevelSize, - bevelThickness - }))); + if (font === '') { + app.toast(_t('Pleast upload typeface first.'), 'warn'); + return; + } + + const fontData = this.fonts.filter(n => n.ID === font)[0]; + + fetch(`${app.options.server}${fontData.Url}`).then(response => { + response.arrayBuffer().then(buffer => { + TypefaceUtils.convertTtfToJson(buffer, false, text).then(obj => { + app.editor.execute(new AddObjectCommand(new ThreeDText(text, { + font: new THREE.Font(JSON.parse(obj.result)), + size, + height, + bevelEnabled, + bevelSize, + bevelThickness + }))); + this.handleClose(); + }); + }); + }); } handleClose() { diff --git a/ShadowEditor.Web/src/object/text/ThreeDText.js b/ShadowEditor.Web/src/object/text/ThreeDText.js index f27c742a..8e6d7d20 100644 --- a/ShadowEditor.Web/src/object/text/ThreeDText.js +++ b/ShadowEditor.Web/src/object/text/ThreeDText.js @@ -1,105 +1,16 @@ -import UnscaledTextVertexShader from './shader/unscaled_text_vertex.glsl'; -import UnscaledTextFragmentShader from './shader/unscaled_text_fragment.glsl'; -import CanvasUtils from '../../utils/CanvasUtils'; - -let ID = -1; - /** * 3D文字 */ class ThreeDText extends THREE.Mesh { - constructor(text = '') { - const canvas = document.createElement('canvas'); - - let geometry = new THREE.PlaneBufferGeometry(); - let material = new THREE.ShaderMaterial({ - vertexShader: UnscaledTextVertexShader, - fragmentShader: UnscaledTextFragmentShader, - uniforms: { - tDiffuse: { - value: new THREE.CanvasTexture(canvas) - }, - width: { - value: 1.0 // canvas width - }, - height: { - value: 1.0 // canvas height - }, - domWidth: { - value: 1422.0 // dom width - }, - domHeight: { - value: 715.0 // dom height - } - }, - transparent: true + constructor(text = '', options) { + const geometry = new THREE.TextBufferGeometry(text, options); + const material = new THREE.MeshPhongMaterial({ + color: 0xffffff }); - super(geometry, material); - this.userData.type = 'text'; - this.setText(text); - - app.on(`resize.${this.constructor.name}${ID--}`, this.onResize.bind(this)); - } - - setText(text) { - let fontSize = 16; - let padding = 4; - this.name = text; - this.userData.text = text; - - // 设置样式并计算文字宽度和高度 - let map = this.material.uniforms.tDiffuse.value; - let canvas = map.image; - let context = canvas.getContext('2d'); - - context.font = `${fontSize}px "Microsoft YaHei"`; - - const width = context.measureText(text).width; - const width2 = CanvasUtils.makePowerOfTwo(width + padding * 2); - const height2 = CanvasUtils.makePowerOfTwo(fontSize + padding * 2); - - canvas.width = width2; - canvas.height = height2; - - const domWidth = app.editor.renderer.domElement.width; - const domHeight = app.editor.renderer.domElement.height; - - this.material.uniforms.width.value = width2; - this.material.uniforms.height.value = height2; - this.material.uniforms.domWidth.value = domWidth; - this.material.uniforms.domHeight.value = domHeight; - - // 设置样式并绘制文字 - context = canvas.getContext('2d'); - - context.imageSmoothingQuality = 'high'; - context.textBaseline = 'middle'; - context.textAlign = 'center'; - context.lineWidth = 2; - - let halfWidth = width2 / 2; - let halfHeight = height2 / 2; - - // 画描边 - context.font = `${fontSize}px "Microsoft YaHei"`; - context.strokeStyle = '#000'; - context.strokeText(text, halfWidth, halfHeight); - - // 画文字 - context.fillStyle = '#fff'; - context.fillText(text, halfWidth, halfHeight); - - // 更新贴图 - map.needsUpdate = true; - } - - onResize() { - const { width, height } = app.editor.renderer.domElement; - this.material.uniforms.domWidth.value = width; - this.material.uniforms.domHeight.value = height; + this.userData.type = '3dtext'; } }