mirror of
https://github.com/overte-org/overte.git
synced 2025-04-07 23:53:54 +02:00
Merge pull request #1034 from vircadia/v2021.1.0-rc
merge V2021.1.0 rc into master
This commit is contained in:
commit
ba54dd755c
41 changed files with 441 additions and 151 deletions
|
@ -33,7 +33,6 @@ SkeletonModel::SkeletonModel(Avatar* owningAvatar, QObject* parent) :
|
|||
{
|
||||
// SkeletonModels, and by extention Avatars, use Dual Quaternion skinning.
|
||||
_useDualQuaternionSkinning = true;
|
||||
_forceOffset = true;
|
||||
|
||||
// Avatars all cast shadow
|
||||
setCanCastShadow(true);
|
||||
|
|
|
@ -368,6 +368,11 @@ bool EntityRenderer::needsRenderUpdate() const {
|
|||
return needsRenderUpdateFromEntity(_entity);
|
||||
}
|
||||
|
||||
Transform EntityRenderer::getTransformToCenterWithMaybeOnlyLocalRotation(const EntityItemPointer& entity, bool& success) const {
|
||||
return entity->getBillboardMode() == BillboardMode::NONE ? entity->getTransformToCenter(success) :
|
||||
entity->getTransformToCenterWithOnlyLocalRotation(success);
|
||||
}
|
||||
|
||||
// Returns true if the item in question needs to have updateInScene called because of changes in the entity
|
||||
bool EntityRenderer::needsRenderUpdateFromEntity(const EntityItemPointer& entity) const {
|
||||
if (entity->needsRenderUpdate()) {
|
||||
|
@ -379,12 +384,12 @@ bool EntityRenderer::needsRenderUpdateFromEntity(const EntityItemPointer& entity
|
|||
}
|
||||
|
||||
bool success = false;
|
||||
auto bound = _entity->getAABox(success);
|
||||
auto bound = entity->getAABox(success);
|
||||
if (success && _bound != bound) {
|
||||
return true;
|
||||
}
|
||||
|
||||
auto newModelTransform = _entity->getTransformToCenter(success);
|
||||
auto newModelTransform = getTransformToCenterWithMaybeOnlyLocalRotation(entity, success);
|
||||
// FIXME can we use a stale model transform here?
|
||||
if (success && newModelTransform != _modelTransform) {
|
||||
return true;
|
||||
|
@ -401,15 +406,15 @@ bool EntityRenderer::needsRenderUpdateFromEntity(const EntityItemPointer& entity
|
|||
return false;
|
||||
}
|
||||
|
||||
void EntityRenderer::updateModelTransformAndBound() {
|
||||
void EntityRenderer::updateModelTransformAndBound(const EntityItemPointer& entity) {
|
||||
bool success = false;
|
||||
auto newModelTransform = _entity->getTransformToCenter(success);
|
||||
auto newModelTransform = getTransformToCenterWithMaybeOnlyLocalRotation(entity, success);
|
||||
if (success) {
|
||||
_modelTransform = newModelTransform;
|
||||
}
|
||||
|
||||
success = false;
|
||||
auto bound = _entity->getAABox(success);
|
||||
auto bound = entity->getAABox(success);
|
||||
if (success) {
|
||||
_bound = bound;
|
||||
}
|
||||
|
@ -429,7 +434,7 @@ void EntityRenderer::doRenderUpdateSynchronous(const ScenePointer& scene, Transa
|
|||
|
||||
_prevIsTransparent = transparent;
|
||||
|
||||
updateModelTransformAndBound();
|
||||
updateModelTransformAndBound(entity);
|
||||
|
||||
_moving = entity->isMovingRelativeToParent();
|
||||
_visible = entity->getVisible();
|
||||
|
|
|
@ -101,7 +101,7 @@ protected:
|
|||
virtual void doRender(RenderArgs* args) = 0;
|
||||
|
||||
virtual bool isFading() const { return _isFading; }
|
||||
virtual void updateModelTransformAndBound();
|
||||
virtual void updateModelTransformAndBound(const EntityItemPointer& entity);
|
||||
virtual bool isTransparent() const { return _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) < 1.0f : false; }
|
||||
inline bool isValidRenderItem() const { return _renderItemID != Item::INVALID_ITEM_ID; }
|
||||
|
||||
|
@ -109,16 +109,14 @@ protected:
|
|||
virtual void setRenderLayer(RenderLayer value) { _renderLayer = value; }
|
||||
virtual void setCullWithParent(bool value) { _cullWithParent = value; }
|
||||
|
||||
signals:
|
||||
void requestRenderUpdate();
|
||||
|
||||
protected:
|
||||
template<typename T>
|
||||
std::shared_ptr<T> asTypedEntity() { return std::static_pointer_cast<T>(_entity); }
|
||||
|
||||
static void makeStatusGetters(const EntityItemPointer& entity, Item::Status::Getters& statusGetters);
|
||||
const Transform& getModelTransform() const;
|
||||
|
||||
Transform getTransformToCenterWithMaybeOnlyLocalRotation(const EntityItemPointer& entity, bool& success) const;
|
||||
|
||||
Item::Bound _bound;
|
||||
SharedSoundPointer _collisionSound;
|
||||
QUuid _changeHandlerId;
|
||||
|
@ -154,6 +152,9 @@ protected:
|
|||
const EntityItemPointer _entity;
|
||||
|
||||
QUuid _entityID;
|
||||
|
||||
signals:
|
||||
void requestRenderUpdate();
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
|
|
|
@ -115,11 +115,12 @@ bool RenderableModelEntityItem::needsUpdateModelBounds() const {
|
|||
}
|
||||
|
||||
bool success;
|
||||
auto transform = getTransform(success);
|
||||
auto transform = getBillboardMode() == BillboardMode::NONE ? getTransform(success) : getTransformWithOnlyLocalRotation(success);
|
||||
if (success) {
|
||||
if (model->getTranslation() != transform.getTranslation()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (model->getRotation() != transform.getRotation()) {
|
||||
return true;
|
||||
}
|
||||
|
@ -171,7 +172,7 @@ void RenderableModelEntityItem::updateModelBounds() {
|
|||
}
|
||||
|
||||
bool success;
|
||||
auto transform = getTransform(success);
|
||||
auto transform = getBillboardMode() == BillboardMode::NONE ? getTransform(success) : getTransformWithOnlyLocalRotation(success);
|
||||
if (success && (model->getTranslation() != transform.getTranslation() ||
|
||||
model->getRotation() != transform.getRotation())) {
|
||||
model->setTransformNoUpdateRenderItems(transform);
|
||||
|
|
|
@ -41,13 +41,13 @@ PolyLineEntityRenderer::PolyLineEntityRenderer(const EntityItemPointer& entity)
|
|||
}
|
||||
}
|
||||
|
||||
void PolyLineEntityRenderer::updateModelTransformAndBound() {
|
||||
void PolyLineEntityRenderer::updateModelTransformAndBound(const EntityItemPointer& entity) {
|
||||
bool success = false;
|
||||
auto newModelTransform = _entity->getTransformToCenter(success);
|
||||
auto newModelTransform = getTransformToCenterWithMaybeOnlyLocalRotation(entity, success);
|
||||
if (success) {
|
||||
_modelTransform = newModelTransform;
|
||||
|
||||
auto lineEntity = std::static_pointer_cast<PolyLineEntityItem>(_entity);
|
||||
auto lineEntity = std::static_pointer_cast<PolyLineEntityItem>(entity);
|
||||
AABox bound;
|
||||
lineEntity->computeTightLocalBoundingBox(bound);
|
||||
bound.transform(newModelTransform);
|
||||
|
|
|
@ -25,7 +25,7 @@ class PolyLineEntityRenderer : public TypedEntityRenderer<PolyLineEntityItem> {
|
|||
public:
|
||||
PolyLineEntityRenderer(const EntityItemPointer& entity);
|
||||
|
||||
void updateModelTransformAndBound() override;
|
||||
void updateModelTransformAndBound(const EntityItemPointer& entity) override;
|
||||
|
||||
virtual bool isTransparent() const override;
|
||||
|
||||
|
|
|
@ -1785,8 +1785,9 @@ void PolyVoxEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& s
|
|||
|
||||
void PolyVoxEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) {
|
||||
_lastVoxelToLocalMatrix = entity->voxelToLocalMatrix();
|
||||
_position = entity->getWorldPosition();
|
||||
_orientation = entity->getWorldOrientation();
|
||||
bool success;
|
||||
_position = entity->getCenterPosition(success);
|
||||
_orientation = entity->getBillboardMode() == BillboardMode::NONE ? entity->getWorldOrientation() : entity->getLocalOrientation();
|
||||
_lastVoxelVolumeSize = entity->getVoxelVolumeSize();
|
||||
_params->setSubData(0, vec4(_lastVoxelVolumeSize, 0.0));
|
||||
graphics::MeshPointer newMesh;
|
||||
|
|
|
@ -56,15 +56,12 @@ void ShapeEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
|
|||
AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this, entity] {
|
||||
withWriteLock([&] {
|
||||
_shape = entity->getShape();
|
||||
_position = entity->getWorldPosition();
|
||||
_dimensions = entity->getUnscaledDimensions(); // get unscaled to avoid scaling twice
|
||||
_orientation = entity->getWorldOrientation();
|
||||
_renderTransform = getModelTransform(); // contains parent scale, if this entity scales with its parent
|
||||
if (_shape == entity::Sphere) {
|
||||
_renderTransform.postScale(SPHERE_ENTITY_SCALE);
|
||||
}
|
||||
|
||||
_renderTransform.postScale(_dimensions);
|
||||
_renderTransform.postScale(entity->getUnscaledDimensions());
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -248,7 +245,7 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) {
|
|||
outColor = procedural->getColor(outColor);
|
||||
outColor.a *= procedural->isFading() ? Interpolate::calculateFadeRatio(procedural->getFadeStartTime()) : 1.0f;
|
||||
withReadLock([&] {
|
||||
procedural->prepare(batch, _position, _dimensions, _orientation, _created, ProceduralProgramKey(outColor.a < 1.0f));
|
||||
procedural->prepare(batch, transform.getTranslation(), transform.getScale(), transform.getRotation(), _created, ProceduralProgramKey(outColor.a < 1.0f));
|
||||
});
|
||||
|
||||
if (render::ShapeKey(args->_globalShapeKey).isWireframe() || _primitiveMode == PrimitiveMode::LINES) {
|
||||
|
|
|
@ -45,10 +45,6 @@ private:
|
|||
std::shared_ptr<graphics::ProceduralMaterial> _material { std::make_shared<graphics::ProceduralMaterial>() };
|
||||
glm::vec3 _color { NAN };
|
||||
float _alpha { NAN };
|
||||
|
||||
glm::vec3 _position;
|
||||
glm::vec3 _dimensions;
|
||||
glm::quat _orientation;
|
||||
};
|
||||
|
||||
} }
|
||||
|
|
|
@ -109,6 +109,7 @@ void TextEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointe
|
|||
_effect = entity->getTextEffect();
|
||||
_effectColor = toGlm(entity->getTextEffectColor());
|
||||
_effectThickness = entity->getTextEffectThickness();
|
||||
_alignment = entity->getAlignment();
|
||||
updateTextRenderItem();
|
||||
}
|
||||
|
||||
|
@ -292,12 +293,12 @@ void entities::TextPayload::render(RenderArgs* args) {
|
|||
}
|
||||
auto textRenderable = std::static_pointer_cast<TextEntityRenderer>(renderable);
|
||||
|
||||
Transform modelTransform;
|
||||
Transform transform;
|
||||
glm::vec3 dimensions;
|
||||
|
||||
glm::vec4 textColor;
|
||||
textRenderable->withReadLock([&] {
|
||||
modelTransform = textRenderable->_renderTransform;
|
||||
transform = textRenderable->_renderTransform;
|
||||
dimensions = textRenderable->_dimensions;
|
||||
|
||||
float fadeRatio = textRenderable->_isFading ? Interpolate::calculateFadeRatio(textRenderable->_fadeStartTime) : 1.0f;
|
||||
|
@ -313,18 +314,18 @@ void entities::TextPayload::render(RenderArgs* args) {
|
|||
return;
|
||||
}
|
||||
|
||||
modelTransform.setRotation(BillboardModeHelpers::getBillboardRotation(modelTransform.getTranslation(), modelTransform.getRotation(), textRenderable->_billboardMode,
|
||||
transform.setRotation(BillboardModeHelpers::getBillboardRotation(transform.getTranslation(), transform.getRotation(), textRenderable->_billboardMode,
|
||||
args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? BillboardModeHelpers::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition()));
|
||||
|
||||
float scale = textRenderable->_lineHeight / textRenderer->getFontSize();
|
||||
modelTransform.postTranslate(glm::vec3(-0.5, 0.5, 1.0f + EPSILON / dimensions.z));
|
||||
modelTransform.setScale(scale);
|
||||
batch.setModelTransform(modelTransform);
|
||||
transform.postTranslate(glm::vec3(-0.5, 0.5, 1.0f + EPSILON / dimensions.z));
|
||||
transform.setScale(scale);
|
||||
batch.setModelTransform(transform);
|
||||
|
||||
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 {
|
||||
|
|
|
@ -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 };
|
||||
|
|
|
@ -1620,6 +1620,19 @@ const Transform EntityItem::getTransformToCenter(bool& success) const {
|
|||
return result;
|
||||
}
|
||||
|
||||
const Transform EntityItem::getTransformToCenterWithOnlyLocalRotation(bool& success) const {
|
||||
Transform result = getTransformWithOnlyLocalRotation(success);
|
||||
glm::vec3 pivot = getPivot();
|
||||
if (pivot != ENTITY_ITEM_ZERO_VEC3) {
|
||||
result.postTranslate(pivot);
|
||||
}
|
||||
glm::vec3 registrationPoint = getRegistrationPoint();
|
||||
if (registrationPoint != ENTITY_ITEM_HALF_VEC3) { // If it is not already centered, translate to center
|
||||
result.postTranslate((ENTITY_ITEM_HALF_VEC3 - registrationPoint) * getScaledDimensions()); // Position to center
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// The maximum bounding cube for the entity, independent of it's rotation.
|
||||
/// This accounts for the registration point (upon which rotation occurs around).
|
||||
///
|
||||
|
|
|
@ -190,6 +190,7 @@ public:
|
|||
void setCenterPosition(const glm::vec3& position);
|
||||
|
||||
const Transform getTransformToCenter(bool& success) const;
|
||||
const Transform getTransformToCenterWithOnlyLocalRotation(bool& success) const;
|
||||
|
||||
void requiresRecalcBoxes();
|
||||
|
||||
|
|
|
@ -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> – <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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -218,8 +218,9 @@ EntityItemID EntityTreeElement::evalDetailedRayIntersection(const glm::vec3& ori
|
|||
// extents is the entity relative, scaled, centered extents of the entity
|
||||
glm::vec3 position = entity->getWorldPosition();
|
||||
glm::mat4 translation = glm::translate(position);
|
||||
glm::quat orientation = entity->getWorldOrientation();
|
||||
glm::mat4 rotation = glm::mat4_cast(BillboardModeHelpers::getBillboardRotation(position, orientation, entity->getBillboardMode(),
|
||||
BillboardMode billboardMode = entity->getBillboardMode();
|
||||
glm::quat orientation = billboardMode == BillboardMode::NONE ? entity->getWorldOrientation() : entity->getLocalOrientation();
|
||||
glm::mat4 rotation = glm::mat4_cast(BillboardModeHelpers::getBillboardRotation(position, orientation, billboardMode,
|
||||
viewFrustumPos, entity->getRotateForPicking()));
|
||||
glm::mat4 entityToWorldMatrix = translation * rotation;
|
||||
glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix);
|
||||
|
@ -368,8 +369,9 @@ EntityItemID EntityTreeElement::evalDetailedParabolaIntersection(const glm::vec3
|
|||
// extents is the entity relative, scaled, centered extents of the entity
|
||||
glm::vec3 position = entity->getWorldPosition();
|
||||
glm::mat4 translation = glm::translate(position);
|
||||
glm::quat orientation = entity->getWorldOrientation();
|
||||
glm::mat4 rotation = glm::mat4_cast(BillboardModeHelpers::getBillboardRotation(position, orientation, entity->getBillboardMode(),
|
||||
BillboardMode billboardMode = entity->getBillboardMode();
|
||||
glm::quat orientation = billboardMode == BillboardMode::NONE ? entity->getWorldOrientation() : entity->getLocalOrientation();
|
||||
glm::mat4 rotation = glm::mat4_cast(BillboardModeHelpers::getBillboardRotation(position, orientation, billboardMode,
|
||||
viewFrustumPos, entity->getRotateForPicking()));
|
||||
glm::mat4 entityToWorldMatrix = translation * rotation;
|
||||
glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix);
|
||||
|
|
|
@ -108,10 +108,11 @@ bool GizmoEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const
|
|||
QVariantMap& extraInfo, bool precisionPicking) const {
|
||||
glm::vec3 dimensions = getScaledDimensions();
|
||||
glm::vec2 xyDimensions(dimensions.x, dimensions.z);
|
||||
glm::quat rotation = getWorldOrientation();
|
||||
BillboardMode billboardMode = getBillboardMode();
|
||||
glm::quat rotation = billboardMode == BillboardMode::NONE ? getWorldOrientation() : getLocalOrientation();
|
||||
rotation *= glm::angleAxis(-(float)M_PI_2, Vectors::RIGHT);
|
||||
glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint()));
|
||||
rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, getBillboardMode(), viewFrustumPos);
|
||||
rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, billboardMode, viewFrustumPos);
|
||||
|
||||
if (findRayRectangleIntersection(origin, direction, rotation, position, xyDimensions, distance)) {
|
||||
glm::vec3 hitPosition = origin + (distance * direction);
|
||||
|
@ -143,10 +144,11 @@ bool GizmoEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin,
|
|||
//// Scale the dimensions by the diameter
|
||||
glm::vec3 dimensions = getScaledDimensions();
|
||||
glm::vec2 xyDimensions(dimensions.x, dimensions.z);
|
||||
glm::quat rotation = getWorldOrientation();
|
||||
BillboardMode billboardMode = getBillboardMode();
|
||||
glm::quat rotation = billboardMode == BillboardMode::NONE ? getWorldOrientation() : getLocalOrientation();
|
||||
rotation *= glm::angleAxis(-(float)M_PI_2, Vectors::RIGHT);
|
||||
glm::vec3 position = getWorldPosition();
|
||||
rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, getBillboardMode(), viewFrustumPos);
|
||||
rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, billboardMode, viewFrustumPos);
|
||||
|
||||
glm::quat inverseRot = glm::inverse(rotation);
|
||||
glm::vec3 localOrigin = inverseRot * (origin - position);
|
||||
|
|
|
@ -330,6 +330,19 @@ const Transform ModelEntityItem::getTransform(bool& success, int depth) const {
|
|||
|
||||
return worldTransform;
|
||||
}
|
||||
|
||||
const Transform ModelEntityItem::getTransformWithOnlyLocalRotation(bool& success, int depth) const {
|
||||
const Transform parentTransform = getParentTransform(success, depth);
|
||||
Transform localTransform = getLocalTransform();
|
||||
localTransform.postScale(getModelScale());
|
||||
|
||||
Transform worldTransform;
|
||||
Transform::mult(worldTransform, parentTransform, localTransform);
|
||||
worldTransform.setRotation(localTransform.getRotation());
|
||||
|
||||
return worldTransform;
|
||||
}
|
||||
|
||||
void ModelEntityItem::setCompoundShapeURL(const QString& url) {
|
||||
withWriteLock([&] {
|
||||
if (_compoundShapeURL.get() != url) {
|
||||
|
|
|
@ -71,6 +71,7 @@ public:
|
|||
virtual void setScaledDimensions(const glm::vec3& value) override;
|
||||
|
||||
virtual const Transform getTransform(bool& success, int depth = 0) const override;
|
||||
virtual const Transform getTransformWithOnlyLocalRotation(bool& success, int depth = 0) const override;
|
||||
virtual const Transform getTransform() const override;
|
||||
|
||||
static const QString DEFAULT_COMPOUND_SHAPE_URL;
|
||||
|
|
|
@ -378,14 +378,15 @@ glm::mat4 PolyVoxEntityItem::localToVoxelMatrix() const {
|
|||
}
|
||||
|
||||
glm::mat4 PolyVoxEntityItem::voxelToWorldMatrix(bool includeBillboard) const {
|
||||
glm::quat orientation = getWorldOrientation();
|
||||
glm::vec3 position = getWorldPosition();
|
||||
glm::mat4 translation = glm::translate(position);
|
||||
glm::mat4 rotation;
|
||||
if (includeBillboard) {
|
||||
rotation = glm::mat4_cast(BillboardModeHelpers::getBillboardRotation(position, orientation, getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition()));
|
||||
BillboardMode billboardMode = getBillboardMode();
|
||||
glm::quat orientation = billboardMode == BillboardMode::NONE ? getWorldOrientation() : getLocalOrientation();
|
||||
rotation = glm::mat4_cast(BillboardModeHelpers::getBillboardRotation(position, orientation, billboardMode, BillboardModeHelpers::getPrimaryViewFrustumPosition()));
|
||||
} else {
|
||||
rotation = glm::mat4_cast(orientation);
|
||||
rotation = glm::mat4_cast(getWorldOrientation());
|
||||
}
|
||||
return translation * rotation * voxelToLocalMatrix();
|
||||
}
|
||||
|
|
|
@ -277,9 +277,10 @@ bool ShapeEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const
|
|||
float& distance, BoxFace& face, glm::vec3& surfaceNormal,
|
||||
QVariantMap& extraInfo, bool precisionPicking) const {
|
||||
glm::vec3 dimensions = getScaledDimensions();
|
||||
glm::quat rotation = getWorldOrientation();
|
||||
BillboardMode billboardMode = getBillboardMode();
|
||||
glm::quat rotation = billboardMode == BillboardMode::NONE ? getWorldOrientation() : getLocalOrientation();
|
||||
glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint()));
|
||||
rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, getBillboardMode(), viewFrustumPos);
|
||||
rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, billboardMode, viewFrustumPos);
|
||||
|
||||
// determine the ray in the frame of the entity transformed from a unit sphere
|
||||
glm::mat4 entityToWorldMatrix = glm::translate(position) * glm::mat4_cast(rotation) * glm::scale(dimensions);
|
||||
|
@ -309,9 +310,10 @@ bool ShapeEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin,
|
|||
BoxFace& face, glm::vec3& surfaceNormal,
|
||||
QVariantMap& extraInfo, bool precisionPicking) const {
|
||||
glm::vec3 dimensions = getScaledDimensions();
|
||||
glm::quat rotation = getWorldOrientation();
|
||||
BillboardMode billboardMode = getBillboardMode();
|
||||
glm::quat rotation = billboardMode == BillboardMode::NONE ? getWorldOrientation() : getLocalOrientation();
|
||||
glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint()));
|
||||
rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, getBillboardMode(), viewFrustumPos);
|
||||
rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, billboardMode, viewFrustumPos);
|
||||
|
||||
// determine the parabola in the frame of the entity transformed from a unit sphere
|
||||
glm::mat4 entityToWorldMatrix = glm::translate(position) * glm::mat4_cast(rotation) * glm::scale(dimensions);
|
||||
|
|
|
@ -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;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -286,6 +286,7 @@ enum class EntityVersion : PacketVersion {
|
|||
UseOriginalPivot,
|
||||
UserAgent,
|
||||
AllBillboardMode,
|
||||
TextAlignment,
|
||||
|
||||
// Add new versions above here
|
||||
NUM_PACKET_TYPE,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -114,7 +114,8 @@ Transform Model::getTransform() const {
|
|||
return transform;
|
||||
} else if (_spatiallyNestableOverride) {
|
||||
bool success;
|
||||
Transform transform = _spatiallyNestableOverride->getTransform(success);
|
||||
Transform transform = _billboardMode == BillboardMode::NONE ? _spatiallyNestableOverride->getTransform(success) :
|
||||
_spatiallyNestableOverride->getTransformWithOnlyLocalRotation(success);
|
||||
if (success) {
|
||||
transform.setScale(getScale());
|
||||
return transform;
|
||||
|
@ -151,6 +152,7 @@ void Model::setOffset(const glm::vec3& offset) {
|
|||
// if someone manually sets our offset, then we are no longer snapped to center
|
||||
_snapModelToRegistrationPoint = false;
|
||||
_snappedToRegistrationPoint = false;
|
||||
_forceOffset = true;
|
||||
}
|
||||
|
||||
void Model::calculateTextureInfo() {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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 };
|
||||
|
||||
|
|
|
@ -754,6 +754,17 @@ const Transform SpatiallyNestable::getTransform(bool& success, int depth) const
|
|||
return result;
|
||||
}
|
||||
|
||||
const Transform SpatiallyNestable::getTransformWithOnlyLocalRotation(bool& success, int depth) const {
|
||||
Transform result;
|
||||
// return a world-space transform for this object's location
|
||||
Transform parentTransform = getParentTransform(success, depth);
|
||||
_transformLock.withReadLock([&] {
|
||||
Transform::mult(result, parentTransform, _transform);
|
||||
result.setRotation(_transform.getRotation());
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
const Transform SpatiallyNestable::getTransform() const {
|
||||
bool success;
|
||||
Transform result = getTransform(success);
|
||||
|
|
|
@ -82,6 +82,7 @@ public:
|
|||
|
||||
// world frame
|
||||
virtual const Transform getTransform(bool& success, int depth = 0) const;
|
||||
virtual const Transform getTransformWithOnlyLocalRotation(bool& success, int depth = 0) const;
|
||||
virtual const Transform getTransform() const;
|
||||
virtual void setTransform(const Transform& transform, bool& success);
|
||||
virtual bool setTransform(const Transform& transform);
|
||||
|
|
25
libraries/shared/src/TextAlignment.cpp
Normal file
25
libraries/shared/src/TextAlignment.cpp
Normal 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];
|
||||
}
|
40
libraries/shared/src/TextAlignment.h
Normal file
40
libraries/shared/src/TextAlignment.h
Normal 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
|
|
@ -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>
|
||||
|
|
|
@ -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."
|
||||
},
|
||||
|
|
|
@ -25,9 +25,10 @@
|
|||
</head>
|
||||
<body onload='loaded();' id="entity-list-body">
|
||||
<div id="entity-list-menubar">
|
||||
<input type="button" class="normal" id="selection" value="Select▾" />
|
||||
<input type="button" class="normal" id="actions" value="Edit▾" />
|
||||
<input type="button" class="normal" id="tools" value="Tools▾" />
|
||||
<input type="button" class="entity-list-menutitle" id="actions" value="Edit▾" />
|
||||
<input type="button" class="entity-list-menutitle" id="selection" value="Select▾" />
|
||||
<input type="button" class="entity-list-menutitle" id="transform" value="Transform▾" />
|
||||
<input type="button" class="entity-list-menutitle" id="tools" value="Tools▾" />
|
||||
</div>
|
||||
<div id="entity-list-header">
|
||||
<input type="button" class="glyph" id="refresh" value="F" />
|
||||
|
@ -146,35 +147,22 @@
|
|||
</div>
|
||||
</button>
|
||||
<div class="menu-separator"></div>
|
||||
<button class="menu-button" id="moveEntitySelectionToAvatar" >
|
||||
<button class="menu-button" id="exportSelectedEntities" >
|
||||
<div class = "menu-item">
|
||||
<div class = "menu-item-caption">Move Selected Entities to Avatar</div>
|
||||
<div class = "menu-item-caption">Export Selected Entities</div>
|
||||
<div class = "menu-item-shortcut"></div>
|
||||
</div>
|
||||
</button>
|
||||
<div class="menu-separator"></div>
|
||||
<button class="menu-button" id="rotateAsTheNextClickedSurface" >
|
||||
<button class="menu-button" id="importEntitiesFromFile" >
|
||||
<div class = "menu-item">
|
||||
<div class = "menu-item-caption">Snap To Next Clicked Surface</div>
|
||||
<div class = "menu-item-shortcut">0</div>
|
||||
<div class = "menu-item-caption">Import Entities (.json) From a File</div>
|
||||
<div class = "menu-item-shortcut"></div>
|
||||
</div>
|
||||
</button>
|
||||
<button class="menu-button" id="quickRotate90x" >
|
||||
<button class="menu-button" id="importEntitiesFromUrl" >
|
||||
<div class = "menu-item">
|
||||
<div class = "menu-item-caption">Rotate 90° on X axis</div>
|
||||
<div class = "menu-item-shortcut">7</div>
|
||||
</div>
|
||||
</button>
|
||||
<button class="menu-button" id="quickRotate90y" >
|
||||
<div class = "menu-item">
|
||||
<div class = "menu-item-caption">Rotate 90° on Y axis</div>
|
||||
<div class = "menu-item-shortcut">8</div>
|
||||
</div>
|
||||
</button>
|
||||
<button class="menu-button" id="quickRotate90z" >
|
||||
<div class = "menu-item">
|
||||
<div class = "menu-item-caption">Rotate 90° on Z axis</div>
|
||||
<div class = "menu-item-shortcut">9</div>
|
||||
<div class = "menu-item-caption">Import Entities (.json) From a URL</div>
|
||||
<div class = "menu-item-shortcut"></div>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
|
@ -242,6 +230,40 @@
|
|||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<div class="entity-list-menu" id="transform-menu" >
|
||||
<button class="menu-button" id="moveEntitySelectionToAvatar" >
|
||||
<div class = "menu-item">
|
||||
<div class = "menu-item-caption">Move Selected Entities to Avatar</div>
|
||||
<div class = "menu-item-shortcut"></div>
|
||||
</div>
|
||||
</button>
|
||||
<div class="menu-separator"></div>
|
||||
<button class="menu-button" id="rotateAsTheNextClickedSurface" >
|
||||
<div class = "menu-item">
|
||||
<div class = "menu-item-caption">Snap To Next Clicked Surface</div>
|
||||
<div class = "menu-item-shortcut">0</div>
|
||||
</div>
|
||||
</button>
|
||||
<div class="menu-separator"></div>
|
||||
<button class="menu-button" id="quickRotate90x" >
|
||||
<div class = "menu-item">
|
||||
<div class = "menu-item-caption">Rotate 90° on X axis</div>
|
||||
<div class = "menu-item-shortcut">7</div>
|
||||
</div>
|
||||
</button>
|
||||
<button class="menu-button" id="quickRotate90y" >
|
||||
<div class = "menu-item">
|
||||
<div class = "menu-item-caption">Rotate 90° on Y axis</div>
|
||||
<div class = "menu-item-shortcut">8</div>
|
||||
</div>
|
||||
</button>
|
||||
<button class="menu-button" id="quickRotate90z" >
|
||||
<div class = "menu-item">
|
||||
<div class = "menu-item-caption">Rotate 90° on Z axis</div>
|
||||
<div class = "menu-item-shortcut">9</div>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<div class="entity-list-menu" id="tools-menu" >
|
||||
<button class="menu-button" id="setCameraFocusToSelection" >
|
||||
<div class = "menu-item">
|
||||
|
@ -261,25 +283,6 @@
|
|||
<div class = "menu-item-caption">Toggle Local/World Mode</div>
|
||||
<div class = "menu-item-shortcut">T</div>
|
||||
</div>
|
||||
</button>
|
||||
<div class="menu-separator"></div>
|
||||
<button class="menu-button" id="exportSelectedEntities" >
|
||||
<div class = "menu-item">
|
||||
<div class = "menu-item-caption">Export Selected Entities</div>
|
||||
<div class = "menu-item-shortcut"></div>
|
||||
</div>
|
||||
</button>
|
||||
<button class="menu-button" id="importEntitiesFromFile" >
|
||||
<div class = "menu-item">
|
||||
<div class = "menu-item-caption">Import Entities (.json) From a File</div>
|
||||
<div class = "menu-item-shortcut"></div>
|
||||
</div>
|
||||
</button>
|
||||
<button class="menu-button" id="importEntitiesFromUrl" >
|
||||
<div class = "menu-item">
|
||||
<div class = "menu-item-caption">Import Entities (.json) From a URL</div>
|
||||
<div class = "menu-item-shortcut"></div>
|
||||
</div>
|
||||
</button>
|
||||
<div class="menu-separator"></div>
|
||||
<button class="menu-button" id="gridActivator" >
|
||||
|
|
|
@ -155,7 +155,15 @@ const COLUMNS = {
|
|||
propertyID: "lastEdited",
|
||||
initialWidth: 0.38,
|
||||
defaultSortOrder: DESCENDING_SORT,
|
||||
},
|
||||
},
|
||||
urlWithPath: {
|
||||
columnHeader: "URL",
|
||||
dropdownLabel: "URL",
|
||||
propertyID: "urlWithPath",
|
||||
initialWidth: 0.54,
|
||||
initiallyShown: false,
|
||||
defaultSortOrder: ASCENDING_SORT,
|
||||
},
|
||||
};
|
||||
|
||||
const FILTER_TYPES = [
|
||||
|
@ -226,9 +234,10 @@ let elEntityTable,
|
|||
elToggleVisible,
|
||||
elActionsMenu,
|
||||
elSelectionMenu,
|
||||
elToolsMenu,
|
||||
elTransformMenu,
|
||||
elToolsMenu,
|
||||
elMenuBackgroundOverlay,
|
||||
elHmdMultiSelect,
|
||||
elHmdMultiSelect,
|
||||
elHmdCopy,
|
||||
elHmdCut,
|
||||
elHmdPaste,
|
||||
|
@ -313,6 +322,7 @@ function loaded() {
|
|||
elHmdMultiSelect = document.getElementById("hmdmultiselect");
|
||||
elActionsMenu = document.getElementById("actions");
|
||||
elSelectionMenu = document.getElementById("selection");
|
||||
elTransformMenu = document.getElementById("transform");
|
||||
elToolsMenu = document.getElementById("tools");
|
||||
elMenuBackgroundOverlay = document.getElementById("menuBackgroundOverlay");
|
||||
elHmdCopy = document.getElementById("hmdcopy");
|
||||
|
@ -395,6 +405,10 @@ function loaded() {
|
|||
document.getElementById("menuBackgroundOverlay").style.display = "block";
|
||||
document.getElementById("selection-menu").style.display = "block";
|
||||
};
|
||||
elTransformMenu.onclick = function() {
|
||||
document.getElementById("menuBackgroundOverlay").style.display = "block";
|
||||
document.getElementById("transform-menu").style.display = "block";
|
||||
};
|
||||
elToolsMenu.onclick = function() {
|
||||
document.getElementById("menuBackgroundOverlay").style.display = "block";
|
||||
document.getElementById("tools-menu").style.display = "block";
|
||||
|
@ -919,7 +933,7 @@ function loaded() {
|
|||
entityIds: selection,
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
function updateEntityData(entityData) {
|
||||
entities = [];
|
||||
entitiesByID = {};
|
||||
|
@ -929,13 +943,14 @@ function loaded() {
|
|||
entityData.forEach(function(entity) {
|
||||
let type = entity.type;
|
||||
let filename = getFilename(entity.url);
|
||||
|
||||
|
||||
let entityData = {
|
||||
id: entity.id,
|
||||
name: entity.name,
|
||||
type: type,
|
||||
url: entity.certificateID === "" ? filename : "<i>" + CERTIFIED_PLACEHOLDER + "</i>",
|
||||
fullUrl: entity.certificateID === "" ? filename : CERTIFIED_PLACEHOLDER,
|
||||
urlWithPath: entity.certificateID === "" ? entity.url : "<i>" + CERTIFIED_PLACEHOLDER + "</i>",
|
||||
locked: entity.locked,
|
||||
visible: entity.visible,
|
||||
certificateID: entity.certificateID,
|
||||
|
@ -975,11 +990,13 @@ function loaded() {
|
|||
let searchFilter = searchTerm === '' || (e.name.toLowerCase().indexOf(searchTerm) > -1 ||
|
||||
e.type.toLowerCase().indexOf(searchTerm) > -1 ||
|
||||
e.fullUrl.toLowerCase().indexOf(searchTerm) > -1 ||
|
||||
(e.urlWithPath.toLowerCase().indexOf(searchTerm) > -1 &&
|
||||
columnsByID["urlWithPath"].elTh.style.visibility === "visible") ||
|
||||
e.id.toLowerCase().indexOf(searchTerm) > -1);
|
||||
return typeFilter && searchFilter;
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
PROFILE("sort", function() {
|
||||
let isAscendingSort = currentSortOrder === ASCENDING_SORT;
|
||||
let isDefaultSort = currentSortOrder === COLUMNS[currentSortColumnID].defaultSortOrder;
|
||||
|
@ -1850,6 +1867,7 @@ function loaded() {
|
|||
document.getElementById("menuBackgroundOverlay").style.display = "none";
|
||||
document.getElementById("selection-menu").style.display = "none";
|
||||
document.getElementById("actions-menu").style.display = "none";
|
||||
document.getElementById("transform-menu").style.display = "none";
|
||||
document.getElementById("tools-menu").style.display = "none";
|
||||
}
|
||||
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -1364,10 +1364,46 @@ div#grid-section, body#entity-list-body {
|
|||
}
|
||||
#entity-list-menubar {
|
||||
margin: 0px -8px 6px -8px;
|
||||
padding: 0px 8px 0px 8px;
|
||||
padding: 0px 9px 0px 9px;
|
||||
border: none;
|
||||
background-color: #000;
|
||||
background: linear-gradient(#343434 20%, #000 100%);
|
||||
background: linear-gradient(#343434 30%, #000 100%);
|
||||
}
|
||||
input[type=button].entity-list-menutitle {
|
||||
font-family: FiraSans-SemiBold;
|
||||
font-size: 15px;
|
||||
text-transform: none;
|
||||
vertical-align: top;
|
||||
height: 28px;
|
||||
min-width: 30px;
|
||||
padding: 0px 8px;
|
||||
margin-right: 6px;
|
||||
border-radius: 5px;
|
||||
border: none;
|
||||
color: #fff;
|
||||
background-color: #000;
|
||||
background: linear-gradient(#343434 30%, #000 100%);
|
||||
cursor: pointer;
|
||||
}
|
||||
input[type=button].entity-list-menutitle:enabled:hover {
|
||||
background: linear-gradient(#000, #000);
|
||||
border: none;
|
||||
}
|
||||
input[type=button].entity-list-menutitle:active {
|
||||
background: linear-gradient(#343434, #343434);
|
||||
}
|
||||
input[type=button].entity-list-menutitle:disabled {
|
||||
color: #252525;
|
||||
background: linear-gradient(#575757 30%, #252525 100%);
|
||||
}
|
||||
input[type=button].entity-list-menutitle[pressed=pressed] {
|
||||
color: #00b4ef;
|
||||
}
|
||||
input[type=button].entity-list-menutitle:focus {
|
||||
outline: none;
|
||||
color: #000000;
|
||||
background: linear-gradient(#c0c0c0, #c0c0c0);
|
||||
border-radius: 5px 5px 0px 0px;
|
||||
}
|
||||
.icon-input-radius input {
|
||||
position: relative;
|
||||
|
|
Loading…
Reference in a new issue