Merge pull request #1020 from HifiExperiments/alignment

Text Entity alignment property
This commit is contained in:
Kalila 2021-02-13 01:28:41 -05:00 committed by GitHub
commit 26894b4325
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 233 additions and 49 deletions

View file

@ -109,6 +109,7 @@ void TextEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointe
_effect = entity->getTextEffect();
_effectColor = toGlm(entity->getTextEffectColor());
_effectThickness = entity->getTextEffectThickness();
_alignment = entity->getAlignment();
updateTextRenderItem();
}
@ -324,7 +325,7 @@ void entities::TextPayload::render(RenderArgs* args) {
glm::vec2 bounds = glm::vec2(dimensions.x - (textRenderable->_leftMargin + textRenderable->_rightMargin), dimensions.y - (textRenderable->_topMargin + textRenderable->_bottomMargin));
textRenderer->draw(batch, textRenderable->_leftMargin / scale, -textRenderable->_topMargin / scale, bounds / scale, scale,
textRenderable->_text, textRenderable->_font, textColor, effectColor, textRenderable->_effectThickness, textRenderable->_effect,
textRenderable->_unlit, forward);
textRenderable->_alignment, textRenderable->_unlit, forward);
}
namespace render {

View file

@ -65,6 +65,7 @@ private:
glm::vec3 _dimensions;
QString _font { "" };
TextAlignment _alignment { TextAlignment::LEFT };
TextEffect _effect { TextEffect::NO_EFFECT };
glm::vec3 _effectColor { 0 };
float _effectThickness { 0.0f };

View file

@ -309,7 +309,6 @@ void EntityItemProperties::setScreenshareFromString(const QString& mode) {
}
}
inline void addTextEffect(QHash<QString, TextEffect>& lookup, TextEffect effect) { lookup[TextEffectHelpers::getNameForTextEffect(effect)] = effect; }
const QHash<QString, TextEffect> stringToTextEffectLookup = [] {
QHash<QString, TextEffect> toReturn;
@ -328,6 +327,23 @@ void EntityItemProperties::setTextEffectFromString(const QString& effect) {
}
}
inline void addTextAlignment(QHash<QString, TextAlignment>& lookup, TextAlignment alignment) { lookup[TextAlignmentHelpers::getNameForTextAlignment(alignment)] = alignment; }
const QHash<QString, TextAlignment> stringToTextAlignmentLookup = [] {
QHash<QString, TextAlignment> toReturn;
addTextAlignment(toReturn, TextAlignment::LEFT);
addTextAlignment(toReturn, TextAlignment::CENTER);
addTextAlignment(toReturn, TextAlignment::RIGHT);
return toReturn;
}();
QString EntityItemProperties::getAlignmentAsString() const { return TextAlignmentHelpers::getNameForTextAlignment(_alignment); }
void EntityItemProperties::setAlignmentFromString(const QString& alignment) {
auto textAlignmentItr = stringToTextAlignmentLookup.find(alignment.toLower());
if (textAlignmentItr != stringToTextAlignmentLookup.end()) {
_alignment = textAlignmentItr.value();
_alignmentChanged = true;
}
}
QString getCollisionGroupAsString(uint16_t group) {
switch (group) {
case USER_COLLISION_GROUP_DYNAMIC:
@ -564,6 +580,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
CHECK_PROPERTY_CHANGE(PROP_TEXT_EFFECT, textEffect);
CHECK_PROPERTY_CHANGE(PROP_TEXT_EFFECT_COLOR, textEffectColor);
CHECK_PROPERTY_CHANGE(PROP_TEXT_EFFECT_THICKNESS, textEffectThickness);
CHECK_PROPERTY_CHANGE(PROP_TEXT_ALIGNMENT, alignment);
// Zone
changedProperties += _keyLight.getChangedProperties();
@ -1339,6 +1356,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
* @property {Entities.TextEffect} textEffect="none" - The effect that is applied to the text.
* @property {Color} textEffectColor=255,255,255 - The color of the effect.
* @property {number} textEffectThickness=0.2 - The magnitude of the text effect, range <code>0.0</code> &ndash; <code>0.5</code>.
* @property {Entities.TextAlignment} alignment="left" - How the text is aligned against its background.
* @property {boolean} faceCamera - <code>true</code> if <code>billboardMode</code> is <code>"yaw"</code>, <code>false</code>
* if it isn't. Setting this property to <code>false</code> sets the <code>billboardMode</code> to <code>"none"</code>.
* <p class="important">Deprecated: This property is deprecated and will be removed.</p>
@ -1791,6 +1809,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_TEXT_EFFECT, textEffect, getTextEffectAsString());
COPY_PROPERTY_TO_QSCRIPTVALUE_TYPED(PROP_TEXT_EFFECT_COLOR, textEffectColor, u8vec3Color);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_TEXT_EFFECT_THICKNESS, textEffectThickness);
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_TEXT_ALIGNMENT, alignment, getAlignmentAsString());
}
// Zones only
@ -2175,6 +2194,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool
COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(textEffect, TextEffect);
COPY_PROPERTY_FROM_QSCRIPTVALUE(textEffectColor, u8vec3Color, setTextEffectColor);
COPY_PROPERTY_FROM_QSCRIPTVALUE(textEffectThickness, float, setTextEffectThickness);
COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(alignment, Alignment);
// Zone
_keyLight.copyFromScriptValue(object, _defaultSettings);
@ -2469,6 +2489,7 @@ void EntityItemProperties::merge(const EntityItemProperties& other) {
COPY_PROPERTY_IF_CHANGED(textEffect);
COPY_PROPERTY_IF_CHANGED(textEffectColor);
COPY_PROPERTY_IF_CHANGED(textEffectThickness);
COPY_PROPERTY_IF_CHANGED(alignment);
// Zone
_keyLight.merge(other._keyLight);
@ -2838,6 +2859,7 @@ bool EntityItemProperties::getPropertyInfo(const QString& propertyName, EntityPr
ADD_PROPERTY_TO_MAP(PROP_TEXT_EFFECT, TextEffect, textEffect, TextEffect);
ADD_PROPERTY_TO_MAP(PROP_TEXT_EFFECT_COLOR, TextEffectColor, textEffectColor, u8vec3Color);
ADD_PROPERTY_TO_MAP_WITH_RANGE(PROP_TEXT_EFFECT_THICKNESS, TextEffectThickness, textEffectThickness, float, 0.0, 0.5);
ADD_PROPERTY_TO_MAP(PROP_TEXT_ALIGNMENT, Alignment, alignment, TextAlignment);
// Zone
{ // Keylight
@ -3280,6 +3302,7 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy
APPEND_ENTITY_PROPERTY(PROP_TEXT_EFFECT, (uint32_t)properties.getTextEffect());
APPEND_ENTITY_PROPERTY(PROP_TEXT_EFFECT_COLOR, properties.getTextEffectColor());
APPEND_ENTITY_PROPERTY(PROP_TEXT_EFFECT_THICKNESS, properties.getTextEffectThickness());
APPEND_ENTITY_PROPERTY(PROP_TEXT_ALIGNMENT, (uint32_t)properties.getAlignment());
}
if (properties.getType() == EntityTypes::Zone) {
@ -3767,6 +3790,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_TEXT_EFFECT, TextEffect, setTextEffect);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_TEXT_EFFECT_COLOR, u8vec3Color, setTextEffectColor);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_TEXT_EFFECT_THICKNESS, float, setTextEffectThickness);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_TEXT_ALIGNMENT, TextAlignment, setAlignment);
}
if (properties.getType() == EntityTypes::Zone) {
@ -4168,6 +4192,7 @@ void EntityItemProperties::markAllChanged() {
_textEffectChanged = true;
_textEffectColorChanged = true;
_textEffectThicknessChanged = true;
_alignmentChanged = true;
// Zone
_keyLight.markAllChanged();
@ -4784,6 +4809,9 @@ QList<QString> EntityItemProperties::listChangedProperties() {
if (textEffectThicknessChanged()) {
out += "textEffectThickness";
}
if (alignmentChanged()) {
out += "alignment";
}
// Zone
getKeyLight().listChangedProperties(out);

View file

@ -67,6 +67,7 @@
#include "WebInputMode.h"
#include "GizmoType.h"
#include "TextEffect.h"
#include "TextAlignment.h"
const quint64 UNKNOWN_CREATED_TIME = 0;
@ -328,6 +329,7 @@ public:
DEFINE_PROPERTY_REF_ENUM(PROP_TEXT_EFFECT, TextEffect, textEffect, TextEffect, TextEffect::NO_EFFECT);
DEFINE_PROPERTY_REF(PROP_TEXT_EFFECT_COLOR, TextEffectColor, textEffectColor, u8vec3Color, TextEntityItem::DEFAULT_TEXT_COLOR);
DEFINE_PROPERTY(PROP_TEXT_EFFECT_THICKNESS, TextEffectThickness, textEffectThickness, float, TextEntityItem::DEFAULT_TEXT_EFFECT_THICKNESS);
DEFINE_PROPERTY_REF_ENUM(PROP_TEXT_ALIGNMENT, Alignment, alignment, TextAlignment, TextAlignment::LEFT);
// Zone
DEFINE_PROPERTY_GROUP(KeyLight, keyLight, KeyLightPropertyGroup);

View file

@ -253,6 +253,7 @@ enum EntityPropertyList {
PROP_TEXT_EFFECT = PROP_DERIVED_12,
PROP_TEXT_EFFECT_COLOR = PROP_DERIVED_13,
PROP_TEXT_EFFECT_THICKNESS = PROP_DERIVED_14,
PROP_TEXT_ALIGNMENT = PROP_DERIVED_15,
// Zone
// Keylight

View file

@ -69,6 +69,7 @@ EntityItemProperties TextEntityItem::getProperties(const EntityPropertyFlags& de
COPY_ENTITY_PROPERTY_TO_PROPERTIES(textEffect, getTextEffect);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(textEffectColor, getTextEffectColor);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(textEffectThickness, getTextEffectThickness);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(alignment, getAlignment);
return properties;
}
@ -96,7 +97,8 @@ bool TextEntityItem::setSubClassProperties(const EntityItemProperties& propertie
SET_ENTITY_PROPERTY_FROM_PROPERTIES(textEffect, setTextEffect);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(textEffectColor, setTextEffectColor);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(textEffectThickness, setTextEffectThickness);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(alignment, setAlignment);
return somethingChanged;
}
@ -131,6 +133,7 @@ int TextEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data,
READ_ENTITY_PROPERTY(PROP_TEXT_EFFECT, TextEffect, setTextEffect);
READ_ENTITY_PROPERTY(PROP_TEXT_EFFECT_COLOR, glm::u8vec3, setTextEffectColor);
READ_ENTITY_PROPERTY(PROP_TEXT_EFFECT_THICKNESS, float, setTextEffectThickness);
READ_ENTITY_PROPERTY(PROP_TEXT_ALIGNMENT, TextAlignment, setAlignment);
return bytesRead;
}
@ -155,6 +158,7 @@ EntityPropertyFlags TextEntityItem::getEntityProperties(EncodeBitstreamParams& p
requestedProperties += PROP_TEXT_EFFECT;
requestedProperties += PROP_TEXT_EFFECT_COLOR;
requestedProperties += PROP_TEXT_EFFECT_THICKNESS;
requestedProperties += PROP_TEXT_ALIGNMENT;
return requestedProperties;
}
@ -189,6 +193,7 @@ void TextEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBits
APPEND_ENTITY_PROPERTY(PROP_TEXT_EFFECT, (uint32_t)getTextEffect());
APPEND_ENTITY_PROPERTY(PROP_TEXT_EFFECT_COLOR, getTextEffectColor());
APPEND_ENTITY_PROPERTY(PROP_TEXT_EFFECT_THICKNESS, getTextEffectThickness());
APPEND_ENTITY_PROPERTY(PROP_TEXT_ALIGNMENT, (uint32_t)getAlignment());
}
void TextEntityItem::setText(const QString& value) {
@ -388,8 +393,21 @@ float TextEntityItem::getTextEffectThickness() const {
});
}
void TextEntityItem::setAlignment(TextAlignment value) {
withWriteLock([&] {
_needsRenderUpdate |= _alignment != value;
_alignment = value;
});
}
TextAlignment TextEntityItem::getAlignment() const {
return resultWithReadLock<TextAlignment>([&] {
return _alignment;
});
}
PulsePropertyGroup TextEntityItem::getPulseProperties() const {
return resultWithReadLock<PulsePropertyGroup>([&] {
return _pulseProperties;
});
}
}

View file

@ -15,7 +15,6 @@
#include "EntityItem.h"
#include "PulsePropertyGroup.h"
#include "TextEffect.h"
class TextEntityItem : public EntityItem {
public:
@ -100,6 +99,9 @@ public:
float getTextEffectThickness() const;
void setTextEffectThickness(float value);
TextAlignment getAlignment() const;
void setAlignment(TextAlignment value);
PulsePropertyGroup getPulseProperties() const;
private:
@ -117,6 +119,7 @@ private:
bool _unlit;
QString _font;
TextAlignment _alignment;
TextEffect _effect;
glm::u8vec3 _effectColor;
float _effectThickness;

View file

@ -286,6 +286,7 @@ enum class EntityVersion : PacketVersion {
UseOriginalPivot,
UserAgent,
AllBillboardMode,
TextAlignment,
// Add new versions above here
NUM_PACKET_TYPE,

View file

@ -41,6 +41,7 @@
#include "PulseMode.h"
#include "GizmoType.h"
#include "TextEffect.h"
#include "TextAlignment.h"
#include "OctreeConstants.h"
#include "OctreeElement.h"
@ -278,6 +279,7 @@ public:
static int unpackDataFromBytes(const unsigned char* dataBytes, PulseMode& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); }
static int unpackDataFromBytes(const unsigned char* dataBytes, GizmoType& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); }
static int unpackDataFromBytes(const unsigned char* dataBytes, TextEffect& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); }
static int unpackDataFromBytes(const unsigned char* dataBytes, TextAlignment& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); }
static int unpackDataFromBytes(const unsigned char* dataBytes, glm::vec2& result);
static int unpackDataFromBytes(const unsigned char* dataBytes, glm::vec3& result);
static int unpackDataFromBytes(const unsigned char* dataBytes, glm::u8vec3& result);

View file

@ -43,18 +43,18 @@ float TextRenderer3D::getFontSize() const {
void TextRenderer3D::draw(gpu::Batch& batch, float x, float y, const glm::vec2& bounds,
const QString& str, const glm::vec4& color, bool unlit, bool forward) {
if (_font) {
_font->drawString(batch, _drawInfo, str, color, glm::vec3(0.0f), 0, TextEffect::NO_EFFECT, { x, y }, bounds, 1.0f, unlit, forward);
_font->drawString(batch, _drawInfo, str, color, glm::vec3(0.0f), 0, TextEffect::NO_EFFECT, TextAlignment::LEFT, { x, y }, bounds, 1.0f, unlit, forward);
}
}
void TextRenderer3D::draw(gpu::Batch& batch, float x, float y, const glm::vec2& bounds, float scale,
const QString& str, const QString& font, const glm::vec4& color, const glm::vec3& effectColor,
float effectThickness, TextEffect effect, bool unlit, bool forward) {
float effectThickness, TextEffect effect, TextAlignment alignment, bool unlit, bool forward) {
if (font != _family) {
_family = font;
_font = Font::load(_family);
}
if (_font) {
_font->drawString(batch, _drawInfo, str, color, effectColor, effectThickness, effect, { x, y }, bounds, scale, unlit, forward);
_font->drawString(batch, _drawInfo, str, color, effectColor, effectThickness, effect, alignment, { x, y }, bounds, scale, unlit, forward);
}
}

View file

@ -17,6 +17,7 @@
#include "text/Font.h"
#include "TextEffect.h"
#include "TextAlignment.h"
#include "FontFamilies.h"
class TextRenderer3D {
@ -30,7 +31,7 @@ public:
const QString& str, const glm::vec4& color, bool unlit, bool forward);
void draw(gpu::Batch& batch, float x, float y, const glm::vec2& bounds, float scale,
const QString& str, const QString& font, const glm::vec4& color, const glm::vec3& effectColor,
float effectThickness, TextEffect effect, bool unlit, bool forward);
float effectThickness, TextEffect effect, TextAlignment alignment, bool unlit, bool forward);
private:
TextRenderer3D(const char* family);

View file

@ -65,7 +65,6 @@ struct QuadBuilder {
vertices[3] = TextureVertex(min + size,
texMin + glm::vec2(texSize.x, 0.0f), bounds);
}
};
Font::Pointer Font::load(QIODevice& fontFile) {
@ -303,7 +302,18 @@ void Font::setupGPU() {
}
}
void Font::buildVertices(Font::DrawInfo& drawInfo, const QString& str, const glm::vec2& origin, const glm::vec2& bounds, float scale, bool enlargeForShadows) {
inline QuadBuilder adjustedQuadBuilderForAlignmentMode(const Glyph& glyph, glm::vec2 advance, float scale, float enlargeForShadows,
TextAlignment alignment, float rightSpacing) {
if (alignment == TextAlignment::RIGHT) {
advance.x += rightSpacing;
} else if (alignment == TextAlignment::CENTER) {
advance.x += 0.5f * rightSpacing;
}
return QuadBuilder(glyph, advance, scale, enlargeForShadows);
}
void Font::buildVertices(Font::DrawInfo& drawInfo, const QString& str, const glm::vec2& origin, const glm::vec2& bounds, float scale, bool enlargeForShadows,
TextAlignment alignment) {
drawInfo.verticesBuffer = std::make_shared<gpu::Buffer>();
drawInfo.indicesBuffer = std::make_shared<gpu::Buffer>();
drawInfo.indexCount = 0;
@ -314,15 +324,17 @@ void Font::buildVertices(Font::DrawInfo& drawInfo, const QString& str, const glm
drawInfo.origin = origin;
float enlargedBoundsX = bounds.x - 0.5f * DOUBLE_MAX_OFFSET_PIXELS * float(enlargeForShadows);
float rightEdge = origin.x + enlargedBoundsX;
// Top left of text
glm::vec2 advance = origin;
std::vector<std::pair<Glyph, vec2>> glyphsAndCorners;
foreach(const QString& token, tokenizeForWrapping(str)) {
bool isNewLine = (token == QString('\n'));
bool forceNewLine = false;
// Handle wrapping
if (!isNewLine && (bounds.x != -1) && (advance.x + computeExtent(token).x > origin.x + enlargedBoundsX)) {
if (!isNewLine && (bounds.x != -1) && (advance.x + computeExtent(token).x > rightEdge)) {
// We are out of the x bound, force new line
forceNewLine = true;
}
@ -347,38 +359,8 @@ void Font::buildVertices(Font::DrawInfo& drawInfo, const QString& str, const glm
if (!isNewLine) {
for (auto c : token) {
auto glyph = _glyphs[c];
quint16 verticesOffset = numVertices;
QuadBuilder qd(glyph, advance - glm::vec2(0.0f, _ascent), scale, enlargeForShadows);
drawInfo.verticesBuffer->append(qd);
numVertices += VERTICES_PER_QUAD;
// Sam's recommended triangle slices
// Triangle tri1 = { v0, v1, v3 };
// Triangle tri2 = { v1, v2, v3 };
// NOTE: Random guy on the internet's recommended triangle slices
// Triangle tri1 = { v0, v1, v2 };
// Triangle tri2 = { v2, v3, v0 };
// The problem here being that the 4 vertices are { ll, lr, ul, ur }, a Z pattern
// Additionally, you want to ensure that the shared side vertices are used sequentially
// to improve cache locality
//
// 2 -- 3
// | |
// | |
// 0 -- 1
//
// { 0, 1, 2 } -> { 2, 1, 3 }
quint16 indices[NUMBER_OF_INDICES_PER_QUAD];
indices[0] = verticesOffset + 0;
indices[1] = verticesOffset + 1;
indices[2] = verticesOffset + 2;
indices[3] = verticesOffset + 2;
indices[4] = verticesOffset + 1;
indices[5] = verticesOffset + 3;
drawInfo.indicesBuffer->append(sizeof(indices), (const gpu::Byte*)indices);
drawInfo.indexCount += NUMBER_OF_INDICES_PER_QUAD;
glyphsAndCorners.emplace_back(glyph, advance - glm::vec2(0.0f, _ascent));
// Advance by glyph size
advance.x += glyph.d;
@ -388,10 +370,71 @@ void Font::buildVertices(Font::DrawInfo& drawInfo, const QString& str, const glm
advance.x += _spaceWidth;
}
}
std::vector<QuadBuilder> quadBuilders;
quadBuilders.reserve(glyphsAndCorners.size());
{
int i = glyphsAndCorners.size() - 1;
while (i >= 0) {
auto nextGlyphAndCorner = glyphsAndCorners[i];
float rightSpacing = rightEdge - (nextGlyphAndCorner.second.x + nextGlyphAndCorner.first.d);
quadBuilders.push_back(adjustedQuadBuilderForAlignmentMode(nextGlyphAndCorner.first, nextGlyphAndCorner.second, scale, enlargeForShadows,
alignment, rightSpacing));
i--;
while (i >= 0) {
auto prevGlyphAndCorner = glyphsAndCorners[i];
// We're to the right of the last character we checked, which means we're on a previous line, so we need to
// recalculate the spacing, so we exit this loop
if (prevGlyphAndCorner.second.x >= nextGlyphAndCorner.second.x) {
break;
}
quadBuilders.push_back(adjustedQuadBuilderForAlignmentMode(prevGlyphAndCorner.first, prevGlyphAndCorner.second, scale, enlargeForShadows,
alignment, rightSpacing));
nextGlyphAndCorner = prevGlyphAndCorner;
i--;
}
}
}
// The quadBuilders is backwards now because we looped over the glyphs backwards to adjust their alignment
for (int i = quadBuilders.size() - 1; i >= 0; i--) {
quint16 verticesOffset = numVertices;
drawInfo.verticesBuffer->append(quadBuilders[i]);
numVertices += VERTICES_PER_QUAD;
// Sam's recommended triangle slices
// Triangle tri1 = { v0, v1, v3 };
// Triangle tri2 = { v1, v2, v3 };
// NOTE: Random guy on the internet's recommended triangle slices
// Triangle tri1 = { v0, v1, v2 };
// Triangle tri2 = { v2, v3, v0 };
// The problem here being that the 4 vertices are { ll, lr, ul, ur }, a Z pattern
// Additionally, you want to ensure that the shared side vertices are used sequentially
// to improve cache locality
//
// 2 -- 3
// | |
// | |
// 0 -- 1
//
// { 0, 1, 2 } -> { 2, 1, 3 }
quint16 indices[NUMBER_OF_INDICES_PER_QUAD];
indices[0] = verticesOffset + 0;
indices[1] = verticesOffset + 1;
indices[2] = verticesOffset + 2;
indices[3] = verticesOffset + 2;
indices[4] = verticesOffset + 1;
indices[5] = verticesOffset + 3;
drawInfo.indicesBuffer->append(sizeof(indices), (const gpu::Byte*)indices);
drawInfo.indexCount += NUMBER_OF_INDICES_PER_QUAD;
}
}
void Font::drawString(gpu::Batch& batch, Font::DrawInfo& drawInfo, const QString& str, const glm::vec4& color,
const glm::vec3& effectColor, float effectThickness, TextEffect effect,
const glm::vec3& effectColor, float effectThickness, TextEffect effect, TextAlignment alignment,
const glm::vec2& origin, const glm::vec2& bounds, float scale, bool unlit, bool forward) {
if (!_loaded || str == "") {
return;
@ -401,11 +444,12 @@ void Font::drawString(gpu::Batch& batch, Font::DrawInfo& drawInfo, const QString
const int SHADOW_EFFECT = (int)TextEffect::SHADOW_EFFECT;
// If we're switching to or from shadow effect mode, we need to rebuild the vertices
if (str != drawInfo.string || bounds != drawInfo.bounds || origin != drawInfo.origin ||
if (str != drawInfo.string || bounds != drawInfo.bounds || origin != drawInfo.origin || alignment != _alignment ||
(drawInfo.params.effect != textEffect && (textEffect == SHADOW_EFFECT || drawInfo.params.effect == SHADOW_EFFECT)) ||
(textEffect == SHADOW_EFFECT && scale != _scale)) {
_scale = scale;
buildVertices(drawInfo, str, origin, bounds, scale, textEffect == SHADOW_EFFECT);
_alignment = alignment;
buildVertices(drawInfo, str, origin, bounds, scale, textEffect == SHADOW_EFFECT, alignment);
}
setupGPU();

View file

@ -14,6 +14,7 @@
#include "Glyph.h"
#include "TextEffect.h"
#include "TextAlignment.h"
#include <gpu/Batch.h>
#include <gpu/Pipeline.h>
@ -58,7 +59,7 @@ public:
// Render string to batch
void drawString(gpu::Batch& batch, DrawInfo& drawInfo, const QString& str, const glm::vec4& color,
const glm::vec3& effectColor, float effectThickness, TextEffect effect,
const glm::vec3& effectColor, float effectThickness, TextEffect effect, TextAlignment alignment,
const glm::vec2& origin, const glm::vec2& bound, float scale, bool unlit, bool forward);
static Pointer load(const QString& family);
@ -76,7 +77,8 @@ private:
glm::vec2 computeTokenExtent(const QString& str) const;
const Glyph& getGlyph(const QChar& c) const;
void buildVertices(DrawInfo& drawInfo, const QString& str, const glm::vec2& origin, const glm::vec2& bounds, float scale, bool enlargeForShadows);
void buildVertices(DrawInfo& drawInfo, const QString& str, const glm::vec2& origin, const glm::vec2& bounds, float scale, bool enlargeForShadows,
TextAlignment alignment);
void setupGPU();
@ -96,6 +98,7 @@ private:
float _spaceWidth { 0.0f };
float _scale { 0.0f };
TextAlignment _alignment;
bool _loaded { true };

View file

@ -0,0 +1,25 @@
//
// Created by HifiExperiments on 2/9/21
// Copyright 2021 Vircadia contributors.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "TextAlignment.h"
const char* textAlignmentNames[] = {
"left",
"center",
"right"
};
static const size_t TEXT_ALIGNMENT_NAMES = (sizeof(textAlignmentNames) / sizeof(textAlignmentNames[0]));
QString TextAlignmentHelpers::getNameForTextAlignment(TextAlignment alignment) {
if (((int)alignment <= 0) || ((int)alignment >= (int)TEXT_ALIGNMENT_NAMES)) {
alignment = (TextAlignment)0;
}
return textAlignmentNames[(int)alignment];
}

View file

@ -0,0 +1,40 @@
//
// Created by HifiExperiments on 2/9/21
// Copyright 2021 Vircadia contributors.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_TextAlignment_h
#define hifi_TextAlignment_h
#include "QString"
/**jsdoc
* <p>A {@link Entities.EntityProperties-Text|Text} entity may use one of the following alignments:</p>
* <table>
* <thead>
* <tr><th>Value</th><th>Description</th></tr>
* </thead>
* <tbody>
* <tr><td><code>"left"</code></td><td>Text is aligned to the left side.</td></tr>
* <tr><td><code>"center"</code></td><td>Text is centered.</td></tr>
* <tr><td><code>"right"</code></td><td>Text is aligned to the right side.</td></tr>
* </tbody>
* </table>
* @typedef {string} Entities.TextAlignment
*/
enum class TextAlignment {
LEFT = 0,
CENTER,
RIGHT
};
class TextAlignmentHelpers {
public:
static QString getNameForTextAlignment(TextAlignment alignment);
};
#endif // hifi_TextAlignment_h

View file

@ -20,7 +20,7 @@
* <tbody>
* <tr><td><code>"none"</code></td><td>No effect.</td></tr>
* <tr><td><code>"outline"</code></td><td>An outline effect.</td></tr>
* <tr><td><code>"outlineFill"</code></td><td>An outline effect, with fill.</td></tr>
* <tr><td><code>"outline fill"</code></td><td>An outline effect, with fill.</td></tr>
* <tr><td><code>"shadow"</code></td><td>A shadow effect.</td></tr>
* </tbody>
* </table>

View file

@ -38,6 +38,9 @@
"textEffectThickness": {
"tooltip": "The magnitude of the text effect."
},
"textAlignment": {
"tooltip": "How the text is aligned within its left and right bounds."
},
"topMargin": {
"tooltip": "The top margin, in meters."
},

View file

@ -239,6 +239,17 @@ const GROUPS = [
decimals: 2,
propertyID: "textEffectThickness",
},
{
label: "Alignment",
type: "dropdown",
options: {
left: "Left",
center: "Center",
right: "Right"
},
propertyID: "textAlignment",
propertyName: "alignment", // actual entity property name
},
{
label: "Top Margin",
type: "number-draggable",