Skip to content
Snippets Groups Projects
Commit af8cf066 authored by Alexander Rose's avatar Alexander Rose
Browse files

text tether

parent 6c957f1e
No related branches found
No related tags found
No related merge requests found
......@@ -32,12 +32,18 @@ export namespace TextBuilder {
const tcoords = ChunkedArray.create(Float32Array, 2, chunkSize, text ? text.tcoordBuffer.ref.value : initialCount);
const p = { ...PD.getDefaultValues(Text.Params), ...props }
const { attachment, background, backgroundMargin } = p
const { attachment, background, backgroundMargin, tether, tetherLength, tetherBaseWidth } = p
const fontAtlas = getFontAtlas(p)
const margin = (1 / 2.5) * backgroundMargin
const outline = fontAtlas.buffer / fontAtlas.lineHeight
const add = (x: number, y: number, z: number, depth: number, group: number) => {
ChunkedArray.add3(centers, x, y, z);
ChunkedArray.add(depths, depth);
ChunkedArray.add(groups, group);
}
return {
add: (str: string, x: number, y: number, z: number, depth: number, group: number) => {
let bWidth = 0
......@@ -53,6 +59,7 @@ export namespace TextBuilder {
// attachment
let yShift: number, xShift: number
// vertical
if (attachment.startsWith('top')) {
yShift = bHeight
} else if (attachment.startsWith('middle')) {
......@@ -60,6 +67,7 @@ export namespace TextBuilder {
} else {
yShift = 0 // "bottom"
}
// horizontal
if (attachment.endsWith('right')) {
xShift = bWidth
} else if (attachment.endsWith('center')) {
......@@ -68,24 +76,152 @@ export namespace TextBuilder {
xShift = 0 // "left"
}
if (tether) {
switch (attachment) {
case 'bottom-left':
xShift -= tetherLength / 2 + margin + 0.1
yShift -= tetherLength / 2 + margin
break
case 'bottom-center':
yShift -= tetherLength + margin
break
case 'bottom-right':
xShift += tetherLength / 2 + margin + 0.1
yShift -= tetherLength / 2 + margin
break
case 'middle-left':
xShift -= tetherLength + margin + 0.1
break
case 'middle-center':
break
case 'middle-right':
xShift += tetherLength + margin + 0.1
break
case 'top-left':
xShift -= tetherLength / 2 + margin + 0.1
yShift += tetherLength / 2 + margin
break
case 'top-center':
yShift += tetherLength + margin
break
case 'top-right':
xShift += tetherLength / 2 + margin + 0.1
yShift += tetherLength / 2 + margin
break
}
}
const xLeft = -xShift - margin - 0.1
const xRight = bWidth - xShift + margin + 0.1
const yTop = bHeight - yShift + margin
const yBottom = -yShift - margin
// background
if (background) {
ChunkedArray.add2(mappings, -xShift - margin - 0.1, bHeight - yShift + margin) // top left
ChunkedArray.add2(mappings, -xShift - margin - 0.1, -yShift - margin) // bottom left
ChunkedArray.add2(mappings, bWidth - xShift + margin + 0.1, bHeight - yShift + margin) // top right
ChunkedArray.add2(mappings, bWidth - xShift + margin + 0.1, -yShift - margin) // bottom right
ChunkedArray.add2(mappings, xLeft, yTop) // top left
ChunkedArray.add2(mappings, xLeft, yBottom) // bottom left
ChunkedArray.add2(mappings, xRight, yTop) // top right
ChunkedArray.add2(mappings, xRight, yBottom) // bottom right
const offset = centers.elementCount
for (let i = 0; i < 4; ++i) {
ChunkedArray.add2(tcoords, 10, 10)
ChunkedArray.add3(centers, x, y, z);
ChunkedArray.add(depths, depth);
ChunkedArray.add(groups, group);
add(x, y, z, depth, group)
}
ChunkedArray.add3(indices, offset + quadIndices[0], offset + quadIndices[1], offset + quadIndices[2])
ChunkedArray.add3(indices, offset + quadIndices[3], offset + quadIndices[4], offset + quadIndices[5])
}
if (tether) {
let xTip: number, yTip: number, xBaseA: number, yBaseA: number, xBaseB: number, yBaseB: number
switch (attachment) {
case 'bottom-left':
xTip = xLeft - tetherLength / 2
xBaseA = xLeft + tetherBaseWidth / 2
xBaseB = xLeft
yTip = yBottom - tetherLength / 2
yBaseA = yBottom
yBaseB = yBottom + tetherBaseWidth / 2
break
case 'bottom-center':
xTip = 0
xBaseA = tetherBaseWidth / 2
xBaseB = -tetherBaseWidth / 2
yTip = yBottom - tetherLength
yBaseA = yBottom
yBaseB = yBottom
break
case 'bottom-right':
xTip = xRight + tetherLength / 2
xBaseA = xRight
xBaseB = xRight - tetherBaseWidth / 2
yTip = yBottom - tetherLength / 2
yBaseA = yBottom + tetherBaseWidth / 2
yBaseB = yBottom
break
case 'middle-left':
xTip = xLeft - tetherLength
xBaseA = xLeft
xBaseB = xLeft
yTip = 0
yBaseA = -tetherBaseWidth / 2
yBaseB = tetherBaseWidth / 2
break
case 'middle-center':
xTip = 0
xBaseA = 0
xBaseB = 0
yTip = 0
yBaseA = 0
yBaseB = 0
break
case 'middle-right':
xTip = xRight + tetherLength
xBaseA = xRight
xBaseB = xRight - tetherBaseWidth / 2
yTip = 0
yBaseA = tetherBaseWidth / 2
yBaseB = -tetherBaseWidth / 2
break
case 'top-left':
xTip = xLeft - tetherLength / 2
xBaseA = xLeft + tetherBaseWidth / 2
xBaseB = xLeft
yTip = yTop + tetherLength / 2
yBaseA = yTop
yBaseB = yTop - tetherBaseWidth / 2
break
case 'top-center':
xTip = 0
xBaseA = tetherBaseWidth / 2
xBaseB = -tetherBaseWidth / 2
yTip = yTop + tetherLength
yBaseA = yTop
yBaseB = yTop
break
case 'top-right':
xTip = xRight + tetherLength / 2
xBaseA = xRight
xBaseB = xRight - tetherBaseWidth / 2
yTip = yTop + tetherLength / 2
yBaseA = yTop - tetherBaseWidth / 2
yBaseB = yTop
break
default:
throw new Error('unsupported attachment')
}
ChunkedArray.add2(mappings, xTip, yTip) // tip
ChunkedArray.add2(mappings, xBaseA, yBaseA) // base A
ChunkedArray.add2(mappings, xBaseB, yBaseB) // base B
const offset = centers.elementCount
for (let i = 0; i < 3; ++i) {
ChunkedArray.add2(tcoords, 10, 10)
add(x, y, z, depth, group)
}
ChunkedArray.add3(indices, offset, offset + 1, offset + 2)
}
xShift += outline
yShift += outline
let xadvance = 0
......@@ -109,11 +245,7 @@ export namespace TextBuilder {
xadvance += c.nw - 2 * outline
const offset = centers.elementCount
for (let i = 0; i < 4; ++i) {
ChunkedArray.add3(centers, x, y, z);
ChunkedArray.add(depths, depth);
ChunkedArray.add(groups, group);
}
for (let i = 0; i < 4; ++i) add(x, y, z, depth, group)
ChunkedArray.add3(indices, offset + quadIndices[0], offset + quadIndices[1], offset + quadIndices[2])
ChunkedArray.add3(indices, offset + quadIndices[3], offset + quadIndices[4], offset + quadIndices[5])
}
......
......@@ -91,6 +91,9 @@ export namespace Text {
backgroundMargin: PD.Numeric(0.2, { min: 0, max: 1, step: 0.01 }),
backgroundColor: PD.Color(ColorNames.grey),
backgroundOpacity: PD.Numeric(1, { min: 0, max: 1, step: 0.01 }),
tether: PD.Boolean(false),
tetherLength: PD.Numeric(1, { min: 0, max: 5, step: 0.1 }),
tetherBaseWidth: PD.Numeric(0.3, { min: 0, max: 1, step: 0.01 }),
attachment: PD.Select('middle-center', [
['bottom-left', 'bottom-left'], ['bottom-center', 'bottom-center'], ['bottom-right', 'bottom-right'],
......
......@@ -30,19 +30,21 @@ canvas3d.animate()
function textRepr() {
const props: PD.Values<Text.Params> = {
...PD.getDefaultValues(Text.Params),
attachment: 'middle-center',
attachment: 'top-right',
fontQuality: 3,
fontWeight: 'normal',
borderWidth: 0.3,
background: true
background: true,
tether: true,
tetherLength: 0.5,
}
const textBuilder = TextBuilder.create(props, 1, 1)
textBuilder.add('Hello world', 0, 0, 0, 0, 0)
textBuilder.add('Добрый день', 0, 1, 0, 0, 0)
textBuilder.add('美好的一天', 0, 2, 0, 0, 0)
textBuilder.add('¿Cómo estás?', 0, -1, 0, 0, 0)
textBuilder.add('αβγ Å', 0, -2, 0, 0, 0)
textBuilder.add('Hello world', 0, 0, 0, 1, 0)
// textBuilder.add('Добрый день', 0, 1, 0, 0, 0)
// textBuilder.add('美好的一天', 0, 2, 0, 0, 0)
// textBuilder.add('¿Cómo estás?', 0, -1, 0, 0, 0)
// textBuilder.add('αβγ Å', 0, -2, 0, 0, 0)
const text = textBuilder.getText()
const values = Text.Utils.createValuesSimple(text, props, Color(0xFFDD00), 1)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment