mirror of
https://github.com/overte-org/overte.git
synced 2025-04-08 04:34:38 +02:00
Merge pull request #13227 from SamGondelman/entityMirror
Add local-only isVisibleInSecondaryCamera flag to entities
This commit is contained in:
commit
08fcad1932
18 changed files with 88 additions and 21 deletions
|
@ -54,9 +54,7 @@ namespace render {
|
|||
}
|
||||
|
||||
// always visible in primary view. if isVisibleInSecondaryCamera, also draw in secondary view
|
||||
uint32_t viewTagBits = render::hifi::TAG_MAIN_VIEW |
|
||||
(overlay->getIsVisibleInSecondaryCamera() ? render::hifi::TAG_SECONDARY_VIEW : render::hifi::TAG_NONE);
|
||||
|
||||
render::hifi::Tag viewTagBits = overlay->getIsVisibleInSecondaryCamera() ? render::hifi::TAG_ALL_VIEWS : render::hifi::TAG_MAIN_VIEW;
|
||||
builder.withTagBits(viewTagBits);
|
||||
|
||||
return builder.build();
|
||||
|
|
|
@ -157,16 +157,20 @@ Item::Bound EntityRenderer::getBound() {
|
|||
return _bound;
|
||||
}
|
||||
|
||||
render::hifi::Tag EntityRenderer::getTagMask() const {
|
||||
return _isVisibleInSecondaryCamera ? render::hifi::TAG_ALL_VIEWS : render::hifi::TAG_MAIN_VIEW;
|
||||
}
|
||||
|
||||
ItemKey EntityRenderer::getKey() {
|
||||
if (isTransparent()) {
|
||||
return ItemKey::Builder::transparentShape().withTypeMeta().withTagBits(render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1);
|
||||
return ItemKey::Builder::transparentShape().withTypeMeta().withTagBits(getTagMask());
|
||||
}
|
||||
|
||||
// This allows shapes to cast shadows
|
||||
if (_canCastShadow) {
|
||||
return ItemKey::Builder::opaqueShape().withTypeMeta().withTagBits(render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1).withShadowCaster();
|
||||
return ItemKey::Builder::opaqueShape().withTypeMeta().withTagBits(getTagMask()).withShadowCaster();
|
||||
} else {
|
||||
return ItemKey::Builder::opaqueShape().withTypeMeta().withTagBits(render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1);
|
||||
return ItemKey::Builder::opaqueShape().withTypeMeta().withTagBits(getTagMask());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -380,6 +384,7 @@ void EntityRenderer::doRenderUpdateSynchronous(const ScenePointer& scene, Transa
|
|||
|
||||
_moving = entity->isMovingRelativeToParent();
|
||||
_visible = entity->getVisible();
|
||||
setIsVisibleInSecondaryCamera(entity->isVisibleInSecondaryCamera());
|
||||
_canCastShadow = entity->getCanCastShadow();
|
||||
_cauterized = entity->getCauterized();
|
||||
_needsRenderUpdate = false;
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "AbstractViewStateInterface.h"
|
||||
#include "EntitiesRendererLogging.h"
|
||||
#include <graphics-scripting/Forward.h>
|
||||
#include <RenderHifi.h>
|
||||
|
||||
class EntityTreeRenderer;
|
||||
|
||||
|
@ -74,6 +75,7 @@ protected:
|
|||
virtual Item::Bound getBound() override;
|
||||
virtual void render(RenderArgs* args) override final;
|
||||
virtual uint32_t metaFetchMetaSubItems(ItemIDs& subItems) override;
|
||||
virtual render::hifi::Tag getTagMask() const;
|
||||
|
||||
// Returns true if the item in question needs to have updateInScene called because of internal rendering state changes
|
||||
virtual bool needsRenderUpdate() const;
|
||||
|
@ -97,6 +99,8 @@ protected:
|
|||
bool isFading() const { return _isFading; }
|
||||
virtual bool isTransparent() const { return _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) < 1.0f : false; }
|
||||
inline bool isValidRenderItem() const { return _renderItemID != Item::INVALID_ITEM_ID; }
|
||||
|
||||
virtual void setIsVisibleInSecondaryCamera(bool value) { _isVisibleInSecondaryCamera = value; }
|
||||
|
||||
template <typename F, typename T>
|
||||
T withReadLockResult(const std::function<T()>& f) {
|
||||
|
@ -129,6 +133,7 @@ protected:
|
|||
bool _isFading{ _entitiesShouldFadeFunction() };
|
||||
bool _prevIsTransparent { false };
|
||||
bool _visible { false };
|
||||
bool _isVisibleInSecondaryCamera { false };
|
||||
bool _canCastShadow { false };
|
||||
bool _cauterized { false };
|
||||
bool _moving { false };
|
||||
|
|
|
@ -43,7 +43,7 @@ void MaterialEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer&
|
|||
|
||||
ItemKey MaterialEntityRenderer::getKey() {
|
||||
ItemKey::Builder builder;
|
||||
builder.withTypeShape().withTagBits(render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1);
|
||||
builder.withTypeShape().withTagBits(getTagMask());
|
||||
|
||||
if (!_visible) {
|
||||
builder.withInvisible();
|
||||
|
|
|
@ -1060,9 +1060,9 @@ ModelEntityRenderer::ModelEntityRenderer(const EntityItemPointer& entity) : Pare
|
|||
|
||||
void ModelEntityRenderer::setKey(bool didVisualGeometryRequestSucceed) {
|
||||
if (didVisualGeometryRequestSucceed) {
|
||||
_itemKey = ItemKey::Builder().withTypeMeta().withTagBits(render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1);
|
||||
_itemKey = ItemKey::Builder().withTypeMeta().withTagBits(getTagMask());
|
||||
} else {
|
||||
_itemKey = ItemKey::Builder().withTypeMeta().withTypeShape().withTagBits(render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1);
|
||||
_itemKey = ItemKey::Builder().withTypeMeta().withTypeShape().withTagBits(getTagMask());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1070,6 +1070,13 @@ ItemKey ModelEntityRenderer::getKey() {
|
|||
return _itemKey;
|
||||
}
|
||||
|
||||
render::hifi::Tag ModelEntityRenderer::getTagMask() const {
|
||||
// Default behavior for model is to not be visible in main view if cauterized (aka parented to the avatar's neck joint)
|
||||
return _cauterized ?
|
||||
(_isVisibleInSecondaryCamera ? render::hifi::TAG_SECONDARY_VIEW : render::hifi::TAG_NONE) :
|
||||
Parent::getTagMask(); // calculate which views to be shown in
|
||||
}
|
||||
|
||||
uint32_t ModelEntityRenderer::metaFetchMetaSubItems(ItemIDs& subItems) {
|
||||
if (_model) {
|
||||
auto metaSubItems = _subRenderItemIDs;
|
||||
|
@ -1329,6 +1336,7 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
|
|||
emit DependencyManager::get<scriptable::ModelProviderFactory>()->
|
||||
modelAddedToScene(entity->getEntityItemID(), NestableType::Entity, _model);
|
||||
}
|
||||
_didLastVisualGeometryRequestSucceed = didVisualGeometryRequestSucceed;
|
||||
});
|
||||
connect(model.get(), &Model::requestRenderUpdate, this, &ModelEntityRenderer::requestRenderUpdate);
|
||||
connect(entity.get(), &RenderableModelEntityItem::requestCollisionGeometryUpdate, this, &ModelEntityRenderer::flagForCollisionGeometryUpdate);
|
||||
|
@ -1386,11 +1394,7 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
|
|||
entity->updateModelBounds();
|
||||
entity->stopModelOverrideIfNoParent();
|
||||
|
||||
// Default behavior for model is to not be visible in main view if cauterized (aka parented to the avatar's neck joint)
|
||||
auto tagMask = _cauterized ?
|
||||
render::hifi::TAG_SECONDARY_VIEW : // draw in every view except the main one (view zero)
|
||||
render::hifi::TAG_ALL_VIEWS; // draw in all views
|
||||
|
||||
render::hifi::Tag tagMask = getTagMask();
|
||||
if (model->isVisible() != _visible) {
|
||||
// FIXME: this seems like it could be optimized if we tracked our last known visible state in
|
||||
// the renderable item. As it stands now the model checks it's visible/invisible state
|
||||
|
@ -1478,6 +1482,11 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
|
|||
}
|
||||
}
|
||||
|
||||
void ModelEntityRenderer::setIsVisibleInSecondaryCamera(bool value) {
|
||||
Parent::setIsVisibleInSecondaryCamera(value);
|
||||
setKey(_didLastVisualGeometryRequestSucceed);
|
||||
}
|
||||
|
||||
void ModelEntityRenderer::flagForCollisionGeometryUpdate() {
|
||||
_needsCollisionGeometryUpdate = true;
|
||||
emit requestRenderUpdate();
|
||||
|
|
|
@ -164,6 +164,10 @@ protected:
|
|||
void flagForCollisionGeometryUpdate();
|
||||
void setCollisionMeshKey(const void* key);
|
||||
|
||||
render::hifi::Tag getTagMask() const override;
|
||||
|
||||
void setIsVisibleInSecondaryCamera(bool value) override;
|
||||
|
||||
private:
|
||||
void animate(const TypedEntityPointer& entity);
|
||||
void mapJoints(const TypedEntityPointer& entity, const QStringList& modelJointNames);
|
||||
|
@ -202,6 +206,8 @@ private:
|
|||
|
||||
render::ItemKey _itemKey { render::ItemKey::Builder().withTypeMeta() };
|
||||
|
||||
bool _didLastVisualGeometryRequestSucceed { false };
|
||||
|
||||
void processMaterials();
|
||||
};
|
||||
|
||||
|
|
|
@ -147,9 +147,9 @@ void ParticleEffectEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEn
|
|||
|
||||
ItemKey ParticleEffectEntityRenderer::getKey() {
|
||||
if (_visible) {
|
||||
return ItemKey::Builder::transparentShape().withTagBits(render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1);
|
||||
return ItemKey::Builder::transparentShape().withTagBits(getTagMask());
|
||||
} else {
|
||||
return ItemKey::Builder().withInvisible().withTagBits(render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1).build();
|
||||
return ItemKey::Builder().withInvisible().withTagBits(getTagMask()).build();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -112,7 +112,7 @@ PolyLineEntityRenderer::PolyLineEntityRenderer(const EntityItemPointer& entity)
|
|||
}
|
||||
|
||||
ItemKey PolyLineEntityRenderer::getKey() {
|
||||
return ItemKey::Builder::transparentShape().withTypeMeta().withTagBits(render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1);
|
||||
return ItemKey::Builder::transparentShape().withTypeMeta().withTagBits(getTagMask());
|
||||
}
|
||||
|
||||
ShapeKey PolyLineEntityRenderer::getShapeKey() {
|
||||
|
|
|
@ -169,7 +169,7 @@ public:
|
|||
}
|
||||
|
||||
protected:
|
||||
virtual ItemKey getKey() override { return ItemKey::Builder::opaqueShape().withTagBits(render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1); }
|
||||
virtual ItemKey getKey() override { return ItemKey::Builder::opaqueShape().withTagBits(getTagMask()); }
|
||||
virtual ShapeKey getShapeKey() override;
|
||||
virtual bool needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const override;
|
||||
virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) override;
|
||||
|
|
|
@ -139,7 +139,7 @@ bool ShapeEntityRenderer::isTransparent() const {
|
|||
|
||||
ItemKey ShapeEntityRenderer::getKey() {
|
||||
ItemKey::Builder builder;
|
||||
builder.withTypeShape().withTypeMeta().withTagBits(render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1);
|
||||
builder.withTypeShape().withTypeMeta().withTagBits(getTagMask());
|
||||
|
||||
withReadLock([&] {
|
||||
if (isTransparent()) {
|
||||
|
|
|
@ -269,7 +269,7 @@ void ZoneEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointe
|
|||
|
||||
|
||||
ItemKey ZoneEntityRenderer::getKey() {
|
||||
return ItemKey::Builder().withTypeMeta().withTagBits(render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1).build();
|
||||
return ItemKey::Builder().withTypeMeta().withTagBits(getTagMask()).build();
|
||||
}
|
||||
|
||||
bool ZoneEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const {
|
||||
|
|
|
@ -1383,6 +1383,7 @@ bool EntityItem::setProperties(const EntityItemProperties& properties) {
|
|||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(visible, setVisible);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(canCastShadow, setCanCastShadow);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(userData, setUserData);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(isVisibleInSecondaryCamera, setIsVisibleInSecondaryCamera);
|
||||
|
||||
// Certifiable Properties
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(itemName, setItemName);
|
||||
|
@ -2760,6 +2761,28 @@ void EntityItem::setVisible(bool value) {
|
|||
}
|
||||
}
|
||||
|
||||
bool EntityItem::isVisibleInSecondaryCamera() const {
|
||||
bool result;
|
||||
withReadLock([&] {
|
||||
result = _isVisibleInSecondaryCamera;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
void EntityItem::setIsVisibleInSecondaryCamera(bool value) {
|
||||
bool changed = false;
|
||||
withWriteLock([&] {
|
||||
if (_isVisibleInSecondaryCamera != value) {
|
||||
changed = true;
|
||||
_isVisibleInSecondaryCamera = value;
|
||||
}
|
||||
});
|
||||
|
||||
if (changed) {
|
||||
emit requestRenderUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
bool EntityItem::getCanCastShadow() const {
|
||||
bool result;
|
||||
withReadLock([&] {
|
||||
|
|
|
@ -277,6 +277,9 @@ public:
|
|||
bool getVisible() const;
|
||||
void setVisible(bool value);
|
||||
|
||||
bool isVisibleInSecondaryCamera() const;
|
||||
void setIsVisibleInSecondaryCamera(bool value);
|
||||
|
||||
bool getCanCastShadow() const;
|
||||
void setCanCastShadow(bool value);
|
||||
|
||||
|
@ -578,6 +581,7 @@ protected:
|
|||
glm::vec3 _registrationPoint { ENTITY_ITEM_DEFAULT_REGISTRATION_POINT };
|
||||
float _angularDamping { ENTITY_ITEM_DEFAULT_ANGULAR_DAMPING };
|
||||
bool _visible { ENTITY_ITEM_DEFAULT_VISIBLE };
|
||||
bool _isVisibleInSecondaryCamera { ENTITY_ITEM_DEFAULT_VISIBLE_IN_SECONDARY_CAMERA };
|
||||
bool _canCastShadow{ ENTITY_ITEM_DEFAULT_CAN_CAST_SHADOW };
|
||||
bool _collisionless { ENTITY_ITEM_DEFAULT_COLLISIONLESS };
|
||||
uint16_t _collisionMask { ENTITY_COLLISION_MASK_DEFAULT };
|
||||
|
|
|
@ -368,6 +368,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
|
|||
CHECK_PROPERTY_CHANGE(PROP_MATERIAL_MAPPING_SCALE, materialMappingScale);
|
||||
CHECK_PROPERTY_CHANGE(PROP_MATERIAL_MAPPING_ROT, materialMappingRot);
|
||||
CHECK_PROPERTY_CHANGE(PROP_MATERIAL_DATA, materialData);
|
||||
CHECK_PROPERTY_CHANGE(PROP_VISIBLE_IN_SECONDARY_CAMERA, isVisibleInSecondaryCamera);
|
||||
|
||||
// Certifiable Properties
|
||||
CHECK_PROPERTY_CHANGE(PROP_ITEM_NAME, itemName);
|
||||
|
@ -490,6 +491,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
|
|||
* {@link Entities.EntityType|Model} and {@link Entities.EntityType|Shape} entities. Shadows are cast if inside a
|
||||
* {@link Entities.EntityType|Zone} entity with <code>castShadows</code> enabled in its
|
||||
* {@link Entities.EntityProperties-Zone|keyLight} property.
|
||||
* @property {boolean} isVisibleInSecondaryCamera=true - Whether or not the entity is rendered in the secondary camera. If <code>true</code> then the entity is rendered.
|
||||
*
|
||||
* @property {Vec3} position=0,0,0 - The position of the entity.
|
||||
* @property {Quat} rotation=0,0,0,1 - The orientation of the entity with respect to world coordinates.
|
||||
|
@ -1226,6 +1228,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool
|
|||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LOCKED, locked);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_USER_DATA, userData);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ALPHA, alpha);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_VISIBLE_IN_SECONDARY_CAMERA, isVisibleInSecondaryCamera);
|
||||
|
||||
// Certifiable Properties
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ITEM_NAME, itemName);
|
||||
|
@ -1565,6 +1568,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool
|
|||
COPY_PROPERTY_FROM_QSCRIPTVALUE(materialMappingScale, glmVec2, setMaterialMappingScale);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(materialMappingRot, float, setMaterialMappingRot);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(materialData, QString, setMaterialData);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(isVisibleInSecondaryCamera, bool, setIsVisibleInSecondaryCamera);
|
||||
|
||||
// Certifiable Properties
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(itemName, QString, setItemName);
|
||||
|
@ -1944,6 +1948,8 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue
|
|||
ADD_PROPERTY_TO_MAP(PROP_MATERIAL_MAPPING_ROT, MaterialMappingRot, materialMappingRot, float);
|
||||
ADD_PROPERTY_TO_MAP(PROP_MATERIAL_DATA, MaterialData, materialData, QString);
|
||||
|
||||
ADD_PROPERTY_TO_MAP(PROP_VISIBLE_IN_SECONDARY_CAMERA, IsVisibleInSecondaryCamera, isVisibleInSecondaryCamera, bool);
|
||||
|
||||
// Certifiable Properties
|
||||
ADD_PROPERTY_TO_MAP(PROP_ITEM_NAME, ItemName, itemName, QString);
|
||||
ADD_PROPERTY_TO_MAP(PROP_ITEM_DESCRIPTION, ItemDescription, itemDescription, QString);
|
||||
|
@ -3041,6 +3047,8 @@ void EntityItemProperties::markAllChanged() {
|
|||
_cloneDynamicChanged = true;
|
||||
_cloneAvatarEntityChanged = true;
|
||||
_cloneOriginIDChanged = true;
|
||||
|
||||
_isVisibleInSecondaryCameraChanged = true;
|
||||
}
|
||||
|
||||
// The minimum bounding box for the entity.
|
||||
|
@ -3319,6 +3327,9 @@ QList<QString> EntityItemProperties::listChangedProperties() {
|
|||
if (materialDataChanged()) {
|
||||
out += "materialData";
|
||||
}
|
||||
if (isVisibleInSecondaryCameraChanged()) {
|
||||
out += "isVisibleInSecondaryCamera";
|
||||
}
|
||||
|
||||
// Certifiable Properties
|
||||
if (itemNameChanged()) {
|
||||
|
|
|
@ -233,6 +233,8 @@ public:
|
|||
DEFINE_PROPERTY_REF(PROP_MATERIAL_MAPPING_ROT, MaterialMappingRot, materialMappingRot, float, 0);
|
||||
DEFINE_PROPERTY_REF(PROP_MATERIAL_DATA, MaterialData, materialData, QString, "");
|
||||
|
||||
DEFINE_PROPERTY(PROP_VISIBLE_IN_SECONDARY_CAMERA, IsVisibleInSecondaryCamera, isVisibleInSecondaryCamera, bool, ENTITY_ITEM_DEFAULT_VISIBLE_IN_SECONDARY_CAMERA);
|
||||
|
||||
// Certifiable Properties - related to Proof of Purchase certificates
|
||||
DEFINE_PROPERTY_REF(PROP_ITEM_NAME, ItemName, itemName, QString, ENTITY_ITEM_DEFAULT_ITEM_NAME);
|
||||
DEFINE_PROPERTY_REF(PROP_ITEM_DESCRIPTION, ItemDescription, itemDescription, QString, ENTITY_ITEM_DEFAULT_ITEM_DESCRIPTION);
|
||||
|
|
|
@ -46,6 +46,7 @@ const quint32 ENTITY_ITEM_DEFAULT_STATIC_CERTIFICATE_VERSION = 0;
|
|||
const float ENTITY_ITEM_DEFAULT_ALPHA = 1.0f;
|
||||
const float ENTITY_ITEM_DEFAULT_LOCAL_RENDER_ALPHA = 1.0f;
|
||||
const bool ENTITY_ITEM_DEFAULT_VISIBLE = true;
|
||||
const bool ENTITY_ITEM_DEFAULT_VISIBLE_IN_SECONDARY_CAMERA = true;
|
||||
const bool ENTITY_ITEM_DEFAULT_CAN_CAST_SHADOW { true };
|
||||
|
||||
const QString ENTITY_ITEM_DEFAULT_SCRIPT = QString("");
|
||||
|
|
|
@ -249,6 +249,8 @@ enum EntityPropertyList {
|
|||
PROP_MATERIAL_MAPPING_ROT,
|
||||
PROP_MATERIAL_DATA,
|
||||
|
||||
PROP_VISIBLE_IN_SECONDARY_CAMERA, // not sent over the wire, only used locally
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// ATTENTION: add new properties to end of list just ABOVE this line
|
||||
PROP_AFTER_LAST_ITEM,
|
||||
|
|
|
@ -83,7 +83,8 @@
|
|||
"position": cameraPosition,
|
||||
"shapeType": "simple-compound",
|
||||
"type": "Model",
|
||||
"userData": "{\"grabbableKey\":{\"grabbable\":true}}"
|
||||
"userData": "{\"grabbableKey\":{\"grabbable\":true}}",
|
||||
"isVisibleInSecondaryCamera": false
|
||||
}, true);
|
||||
spectatorCameraConfig.attachedEntityId = camera;
|
||||
updateOverlay();
|
||||
|
|
Loading…
Reference in a new issue