mirror of
https://thingvellir.net/git/overte
synced 2025-03-27 23:52:03 +01:00
wip live material swapping on model entities, model overlays, avatars,
and albedo swap on shape entities
This commit is contained in:
parent
4d4294dd6a
commit
84cd0e1529
52 changed files with 1038 additions and 251 deletions
|
@ -22,6 +22,8 @@ setup_memory_debugger()
|
|||
symlink_or_copy_directory_beside_target(${_SHOULD_SYMLINK_RESOURCES} "${CMAKE_CURRENT_SOURCE_DIR}/resources" "resources")
|
||||
|
||||
# link the shared hifi libraries
|
||||
include_hifi_library_headers(gpu)
|
||||
include_hifi_library_headers(graphics)
|
||||
link_hifi_libraries(embedded-webserver networking shared avatars)
|
||||
|
||||
# find OpenSSL
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 19.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
|
||||
<path d="M348.5,162.5c1.7,0,3,1.4,3,3v181.4c0,1.7-1.3,3-3,3H167.2c-1.6,0-3-1.3-3-3V165.5c0-1.6,1.4-3,3-3H348.5 M348.5,145.5
|
||||
H167.2c-11,0-20,9-20,20v181.4c0,11,9,20,20,20h181.4c11,0,20-9,20-20V165.5C368.5,154.5,359.6,145.5,348.5,145.5L348.5,145.5z"/>
|
||||
<rect x="161.6" y="253.6" width="96.3" height="96.3"/>
|
||||
<rect x="256.1" y="159.8" width="95.4" height="95.4"/>
|
||||
</svg>
|
After Width: | Height: | Size: 717 B |
|
@ -135,7 +135,7 @@ TabView {
|
|||
}
|
||||
|
||||
NewEntityButton {
|
||||
icon: "icons/create-icons/94-model-01.svg"
|
||||
icon: "icons/create-icons/126-material-01.svg"
|
||||
text: "MATERIAL"
|
||||
onClicked: {
|
||||
editRoot.sendToScript({
|
||||
|
|
|
@ -1580,6 +1580,42 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
}
|
||||
});
|
||||
|
||||
EntityTree::setAddMaterialToAvatarOperator([](const QUuid& avatarID, graphics::MaterialPointer material, quint16 shapeID) {
|
||||
auto avatarManager = DependencyManager::get<AvatarManager>();
|
||||
auto avatar = avatarManager->getAvatarBySessionID(avatarID);
|
||||
if (avatar) {
|
||||
avatar->addMaterial(material, shapeID);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
EntityTree::setRemoveMaterialFromAvatarOperator([](const QUuid& avatarID, graphics::MaterialPointer material, quint16 shapeID) {
|
||||
auto avatarManager = DependencyManager::get<AvatarManager>();
|
||||
auto avatar = avatarManager->getAvatarBySessionID(avatarID);
|
||||
if (avatar) {
|
||||
avatar->removeMaterial(material, shapeID);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
EntityTree::setAddMaterialToOverlayOperator([&](const QUuid& overlayID, graphics::MaterialPointer material, quint16 shapeID) {
|
||||
auto overlay = _overlays.getOverlay(overlayID);
|
||||
if (overlay) {
|
||||
overlay->addMaterial(material, shapeID);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
EntityTree::setRemoveMaterialFromOverlayOperator([&](const QUuid& overlayID, graphics::MaterialPointer material, quint16 shapeID) {
|
||||
auto overlay = _overlays.getOverlay(overlayID);
|
||||
if (overlay) {
|
||||
overlay->removeMaterial(material, shapeID);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
// Keyboard focus handling for Web overlays.
|
||||
auto overlays = &(qApp->getOverlays());
|
||||
connect(overlays, &Overlays::overlayDeleted, [=](const OverlayID& overlayID) {
|
||||
|
|
|
@ -632,3 +632,29 @@ uint32_t ModelOverlay::fetchMetaSubItems(render::ItemIDs& subItems) const {
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ModelOverlay::addMaterial(graphics::MaterialPointer material, quint16 shapeID) {
|
||||
Parent::addMaterial(material, shapeID);
|
||||
if (_model && _model->fetchRenderItemIDs().size() > 0) {
|
||||
_model->addMaterial(material, shapeID);
|
||||
}
|
||||
}
|
||||
|
||||
void ModelOverlay::removeMaterial(graphics::MaterialPointer material, quint16 shapeID) {
|
||||
Parent::removeMaterial(material, shapeID);
|
||||
if (_model && _model->fetchRenderItemIDs().size() > 0) {
|
||||
_model->removeMaterial(material, shapeID);
|
||||
}
|
||||
}
|
||||
|
||||
void ModelOverlay::processMaterials() {
|
||||
assert(_model);
|
||||
std::lock_guard<std::mutex> lock(_materialsLock);
|
||||
for (auto& shapeMaterialPair : _materials) {
|
||||
auto material = shapeMaterialPair.second;
|
||||
while (!material.empty()) {
|
||||
_model->addMaterial(material.top(), shapeMaterialPair.first);
|
||||
material.pop();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -59,6 +59,9 @@ public:
|
|||
void setDrawInFront(bool drawInFront) override;
|
||||
void setDrawHUDLayer(bool drawHUDLayer) override;
|
||||
|
||||
void addMaterial(graphics::MaterialPointer material, quint16 shapeID) override;
|
||||
void removeMaterial(graphics::MaterialPointer material, quint16 shapeID) override;
|
||||
|
||||
protected:
|
||||
Transform evalRenderTransform() override;
|
||||
|
||||
|
@ -110,6 +113,8 @@ private:
|
|||
bool _drawInFrontDirty { false };
|
||||
bool _drawInHUDDirty { false };
|
||||
|
||||
void processMaterials();
|
||||
|
||||
};
|
||||
|
||||
#endif // hifi_ModelOverlay_h
|
||||
|
|
|
@ -235,3 +235,13 @@ QVector<OverlayID> qVectorOverlayIDFromScriptValue(const QScriptValue& array) {
|
|||
}
|
||||
return newVector;
|
||||
}
|
||||
|
||||
void Overlay::addMaterial(graphics::MaterialPointer material, quint16 shapeID) {
|
||||
std::lock_guard<std::mutex> lock(_materialsLock);
|
||||
_materials[shapeID].push(material);
|
||||
}
|
||||
|
||||
void Overlay::removeMaterial(graphics::MaterialPointer material, quint16 shapeID) {
|
||||
std::lock_guard<std::mutex> lock(_materialsLock);
|
||||
_materials[shapeID].remove(material);
|
||||
}
|
|
@ -91,6 +91,9 @@ public:
|
|||
unsigned int getStackOrder() const { return _stackOrder; }
|
||||
void setStackOrder(unsigned int stackOrder) { _stackOrder = stackOrder; }
|
||||
|
||||
virtual void addMaterial(graphics::MaterialPointer material, quint16 shapeID);
|
||||
virtual void removeMaterial(graphics::MaterialPointer material, quint16 shapeID);
|
||||
|
||||
protected:
|
||||
float updatePulse();
|
||||
|
||||
|
@ -117,6 +120,9 @@ protected:
|
|||
static const xColor DEFAULT_OVERLAY_COLOR;
|
||||
static const float DEFAULT_ALPHA;
|
||||
|
||||
std::unordered_map<quint16, graphics::MultiMaterial> _materials;
|
||||
std::mutex _materialsLock;
|
||||
|
||||
private:
|
||||
OverlayID _overlayID; // only used for non-3d overlays
|
||||
};
|
||||
|
|
|
@ -570,6 +570,7 @@ void Avatar::addToScene(AvatarSharedPointer self, const render::ScenePointer& sc
|
|||
}
|
||||
transaction.resetItem(_renderItemID, avatarPayloadPointer);
|
||||
_skeletonModel->addToScene(scene, transaction);
|
||||
processMaterials();
|
||||
for (auto& attachmentModel : _attachmentModels) {
|
||||
attachmentModel->addToScene(scene, transaction);
|
||||
}
|
||||
|
@ -761,6 +762,7 @@ void Avatar::fixupModelsInScene(const render::ScenePointer& scene) {
|
|||
if (_skeletonModel->isRenderable() && _skeletonModel->needsFixupInScene()) {
|
||||
_skeletonModel->removeFromScene(scene, transaction);
|
||||
_skeletonModel->addToScene(scene, transaction);
|
||||
processMaterials();
|
||||
canTryFade = true;
|
||||
_isAnimatingScale = true;
|
||||
}
|
||||
|
@ -1760,3 +1762,31 @@ float Avatar::getUnscaledEyeHeightFromSkeleton() const {
|
|||
return DEFAULT_AVATAR_EYE_HEIGHT;
|
||||
}
|
||||
}
|
||||
|
||||
void Avatar::addMaterial(graphics::MaterialPointer material, quint16 shapeID) {
|
||||
std::lock_guard<std::mutex> lock(_materialsLock);
|
||||
_materials[shapeID].push(material);
|
||||
if (_skeletonModel && _skeletonModel->fetchRenderItemIDs().size() > 0) {
|
||||
_skeletonModel->addMaterial(material, shapeID);
|
||||
}
|
||||
}
|
||||
|
||||
void Avatar::removeMaterial(graphics::MaterialPointer material, quint16 shapeID) {
|
||||
std::lock_guard<std::mutex> lock(_materialsLock);
|
||||
_materials[shapeID].remove(material);
|
||||
if (_skeletonModel && _skeletonModel->fetchRenderItemIDs().size() > 0) {
|
||||
_skeletonModel->removeMaterial(material, shapeID);
|
||||
}
|
||||
}
|
||||
|
||||
void Avatar::processMaterials() {
|
||||
assert(_skeletonModel);
|
||||
std::lock_guard<std::mutex> lock(_materialsLock);
|
||||
for (auto& shapeMaterialPair : _materials) {
|
||||
auto material = shapeMaterialPair.second;
|
||||
while (!material.empty()) {
|
||||
_skeletonModel->addMaterial(material.top(), shapeMaterialPair.first);
|
||||
material.pop();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -272,6 +272,9 @@ public:
|
|||
|
||||
virtual void setAvatarEntityDataChanged(bool value) override;
|
||||
|
||||
void addMaterial(graphics::MaterialPointer material, quint16 shapeID) override;
|
||||
void removeMaterial(graphics::MaterialPointer material, quint16 shapeID) override;
|
||||
|
||||
public slots:
|
||||
|
||||
// FIXME - these should be migrated to use Pose data instead
|
||||
|
@ -397,6 +400,11 @@ protected:
|
|||
float _displayNameAlpha { 1.0f };
|
||||
|
||||
ThreadSafeValueCache<float> _unscaledEyeHeightCache { DEFAULT_AVATAR_EYE_HEIGHT };
|
||||
|
||||
std::unordered_map<quint16, graphics::MultiMaterial> _materials;
|
||||
std::mutex _materialsLock;
|
||||
|
||||
void processMaterials();
|
||||
};
|
||||
|
||||
#endif // hifi_Avatar_h
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
set(TARGET_NAME avatars)
|
||||
setup_hifi_library(Network Script)
|
||||
link_hifi_libraries(shared networking)
|
||||
include_hifi_library_headers(gpu)
|
||||
link_hifi_libraries(shared networking graphics)
|
||||
|
|
|
@ -2558,4 +2558,4 @@ void AvatarEntityMapFromScriptValue(const QScriptValue& object, AvatarEntityMap&
|
|||
|
||||
value[EntityID] = binaryEntityProperties;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -54,6 +54,8 @@
|
|||
#include "HeadData.h"
|
||||
#include "PathUtils.h"
|
||||
|
||||
#include <graphics/Material.h>
|
||||
|
||||
using AvatarSharedPointer = std::shared_ptr<AvatarData>;
|
||||
using AvatarWeakPointer = std::weak_ptr<AvatarData>;
|
||||
using AvatarHash = QHash<QUuid, AvatarSharedPointer>;
|
||||
|
@ -694,6 +696,9 @@ public:
|
|||
|
||||
bool getIsReplicated() const { return _isReplicated; }
|
||||
|
||||
virtual void addMaterial(graphics::MaterialPointer material, quint16 shapeID) {}
|
||||
virtual void removeMaterial(graphics::MaterialPointer material, quint16 shapeID) {}
|
||||
|
||||
signals:
|
||||
void displayNameChanged();
|
||||
void sessionDisplayNameChanged();
|
||||
|
|
|
@ -146,6 +146,9 @@ EntityRenderer::EntityRenderer(const EntityItemPointer& entity) : _entity(entity
|
|||
_needsRenderUpdate = true;
|
||||
emit requestRenderUpdate();
|
||||
});
|
||||
_materials = entity->getMaterials();
|
||||
connect(entity.get(), &EntityItem::addMaterialToRenderItem, this, &EntityRenderer::addMaterial);
|
||||
connect(entity.get(), &EntityItem::removeMaterialFromRenderItem, this, &EntityRenderer::removeMaterial);
|
||||
}
|
||||
|
||||
EntityRenderer::~EntityRenderer() { }
|
||||
|
@ -399,4 +402,14 @@ void EntityRenderer::onAddToScene(const EntityItemPointer& entity) {
|
|||
void EntityRenderer::onRemoveFromScene(const EntityItemPointer& entity) {
|
||||
entity->deregisterChangeHandler(_changeHandlerId);
|
||||
QObject::disconnect(this, &EntityRenderer::requestRenderUpdate, this, nullptr);
|
||||
}
|
||||
|
||||
void EntityRenderer::addMaterial(graphics::MaterialPointer material, quint16 shapeID) {
|
||||
std::lock_guard<std::mutex> lock(_materialsLock);
|
||||
_materials[shapeID].push(material);
|
||||
}
|
||||
|
||||
void EntityRenderer::removeMaterial(graphics::MaterialPointer material, quint16 shapeID) {
|
||||
std::lock_guard<std::mutex> lock(_materialsLock);
|
||||
_materials[shapeID].remove(material);
|
||||
}
|
|
@ -101,6 +101,10 @@ protected:
|
|||
return result;
|
||||
}
|
||||
|
||||
public slots:
|
||||
virtual void addMaterial(graphics::MaterialPointer material, quint16 shapeID);
|
||||
virtual void removeMaterial(graphics::MaterialPointer material, quint16 shapeID);
|
||||
|
||||
signals:
|
||||
void requestRenderUpdate();
|
||||
|
||||
|
@ -129,6 +133,8 @@ protected:
|
|||
// Only touched on the rendering thread
|
||||
bool _renderUpdateQueued{ false };
|
||||
|
||||
std::unordered_map<quint16, graphics::MultiMaterial> _materials;
|
||||
std::mutex _materialsLock;
|
||||
|
||||
private:
|
||||
// The base class relies on comparing the model transform to the entity transform in order
|
||||
|
|
|
@ -15,12 +15,18 @@ bool MaterialEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityP
|
|||
if (entity->getMaterial() != _drawMaterial) {
|
||||
return true;
|
||||
}
|
||||
if (entity->getParentID() != _parentID || entity->getClientOnly() != _clientOnly || entity->getOwningAvatarID() != _owningAvatarID) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void MaterialEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) {
|
||||
withWriteLock([&] {
|
||||
_drawMaterial = entity->getMaterial();
|
||||
_parentID = entity->getParentID();
|
||||
_clientOnly = entity->getClientOnly();
|
||||
_owningAvatarID = entity->getOwningAvatarID();
|
||||
_renderTransform = getModelTransform();
|
||||
const float MATERIAL_ENTITY_SCALE = 0.5f;
|
||||
_renderTransform.postScale(MATERIAL_ENTITY_SCALE);
|
||||
|
@ -30,7 +36,7 @@ void MaterialEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer&
|
|||
|
||||
ItemKey MaterialEntityRenderer::getKey() {
|
||||
ItemKey::Builder builder;
|
||||
builder.withTypeShape();
|
||||
builder.withTypeShape().withTagBits(render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1);
|
||||
|
||||
if (!_visible) {
|
||||
builder.withInvisible();
|
||||
|
@ -215,13 +221,25 @@ void MaterialEntityRenderer::generateMesh() {
|
|||
void MaterialEntityRenderer::doRender(RenderArgs* args) {
|
||||
PerformanceTimer perfTimer("RenderableMaterialEntityItem::render");
|
||||
Q_ASSERT(args->_batch);
|
||||
|
||||
gpu::Batch& batch = *args->_batch;
|
||||
|
||||
batch.setModelTransform(_renderTransform);
|
||||
// Don't render if our parent is set or our material is null
|
||||
QUuid parentID;
|
||||
Transform renderTransform;
|
||||
graphics::MaterialPointer drawMaterial;
|
||||
withReadLock([&] {
|
||||
parentID = _clientOnly ? _owningAvatarID : _parentID;
|
||||
renderTransform = _renderTransform;
|
||||
drawMaterial = _drawMaterial;
|
||||
});
|
||||
if (!parentID.isNull() || !drawMaterial) {
|
||||
return;
|
||||
}
|
||||
|
||||
batch.setModelTransform(renderTransform);
|
||||
|
||||
// bind the material
|
||||
args->_shapePipeline->bindMaterial(_drawMaterial, batch, args->_enableTexturing);
|
||||
args->_shapePipeline->bindMaterial(drawMaterial, batch, args->_enableTexturing);
|
||||
args->_details._materialSwitches++;
|
||||
|
||||
// Draw!
|
||||
|
|
|
@ -31,6 +31,9 @@ private:
|
|||
ItemKey getKey() override;
|
||||
ShapeKey getShapeKey() override;
|
||||
|
||||
QUuid _parentID;
|
||||
bool _clientOnly;
|
||||
QUuid _owningAvatarID;
|
||||
Transform _renderTransform;
|
||||
|
||||
std::shared_ptr<NetworkMaterial> _drawMaterial;
|
||||
|
@ -47,7 +50,7 @@ private:
|
|||
static void addVertex(std::vector<float>& buffer, const glm::vec3& pos, const glm::vec3& tan, const glm::vec2 uv);
|
||||
const int SLICES = 15;
|
||||
const int STACKS = 9;
|
||||
const float M_PI_TIMES_2 = 2.0f * M_PI;
|
||||
const float M_PI_TIMES_2 = 2.0f * (float)M_PI;
|
||||
};
|
||||
|
||||
} }
|
||||
|
|
|
@ -1380,6 +1380,7 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
|
|||
auto entityRenderer = static_cast<EntityRenderer*>(&data);
|
||||
entityRenderer->setSubRenderItemIDs(newRenderItemIDs);
|
||||
});
|
||||
processMaterials();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1466,3 +1467,28 @@ void ModelEntityRenderer::mapJoints(const TypedEntityPointer& entity, const QStr
|
|||
}
|
||||
}
|
||||
|
||||
void ModelEntityRenderer::addMaterial(graphics::MaterialPointer material, quint16 shapeID) {
|
||||
Parent::addMaterial(material, shapeID);
|
||||
if (_model && _model->fetchRenderItemIDs().size() > 0) {
|
||||
_model->addMaterial(material, shapeID);
|
||||
}
|
||||
}
|
||||
|
||||
void ModelEntityRenderer::removeMaterial(graphics::MaterialPointer material, quint16 shapeID) {
|
||||
Parent::removeMaterial(material, shapeID);
|
||||
if (_model && _model->fetchRenderItemIDs().size() > 0) {
|
||||
_model->removeMaterial(material, shapeID);
|
||||
}
|
||||
}
|
||||
|
||||
void ModelEntityRenderer::processMaterials() {
|
||||
assert(_model);
|
||||
std::lock_guard<std::mutex> lock(_materialsLock);
|
||||
for (auto& shapeMaterialPair : _materials) {
|
||||
auto material = shapeMaterialPair.second;
|
||||
while (!material.empty()) {
|
||||
_model->addMaterial(material.top(), shapeMaterialPair.first);
|
||||
material.pop();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -138,10 +138,15 @@ namespace render { namespace entities {
|
|||
class ModelEntityRenderer : public TypedEntityRenderer<RenderableModelEntityItem> {
|
||||
using Parent = TypedEntityRenderer<RenderableModelEntityItem>;
|
||||
friend class EntityRenderer;
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ModelEntityRenderer(const EntityItemPointer& entity);
|
||||
|
||||
public slots:
|
||||
void addMaterial(graphics::MaterialPointer material, quint16 shapeID) override;
|
||||
void removeMaterial(graphics::MaterialPointer material, quint16 shapeID) override;
|
||||
|
||||
protected:
|
||||
virtual void removeFromScene(const ScenePointer& scene, Transaction& transaction) override;
|
||||
virtual void onRemoveFromSceneTyped(const TypedEntityPointer& entity) override;
|
||||
|
@ -194,6 +199,8 @@ private:
|
|||
uint64_t _lastAnimated { 0 };
|
||||
|
||||
render::ItemKey _itemKey { render::ItemKey::Builder().withTypeMeta() };
|
||||
|
||||
void processMaterials();
|
||||
};
|
||||
|
||||
} } // namespace
|
||||
|
|
|
@ -54,8 +54,7 @@ bool ShapeEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPoin
|
|||
if (_lastUserData != entity->getUserData()) {
|
||||
return true;
|
||||
}
|
||||
glm::vec4 newColor(toGlm(entity->getXColor()), entity->getLocalRenderAlpha());
|
||||
if (newColor != _color) {
|
||||
if (_material != entity->getMaterial()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -78,7 +77,9 @@ void ShapeEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
|
|||
_procedural.setProceduralData(ProceduralData::parse(_lastUserData));
|
||||
}
|
||||
|
||||
_color = vec4(toGlm(entity->getXColor()), entity->getLocalRenderAlpha());
|
||||
removeMaterial(_material, 0);
|
||||
_material = entity->getMaterial();
|
||||
addMaterial(_material, 0);
|
||||
|
||||
_shape = entity->getShape();
|
||||
_position = entity->getWorldPosition();
|
||||
|
@ -112,14 +113,13 @@ bool ShapeEntityRenderer::isTransparent() const {
|
|||
return Parent::isTransparent();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ShapeEntityRenderer::doRender(RenderArgs* args) {
|
||||
PerformanceTimer perfTimer("RenderableShapeEntityItem::render");
|
||||
Q_ASSERT(args->_batch);
|
||||
|
||||
gpu::Batch& batch = *args->_batch;
|
||||
|
||||
std::shared_ptr<graphics::Material> mat;
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
GeometryCache::Shape geometryShape;
|
||||
bool proceduralRender = false;
|
||||
|
@ -127,15 +127,22 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) {
|
|||
withReadLock([&] {
|
||||
geometryShape = geometryCache->getShapeForEntityShape(_shape);
|
||||
batch.setModelTransform(_renderTransform); // use a transform with scale, rotation, registration point and translation
|
||||
outColor = _color;
|
||||
if (_procedural.isReady()) {
|
||||
_procedural.prepare(batch, _position, _dimensions, _orientation);
|
||||
outColor = _procedural.getColor(_color);
|
||||
outColor.a *= _procedural.isFading() ? Interpolate::calculateFadeRatio(_procedural.getFadeStartTime()) : 1.0f;
|
||||
proceduralRender = true;
|
||||
mat = _materials[0].top();
|
||||
if (mat) {
|
||||
outColor = glm::vec4(mat->getAlbedo(), mat->getOpacity());
|
||||
if (_procedural.isReady()) {
|
||||
_procedural.prepare(batch, _position, _dimensions, _orientation);
|
||||
outColor = _procedural.getColor(outColor);
|
||||
outColor.a *= _procedural.isFading() ? Interpolate::calculateFadeRatio(_procedural.getFadeStartTime()) : 1.0f;
|
||||
proceduralRender = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (!mat) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (proceduralRender) {
|
||||
if (render::ShapeKey(args->_globalShapeKey).isWireframe()) {
|
||||
geometryCache->renderWireShape(batch, geometryShape, outColor);
|
||||
|
|
|
@ -34,7 +34,7 @@ private:
|
|||
QString _lastUserData;
|
||||
Transform _renderTransform;
|
||||
entity::Shape _shape { entity::Sphere };
|
||||
glm::vec4 _color;
|
||||
std::shared_ptr<graphics::Material> _material;
|
||||
glm::vec3 _position;
|
||||
glm::vec3 _dimensions;
|
||||
glm::quat _orientation;
|
||||
|
|
|
@ -93,7 +93,7 @@ bool DeleteEntityOperator::preRecursion(const OctreeElementPointer& element) {
|
|||
// and we can stop searching.
|
||||
if (entityTreeElement == details.containingElement) {
|
||||
EntityItemPointer theEntity = details.entity;
|
||||
bool entityDeleted = entityTreeElement->removeEntityItem(theEntity); // remove it from the element
|
||||
bool entityDeleted = entityTreeElement->removeEntityItem(theEntity, true); // remove it from the element
|
||||
assert(entityDeleted);
|
||||
(void)entityDeleted; // quite warning
|
||||
_tree->clearEntityMapEntry(details.entity->getEntityItemID());
|
||||
|
|
|
@ -60,14 +60,6 @@ EntityItem::EntityItem(const EntityItemID& entityItemID) :
|
|||
}
|
||||
|
||||
EntityItem::~EntityItem() {
|
||||
// clear out any left-over actions
|
||||
EntityTreeElementPointer element = _element; // use local copy of _element for logic below
|
||||
EntityTreePointer entityTree = element ? element->getTree() : nullptr;
|
||||
EntitySimulationPointer simulation = entityTree ? entityTree->getSimulation() : nullptr;
|
||||
if (simulation) {
|
||||
clearActions(simulation);
|
||||
}
|
||||
|
||||
// these pointers MUST be correct at delete, else we probably have a dangling backpointer
|
||||
// to this EntityItem in the corresponding data structure.
|
||||
assert(!_simulated);
|
||||
|
@ -2937,3 +2929,34 @@ void EntityItem::retrieveMarketplacePublicKey() {
|
|||
networkReply->deleteLater();
|
||||
});
|
||||
}
|
||||
|
||||
void EntityItem::preDelete() {
|
||||
// clear out any left-over actions
|
||||
EntityTreeElementPointer element = _element; // use local copy of _element for logic below
|
||||
EntityTreePointer entityTree = element ? element->getTree() : nullptr;
|
||||
EntitySimulationPointer simulation = entityTree ? entityTree->getSimulation() : nullptr;
|
||||
if (simulation) {
|
||||
clearActions(simulation);
|
||||
}
|
||||
}
|
||||
|
||||
void EntityItem::addMaterial(graphics::MaterialPointer material, quint16 shapeID) {
|
||||
std::lock_guard<std::mutex> lock(_materialsLock);
|
||||
_materials[shapeID].push(material);
|
||||
emit addMaterialToRenderItem(material, shapeID);
|
||||
}
|
||||
|
||||
void EntityItem::removeMaterial(graphics::MaterialPointer material, quint16 shapeID) {
|
||||
std::lock_guard<std::mutex> lock(_materialsLock);
|
||||
_materials[shapeID].remove(material);
|
||||
emit removeMaterialFromRenderItem(material, shapeID);
|
||||
}
|
||||
|
||||
std::unordered_map<quint16, graphics::MultiMaterial> EntityItem::getMaterials() {
|
||||
std::unordered_map<quint16, graphics::MultiMaterial> toReturn;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_materialsLock);
|
||||
toReturn = _materials;
|
||||
}
|
||||
return toReturn;
|
||||
}
|
|
@ -36,6 +36,8 @@
|
|||
#include "SimulationFlags.h"
|
||||
#include "EntityDynamicInterface.h"
|
||||
|
||||
#include "graphics/Material.h"
|
||||
|
||||
class EntitySimulation;
|
||||
class EntityTreeElement;
|
||||
class EntityTreeElementExtraEncodeData;
|
||||
|
@ -49,7 +51,6 @@ typedef std::shared_ptr<EntityTreeElement> EntityTreeElementPointer;
|
|||
using EntityTreeElementExtraEncodeDataPointer = std::shared_ptr<EntityTreeElementExtraEncodeData>;
|
||||
|
||||
|
||||
|
||||
#define DONT_ALLOW_INSTANTIATION virtual void pureVirtualFunctionPlaceHolder() = 0;
|
||||
#define ALLOW_INSTANTIATION virtual void pureVirtualFunctionPlaceHolder() override { };
|
||||
|
||||
|
@ -443,10 +444,10 @@ public:
|
|||
void scriptHasUnloaded() { _loadedScript = ""; _loadedScriptTimestamp = 0; }
|
||||
|
||||
bool getClientOnly() const { return _clientOnly; }
|
||||
void setClientOnly(bool clientOnly) { _clientOnly = clientOnly; }
|
||||
virtual void setClientOnly(bool clientOnly) { _clientOnly = clientOnly; }
|
||||
// if this entity is client-only, which avatar is it associated with?
|
||||
QUuid getOwningAvatarID() const { return _owningAvatarID; }
|
||||
void setOwningAvatarID(const QUuid& owningAvatarID) { _owningAvatarID = owningAvatarID; }
|
||||
virtual void setOwningAvatarID(const QUuid& owningAvatarID) { _owningAvatarID = owningAvatarID; }
|
||||
|
||||
virtual bool wantsHandControllerPointerEvents() const { return false; }
|
||||
virtual bool wantsKeyboardFocus() const { return false; }
|
||||
|
@ -477,8 +478,18 @@ public:
|
|||
void setCauterized(bool value) { _cauterized = value; }
|
||||
bool getCauterized() const { return _cauterized; }
|
||||
|
||||
virtual void postAdd() {}
|
||||
virtual void preDelete();
|
||||
virtual void postParentFixup() {}
|
||||
|
||||
void addMaterial(graphics::MaterialPointer material, quint16 shapeID);
|
||||
void removeMaterial(graphics::MaterialPointer material, quint16 shapeID);
|
||||
std::unordered_map<quint16, graphics::MultiMaterial> getMaterials();
|
||||
|
||||
signals:
|
||||
void requestRenderUpdate();
|
||||
void addMaterialToRenderItem(graphics::MaterialPointer material, quint16 shapeID);
|
||||
void removeMaterialFromRenderItem(graphics::MaterialPointer material, quint16 shapeID);
|
||||
|
||||
protected:
|
||||
QHash<ChangeHandlerId, ChangeHandlerCallback> _changeHandlers;
|
||||
|
@ -631,6 +642,11 @@ protected:
|
|||
quint64 _lastUpdatedQueryAACubeTimestamp { 0 };
|
||||
|
||||
bool _cauterized { false }; // if true, don't draw because it would obscure 1st-person camera
|
||||
|
||||
private:
|
||||
std::unordered_map<quint16, graphics::MultiMaterial> _materials;
|
||||
std::mutex _materialsLock;
|
||||
|
||||
};
|
||||
|
||||
#endif // hifi_EntityItem_h
|
||||
|
|
|
@ -360,7 +360,9 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
|
|||
CHECK_PROPERTY_CHANGE(PROP_MATERIAL_BLEND_FACTOR, blendFactor);
|
||||
CHECK_PROPERTY_CHANGE(PROP_MATERIAL_PRIORITY, priority);
|
||||
CHECK_PROPERTY_CHANGE(PROP_PARENT_SHAPE_ID, shapeID);
|
||||
CHECK_PROPERTY_CHANGE(PROP_MATERIAL_BOUNDS, materialBounds);
|
||||
CHECK_PROPERTY_CHANGE(PROP_MATERIAL_POS, materialPos);
|
||||
CHECK_PROPERTY_CHANGE(PROP_MATERIAL_SCALE, materialScale);
|
||||
CHECK_PROPERTY_CHANGE(PROP_MATERIAL_ROT, materialRot);
|
||||
|
||||
// Certifiable Properties
|
||||
CHECK_PROPERTY_CHANGE(PROP_ITEM_NAME, itemName);
|
||||
|
@ -664,7 +666,9 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool
|
|||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MATERIAL_BLEND_FACTOR, blendFactor);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MATERIAL_PRIORITY, priority);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_PARENT_SHAPE_ID, shapeID);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MATERIAL_BOUNDS, materialBounds);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MATERIAL_POS, materialPos);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MATERIAL_SCALE, materialScale);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MATERIAL_ROT, materialRot);
|
||||
}
|
||||
|
||||
if (!skipDefaults && !strictSemantics) {
|
||||
|
@ -801,11 +805,13 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool
|
|||
COPY_PROPERTY_FROM_QSCRIPTVALUE(radiusFinish, float, setRadiusFinish);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(relayParentJoints, bool, setRelayParentJoints);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(materialURL, QString, setMaterialURL);
|
||||
COPY_PROPERTY_FROM_QSCRITPTVALUE_ENUM(materialMode, MaterialMode, setMaterialMode);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(materialMode, MaterialMode);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(blendFactor, float, setBlendFactor);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(priority, int, setPriority);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(shapeID, int, setShapeID);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(materialBounds, glmVec4, setMaterialBounds);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(priority, quint16, setPriority);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(shapeID, quint16, setShapeID);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(materialPos, glmVec2, setMaterialPos);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(materialScale, glmVec2, setMaterialScale);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(materialRot, float, setMaterialRot);
|
||||
|
||||
// Certifiable Properties
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(itemName, QString, setItemName);
|
||||
|
@ -1163,9 +1169,11 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue
|
|||
ADD_PROPERTY_TO_MAP(PROP_MATERIAL_URL, MaterialURL, materialURL, QString);
|
||||
ADD_PROPERTY_TO_MAP(PROP_MATERIAL_TYPE, MaterialMode, materialMode, MaterialMode);
|
||||
ADD_PROPERTY_TO_MAP(PROP_MATERIAL_BLEND_FACTOR, BlendFactor, blendFactor, float);
|
||||
ADD_PROPERTY_TO_MAP(PROP_MATERIAL_PRIORITY, Priority, priority, uint32_t);
|
||||
ADD_PROPERTY_TO_MAP(PROP_PARENT_SHAPE_ID, ShapeID, shapeID, uint32_t);
|
||||
ADD_PROPERTY_TO_MAP(PROP_MATERIAL_BOUNDS, MaterialBounds, materialBounds, glmVec4);
|
||||
ADD_PROPERTY_TO_MAP(PROP_MATERIAL_PRIORITY, Priority, priority, quint16);
|
||||
ADD_PROPERTY_TO_MAP(PROP_PARENT_SHAPE_ID, ShapeID, shapeID, quint16);
|
||||
ADD_PROPERTY_TO_MAP(PROP_MATERIAL_POS, MaterialPos, materialPos, glmVec2);
|
||||
ADD_PROPERTY_TO_MAP(PROP_MATERIAL_SCALE, MaterialScale, materialScale, glmVec2);
|
||||
ADD_PROPERTY_TO_MAP(PROP_MATERIAL_ROT, MaterialRot, materialRot, float);
|
||||
|
||||
// Certifiable Properties
|
||||
ADD_PROPERTY_TO_MAP(PROP_ITEM_NAME, ItemName, itemName, QString);
|
||||
|
@ -1557,7 +1565,9 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy
|
|||
APPEND_ENTITY_PROPERTY(PROP_MATERIAL_BLEND_FACTOR, properties.getBlendFactor());
|
||||
APPEND_ENTITY_PROPERTY(PROP_MATERIAL_PRIORITY, properties.getPriority());
|
||||
APPEND_ENTITY_PROPERTY(PROP_PARENT_SHAPE_ID, properties.getShapeID());
|
||||
APPEND_ENTITY_PROPERTY(PROP_MATERIAL_BOUNDS, properties.getMaterialBounds());
|
||||
APPEND_ENTITY_PROPERTY(PROP_MATERIAL_POS, properties.getMaterialPos());
|
||||
APPEND_ENTITY_PROPERTY(PROP_MATERIAL_SCALE, properties.getMaterialScale());
|
||||
APPEND_ENTITY_PROPERTY(PROP_MATERIAL_ROT, properties.getMaterialRot());
|
||||
}
|
||||
|
||||
APPEND_ENTITY_PROPERTY(PROP_NAME, properties.getName());
|
||||
|
@ -1921,9 +1931,11 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
|
|||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MATERIAL_URL, QString, setMaterialURL);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MATERIAL_TYPE, MaterialMode, setMaterialMode);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MATERIAL_BLEND_FACTOR, float, setBlendFactor);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MATERIAL_PRIORITY, uint32_t, setPriority);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_PARENT_SHAPE_ID, uint32_t, setShapeID);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MATERIAL_BOUNDS, glmVec4, setMaterialBounds);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MATERIAL_PRIORITY, quint16, setPriority);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_PARENT_SHAPE_ID, quint16, setShapeID);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MATERIAL_POS, glmVec2, setMaterialPos);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MATERIAL_SCALE, glmVec2, setMaterialScale);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MATERIAL_ROT, float, setMaterialRot);
|
||||
}
|
||||
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_NAME, QString, setName);
|
||||
|
@ -2104,7 +2116,9 @@ void EntityItemProperties::markAllChanged() {
|
|||
_blendFactorChanged = true;
|
||||
_priorityChanged = true;
|
||||
_shapeIDChanged = true;
|
||||
_materialBoundsChanged = true;
|
||||
_materialPosChanged = true;
|
||||
_materialScaleChanged = true;
|
||||
_materialRotChanged = true;
|
||||
|
||||
// Certifiable Properties
|
||||
_itemNameChanged = true;
|
||||
|
@ -2444,8 +2458,14 @@ QList<QString> EntityItemProperties::listChangedProperties() {
|
|||
if (shapeIDChanged()) {
|
||||
out += "shapeID";
|
||||
}
|
||||
if (materialBoundsChanged()) {
|
||||
out += "materialBounds";
|
||||
if (materialPosChanged()) {
|
||||
out += "materialPos";
|
||||
}
|
||||
if (materialScaleChanged()) {
|
||||
out += "materialScale";
|
||||
}
|
||||
if (materialRotChanged()) {
|
||||
out += "materialRot";
|
||||
}
|
||||
|
||||
// Certifiable Properties
|
||||
|
|
|
@ -225,9 +225,11 @@ public:
|
|||
DEFINE_PROPERTY_REF(PROP_MATERIAL_URL, MaterialURL, materialURL, QString, "");
|
||||
DEFINE_PROPERTY_REF_ENUM(PROP_MATERIAL_TYPE, MaterialMode, materialMode, MaterialMode, UV);
|
||||
DEFINE_PROPERTY_REF(PROP_MATERIAL_BLEND_FACTOR, BlendFactor, blendFactor, float, 1.0f);
|
||||
DEFINE_PROPERTY_REF(PROP_MATERIAL_PRIORITY, Priority, priority, uint32_t, 0);
|
||||
DEFINE_PROPERTY_REF(PROP_PARENT_SHAPE_ID, ShapeID, shapeID, uint32_t, 0);
|
||||
DEFINE_PROPERTY_REF(PROP_MATERIAL_BOUNDS, MaterialBounds, materialBounds, glmVec4, glm::vec4(0, 0, 1, 1));
|
||||
DEFINE_PROPERTY_REF(PROP_MATERIAL_PRIORITY, Priority, priority, quint16, 0);
|
||||
DEFINE_PROPERTY_REF(PROP_PARENT_SHAPE_ID, ShapeID, shapeID, quint16, 0);
|
||||
DEFINE_PROPERTY_REF(PROP_MATERIAL_POS, MaterialPos, materialPos, glmVec2, glm::vec2(0, 0));
|
||||
DEFINE_PROPERTY_REF(PROP_MATERIAL_SCALE, MaterialScale, materialScale, glmVec2, glm::vec2(1, 1));
|
||||
DEFINE_PROPERTY_REF(PROP_MATERIAL_ROT, MaterialRot, materialRot, float, 0);
|
||||
|
||||
// Certifiable Properties - related to Proof of Purchase certificates
|
||||
DEFINE_PROPERTY_REF(PROP_ITEM_NAME, ItemName, itemName, QString, ENTITY_ITEM_DEFAULT_ITEM_NAME);
|
||||
|
|
|
@ -101,6 +101,7 @@
|
|||
changedProperties += P; \
|
||||
}
|
||||
|
||||
inline QScriptValue convertScriptValue(QScriptEngine* e, const glm::vec2& v) { return vec2toScriptValue(e, v); }
|
||||
inline QScriptValue convertScriptValue(QScriptEngine* e, const glm::vec3& v) { return vec3toScriptValue(e, v); }
|
||||
inline QScriptValue convertScriptValue(QScriptEngine* e, float v) { return QScriptValue(v); }
|
||||
inline QScriptValue convertScriptValue(QScriptEngine* e, int v) { return QScriptValue(v); }
|
||||
|
@ -183,8 +184,8 @@ inline QScriptValue convertScriptValue(QScriptEngine* e, const AACube& v) { retu
|
|||
properties.setProperty(#P, V); \
|
||||
}
|
||||
|
||||
typedef glm::vec2 glmVec2;
|
||||
typedef glm::vec3 glmVec3;
|
||||
typedef glm::vec4 glmVec4;
|
||||
typedef glm::quat glmQuat;
|
||||
typedef QVector<glm::vec3> qVectorVec3;
|
||||
typedef QVector<glm::quat> qVectorQuat;
|
||||
|
@ -222,6 +223,23 @@ inline QByteArray QByteArray_convertFromScriptValue(const QScriptValue& v, bool&
|
|||
return QByteArray::fromBase64(b64.toUtf8());
|
||||
}
|
||||
|
||||
inline glmVec2 glmVec2_convertFromScriptValue(const QScriptValue& v, bool& isValid) {
|
||||
isValid = false; /// assume it can't be converted
|
||||
QScriptValue x = v.property("x");
|
||||
QScriptValue y = v.property("y");
|
||||
if (x.isValid() && y.isValid()) {
|
||||
glm::vec4 newValue(0);
|
||||
newValue.x = x.toVariant().toFloat();
|
||||
newValue.y = y.toVariant().toFloat();
|
||||
isValid = !glm::isnan(newValue.x) &&
|
||||
!glm::isnan(newValue.y);
|
||||
if (isValid) {
|
||||
return newValue;
|
||||
}
|
||||
}
|
||||
return glm::vec2(0);
|
||||
}
|
||||
|
||||
inline glmVec3 glmVec3_convertFromScriptValue(const QScriptValue& v, bool& isValid) {
|
||||
isValid = false; /// assume it can't be converted
|
||||
QScriptValue x = v.property("x");
|
||||
|
@ -242,29 +260,6 @@ inline glmVec3 glmVec3_convertFromScriptValue(const QScriptValue& v, bool& isVal
|
|||
return glm::vec3(0);
|
||||
}
|
||||
|
||||
inline glmVec4 glmVec4_convertFromScriptValue(const QScriptValue& v, bool& isValid) {
|
||||
isValid = false; /// assume it can't be converted
|
||||
QScriptValue x = v.property("x");
|
||||
QScriptValue y = v.property("y");
|
||||
QScriptValue z = v.property("z");
|
||||
QScriptValue w = v.property("w");
|
||||
if (x.isValid() && y.isValid() && z.isValid() && w.isValid()) {
|
||||
glm::vec4 newValue(0);
|
||||
newValue.x = x.toVariant().toFloat();
|
||||
newValue.y = y.toVariant().toFloat();
|
||||
newValue.z = z.toVariant().toFloat();
|
||||
newValue.w = w.toVariant().toFloat();
|
||||
isValid = !glm::isnan(newValue.x) &&
|
||||
!glm::isnan(newValue.y) &&
|
||||
!glm::isnan(newValue.z) &&
|
||||
!glm::isnan(newValue.w);
|
||||
if (isValid) {
|
||||
return newValue;
|
||||
}
|
||||
}
|
||||
return glm::vec4(0);
|
||||
}
|
||||
|
||||
inline AACube AACube_convertFromScriptValue(const QScriptValue& v, bool& isValid) {
|
||||
isValid = true;
|
||||
AACube result;
|
||||
|
|
|
@ -232,7 +232,9 @@ enum EntityPropertyList {
|
|||
PROP_MATERIAL_BLEND_FACTOR,
|
||||
PROP_MATERIAL_PRIORITY,
|
||||
PROP_PARENT_SHAPE_ID,
|
||||
PROP_MATERIAL_BOUNDS,
|
||||
PROP_MATERIAL_POS,
|
||||
PROP_MATERIAL_SCALE,
|
||||
PROP_MATERIAL_ROT,
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// ATTENTION: add new properties to end of list just ABOVE this line
|
||||
|
|
|
@ -1732,15 +1732,19 @@ void EntityTree::fixupNeedsParentFixups() {
|
|||
}
|
||||
});
|
||||
entity->locationChanged(true);
|
||||
} else if (getIsServer() && _avatarIDs.contains(entity->getParentID())) {
|
||||
// this is a child of an avatar, which the entity server will never have
|
||||
// a SpatiallyNestable object for. Add it to a list for cleanup when the avatar leaves.
|
||||
if (!_childrenOfAvatars.contains(entity->getParentID())) {
|
||||
_childrenOfAvatars[entity->getParentID()] = QSet<EntityItemID>();
|
||||
entity->postParentFixup();
|
||||
} else if (_avatarIDs.contains(entity->getParentID())) {
|
||||
if (getIsServer()) {
|
||||
// this is a child of an avatar, which the entity server will never have
|
||||
// a SpatiallyNestable object for. Add it to a list for cleanup when the avatar leaves.
|
||||
if (!_childrenOfAvatars.contains(entity->getParentID())) {
|
||||
_childrenOfAvatars[entity->getParentID()] = QSet<EntityItemID>();
|
||||
}
|
||||
_childrenOfAvatars[entity->getParentID()] += entity->getEntityItemID();
|
||||
}
|
||||
_childrenOfAvatars[entity->getParentID()] += entity->getEntityItemID();
|
||||
doMove = true;
|
||||
iter.remove(); // and pull it out of the list
|
||||
entity->postParentFixup();
|
||||
}
|
||||
|
||||
if (queryAACubeSuccess && doMove) {
|
||||
|
@ -2378,3 +2382,35 @@ QStringList EntityTree::getJointNames(const QUuid& entityID) const {
|
|||
return entity->getJointNames();
|
||||
}
|
||||
|
||||
std::function<bool(const QUuid&, graphics::MaterialPointer, quint16)> EntityTree::_addMaterialToAvatarOperator = nullptr;
|
||||
std::function<bool(const QUuid&, graphics::MaterialPointer, quint16)> EntityTree::_removeMaterialFromAvatarOperator = nullptr;
|
||||
std::function<bool(const QUuid&, graphics::MaterialPointer, quint16)> EntityTree::_addMaterialToOverlayOperator = nullptr;
|
||||
std::function<bool(const QUuid&, graphics::MaterialPointer, quint16)> EntityTree::_removeMaterialFromOverlayOperator = nullptr;
|
||||
|
||||
bool EntityTree::addMaterialToAvatar(const QUuid& avatarID, graphics::MaterialPointer material, quint16 shapeID) {
|
||||
if (_addMaterialToAvatarOperator) {
|
||||
return _addMaterialToAvatarOperator(avatarID, material, shapeID);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool EntityTree::removeMaterialFromAvatar(const QUuid& avatarID, graphics::MaterialPointer material, quint16 shapeID) {
|
||||
if (_removeMaterialFromAvatarOperator) {
|
||||
return _removeMaterialFromAvatarOperator(avatarID, material, shapeID);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool EntityTree::addMaterialToOverlay(const QUuid& overlayID, graphics::MaterialPointer material, quint16 shapeID) {
|
||||
if (_addMaterialToOverlayOperator) {
|
||||
return _addMaterialToOverlayOperator(overlayID, material, shapeID);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool EntityTree::removeMaterialFromOverlay(const QUuid& overlayID, graphics::MaterialPointer material, quint16 shapeID) {
|
||||
if (_removeMaterialFromOverlayOperator) {
|
||||
return _removeMaterialFromOverlayOperator(overlayID, material, shapeID);
|
||||
}
|
||||
return false;
|
||||
}
|
|
@ -280,6 +280,16 @@ public:
|
|||
|
||||
void setMyAvatar(std::shared_ptr<AvatarData> myAvatar) { _myAvatar = myAvatar; }
|
||||
|
||||
static void setAddMaterialToAvatarOperator(std::function<bool(const QUuid&, graphics::MaterialPointer, quint16)> addMaterialToAvatarOperator) { _addMaterialToAvatarOperator = addMaterialToAvatarOperator; }
|
||||
static void setRemoveMaterialFromAvatarOperator(std::function<bool(const QUuid&, graphics::MaterialPointer, quint16)> removeMaterialFromAvatarOperator) { _removeMaterialFromAvatarOperator = removeMaterialFromAvatarOperator; }
|
||||
static bool addMaterialToAvatar(const QUuid& avatarID, graphics::MaterialPointer material, quint16 shapeID);
|
||||
static bool removeMaterialFromAvatar(const QUuid& avatarID, graphics::MaterialPointer material, quint16 shapeID);
|
||||
|
||||
static void setAddMaterialToOverlayOperator(std::function<bool(const QUuid&, graphics::MaterialPointer, quint16)> addMaterialToOverlayOperator) { _addMaterialToOverlayOperator = addMaterialToOverlayOperator; }
|
||||
static void setRemoveMaterialFromOverlayOperator(std::function<bool(const QUuid&, graphics::MaterialPointer, quint16)> removeMaterialFromOverlayOperator) { _removeMaterialFromOverlayOperator = removeMaterialFromOverlayOperator; }
|
||||
static bool addMaterialToOverlay(const QUuid& overlayID, graphics::MaterialPointer material, quint16 shapeID);
|
||||
static bool removeMaterialFromOverlay(const QUuid& overlayID, graphics::MaterialPointer material, quint16 shapeID);
|
||||
|
||||
signals:
|
||||
void deletingEntity(const EntityItemID& entityID);
|
||||
void deletingEntityPointer(EntityItem* entityID);
|
||||
|
@ -387,6 +397,11 @@ private:
|
|||
void validatePop(const QString& certID, const EntityItemID& entityItemID, const SharedNodePointer& senderNode, bool isRetryingValidation);
|
||||
|
||||
std::shared_ptr<AvatarData> _myAvatar{ nullptr };
|
||||
|
||||
static std::function<bool(const QUuid&, graphics::MaterialPointer, quint16)> _addMaterialToAvatarOperator;
|
||||
static std::function<bool(const QUuid&, graphics::MaterialPointer, quint16)> _removeMaterialFromAvatarOperator;
|
||||
static std::function<bool(const QUuid&, graphics::MaterialPointer, quint16)> _addMaterialToOverlayOperator;
|
||||
static std::function<bool(const QUuid&, graphics::MaterialPointer, quint16)> _removeMaterialFromOverlayOperator;
|
||||
};
|
||||
|
||||
#endif // hifi_EntityTree_h
|
||||
|
|
|
@ -896,6 +896,7 @@ EntityItemPointer EntityTreeElement::getEntityWithEntityItemID(const EntityItemI
|
|||
void EntityTreeElement::cleanupEntities() {
|
||||
withWriteLock([&] {
|
||||
foreach(EntityItemPointer entity, _entityItems) {
|
||||
entity->preDelete();
|
||||
// NOTE: only EntityTreeElement should ever be changing the value of entity->_element
|
||||
// NOTE: We explicitly don't delete the EntityItem here because since we only
|
||||
// access it by smart pointers, when we remove it from the _entityItems
|
||||
|
@ -907,26 +908,10 @@ void EntityTreeElement::cleanupEntities() {
|
|||
bumpChangedContent();
|
||||
}
|
||||
|
||||
bool EntityTreeElement::removeEntityWithEntityItemID(const EntityItemID& id) {
|
||||
bool foundEntity = false;
|
||||
withWriteLock([&] {
|
||||
uint16_t numberOfEntities = _entityItems.size();
|
||||
for (uint16_t i = 0; i < numberOfEntities; i++) {
|
||||
EntityItemPointer& entity = _entityItems[i];
|
||||
if (entity->getEntityItemID() == id) {
|
||||
foundEntity = true;
|
||||
// NOTE: only EntityTreeElement should ever be changing the value of entity->_element
|
||||
entity->_element = NULL;
|
||||
_entityItems.removeAt(i);
|
||||
bumpChangedContent();
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
return foundEntity;
|
||||
}
|
||||
|
||||
bool EntityTreeElement::removeEntityItem(EntityItemPointer entity) {
|
||||
bool EntityTreeElement::removeEntityItem(EntityItemPointer entity, bool deletion) {
|
||||
if (deletion) {
|
||||
entity->preDelete();
|
||||
}
|
||||
int numEntries = 0;
|
||||
withWriteLock([&] {
|
||||
numEntries = _entityItems.removeAll(entity);
|
||||
|
@ -955,6 +940,7 @@ void EntityTreeElement::addEntityItem(EntityItemPointer entity) {
|
|||
});
|
||||
bumpChangedContent();
|
||||
entity->_element = getThisPointer();
|
||||
entity->postAdd();
|
||||
}
|
||||
|
||||
// will average a "common reduced LOD view" from the the child elements...
|
||||
|
|
|
@ -210,8 +210,7 @@ public:
|
|||
void getEntitiesInside(const AACube& box, QVector<EntityItemPointer>& foundEntities);
|
||||
|
||||
void cleanupEntities(); /// called by EntityTree on cleanup this will free all entities
|
||||
bool removeEntityWithEntityItemID(const EntityItemID& id);
|
||||
bool removeEntityItem(EntityItemPointer entity);
|
||||
bool removeEntityItem(EntityItemPointer entity, bool deletion = false);
|
||||
|
||||
bool containsEntityBounds(EntityItemPointer entity) const;
|
||||
bool bestFitEntityBounds(EntityItemPointer entity) const;
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
EntityItemPointer MaterialEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
Pointer entity(new MaterialEntityItem(entityID), [](EntityItem* ptr) { ptr->deleteLater(); });
|
||||
entity->setProperties(properties);
|
||||
// When you reload content, setProperties doesn't have any of the propertiesChanged flags set, so it won't trigger a material add
|
||||
entity->removeMaterial();
|
||||
entity->applyMaterial();
|
||||
return entity;
|
||||
}
|
||||
|
||||
|
@ -31,7 +34,9 @@ EntityItemProperties MaterialEntityItem::getProperties(EntityPropertyFlags desir
|
|||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(blendFactor, getBlendFactor);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(priority, getPriority);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(shapeID, getShapeID);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(materialBounds, getMaterialBounds);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(materialPos, getMaterialPos);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(materialScale, getMaterialScale);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(materialRot, getMaterialRot);
|
||||
return properties;
|
||||
}
|
||||
|
||||
|
@ -43,7 +48,9 @@ bool MaterialEntityItem::setProperties(const EntityItemProperties& properties) {
|
|||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(blendFactor, setBlendFactor);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(priority, setPriority);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(shapeID, setShapeID);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(materialBounds, setMaterialBounds);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(materialPos, setMaterialPos);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(materialScale, setMaterialScale);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(materialRot, setMaterialRot);
|
||||
|
||||
if (somethingChanged) {
|
||||
bool wantDebug = false;
|
||||
|
@ -202,9 +209,11 @@ int MaterialEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* da
|
|||
READ_ENTITY_PROPERTY(PROP_MATERIAL_URL, QString, setMaterialURL);
|
||||
READ_ENTITY_PROPERTY(PROP_MATERIAL_TYPE, MaterialMode, setMaterialMode);
|
||||
READ_ENTITY_PROPERTY(PROP_MATERIAL_BLEND_FACTOR, float, setBlendFactor);
|
||||
READ_ENTITY_PROPERTY(PROP_MATERIAL_PRIORITY, uint32_t, setPriority);
|
||||
READ_ENTITY_PROPERTY(PROP_PARENT_SHAPE_ID, uint32_t, setShapeID);
|
||||
READ_ENTITY_PROPERTY(PROP_MATERIAL_BOUNDS, glm::vec4, setMaterialBounds);
|
||||
READ_ENTITY_PROPERTY(PROP_MATERIAL_PRIORITY, quint16, setPriority);
|
||||
READ_ENTITY_PROPERTY(PROP_PARENT_SHAPE_ID, quint16, setShapeID);
|
||||
READ_ENTITY_PROPERTY(PROP_MATERIAL_POS, glm::vec2, setMaterialPos);
|
||||
READ_ENTITY_PROPERTY(PROP_MATERIAL_SCALE, glm::vec2, setMaterialScale);
|
||||
READ_ENTITY_PROPERTY(PROP_MATERIAL_ROT, float, setMaterialRot);
|
||||
|
||||
return bytesRead;
|
||||
}
|
||||
|
@ -218,7 +227,9 @@ EntityPropertyFlags MaterialEntityItem::getEntityProperties(EncodeBitstreamParam
|
|||
requestedProperties += PROP_MATERIAL_BLEND_FACTOR;
|
||||
requestedProperties += PROP_MATERIAL_PRIORITY;
|
||||
requestedProperties += PROP_PARENT_SHAPE_ID;
|
||||
requestedProperties += PROP_MATERIAL_BOUNDS;
|
||||
requestedProperties += PROP_MATERIAL_POS;
|
||||
requestedProperties += PROP_MATERIAL_SCALE;
|
||||
requestedProperties += PROP_MATERIAL_ROT;
|
||||
return requestedProperties;
|
||||
}
|
||||
|
||||
|
@ -234,9 +245,11 @@ void MaterialEntityItem::appendSubclassData(OctreePacketData* packetData, Encode
|
|||
APPEND_ENTITY_PROPERTY(PROP_MATERIAL_URL, getMaterialURL());
|
||||
APPEND_ENTITY_PROPERTY(PROP_MATERIAL_TYPE, (uint32_t)getMaterialMode());
|
||||
APPEND_ENTITY_PROPERTY(PROP_MATERIAL_BLEND_FACTOR, getBlendFactor());
|
||||
APPEND_ENTITY_PROPERTY(PROP_MATERIAL_PRIORITY, (uint32_t)getPriority());
|
||||
APPEND_ENTITY_PROPERTY(PROP_PARENT_SHAPE_ID, (uint32_t)getShapeID());
|
||||
APPEND_ENTITY_PROPERTY(PROP_MATERIAL_BOUNDS, getMaterialBounds());
|
||||
APPEND_ENTITY_PROPERTY(PROP_MATERIAL_PRIORITY, getPriority());
|
||||
APPEND_ENTITY_PROPERTY(PROP_PARENT_SHAPE_ID, getShapeID());
|
||||
APPEND_ENTITY_PROPERTY(PROP_MATERIAL_POS, getMaterialPos());
|
||||
APPEND_ENTITY_PROPERTY(PROP_MATERIAL_SCALE, getMaterialScale());
|
||||
APPEND_ENTITY_PROPERTY(PROP_MATERIAL_ROT, getMaterialRot());
|
||||
}
|
||||
|
||||
void MaterialEntityItem::debugDump() const {
|
||||
|
@ -249,7 +262,9 @@ void MaterialEntityItem::debugDump() const {
|
|||
qCDebug(entities) << " blend factor:" << _blendFactor;
|
||||
qCDebug(entities) << " priority:" << _priority;
|
||||
qCDebug(entities) << " parent shape ID:" << _shapeID;
|
||||
qCDebug(entities) << " material bounds:" << _materialBounds;
|
||||
qCDebug(entities) << " material pos:" << _materialPos;
|
||||
qCDebug(entities) << " material scale:" << _materialRot;
|
||||
qCDebug(entities) << " material rot:" << _materialScale;
|
||||
qCDebug(entities) << " position:" << debugTreeVector(getWorldPosition());
|
||||
qCDebug(entities) << " dimensions:" << debugTreeVector(getScaledDimensions());
|
||||
qCDebug(entities) << " getLastEdited:" << debugTime(getLastEdited(), now);
|
||||
|
@ -269,30 +284,38 @@ std::shared_ptr<NetworkMaterial> MaterialEntityItem::getMaterial() const {
|
|||
}
|
||||
}
|
||||
|
||||
void MaterialEntityItem::setMaterialURL(const QString& materialURLString) {
|
||||
if (materialURLString.startsWith("userData")) {
|
||||
QJsonDocument materialJSON = QJsonDocument::fromJson(getUserData().toUtf8());
|
||||
_materials.clear();
|
||||
_materialNames.clear();
|
||||
if (!materialJSON.isNull()) {
|
||||
if (materialJSON.isArray()) {
|
||||
QJsonArray materials = materialJSON.array();
|
||||
for (auto& material : materials) {
|
||||
if (!material.isNull() && material.isObject()) {
|
||||
parseJSONMaterial(material.toObject());
|
||||
void MaterialEntityItem::setMaterialURL(const QString& materialURLString, bool userDataChanged) {
|
||||
bool usingUserData = materialURLString.startsWith("userData");
|
||||
if (_materialURL != materialURLString || (usingUserData && userDataChanged)) {
|
||||
removeMaterial();
|
||||
_materialURL = materialURLString;
|
||||
|
||||
if (usingUserData) {
|
||||
QJsonDocument materialJSON = QJsonDocument::fromJson(getUserData().toUtf8());
|
||||
_materials.clear();
|
||||
_materialNames.clear();
|
||||
if (!materialJSON.isNull()) {
|
||||
if (materialJSON.isArray()) {
|
||||
QJsonArray materials = materialJSON.array();
|
||||
for (auto material : materials) {
|
||||
if (!material.isNull() && material.isObject()) {
|
||||
parseJSONMaterial(material.toObject());
|
||||
}
|
||||
}
|
||||
} else if (materialJSON.isObject()) {
|
||||
parseJSONMaterial(materialJSON.object());
|
||||
}
|
||||
} else if (materialJSON.isObject()) {
|
||||
parseJSONMaterial(materialJSON.object());
|
||||
}
|
||||
} else {
|
||||
// get material via network request
|
||||
}
|
||||
|
||||
// TODO: if URL ends with ?string, try to set _currentMaterialName = string
|
||||
|
||||
// Since our JSON changed, the current name might not be valid anymore, so we need to update
|
||||
setCurrentMaterialName(_currentMaterialName);
|
||||
applyMaterial();
|
||||
}
|
||||
_materialURL = materialURLString;
|
||||
|
||||
// TODO: if URL ends with ?string, set _currentMaterialName = string
|
||||
|
||||
// Since our JSON changed, the current name might not be valid anymore, so we need to update
|
||||
setCurrentMaterialName(_currentMaterialName);
|
||||
}
|
||||
|
||||
void MaterialEntityItem::setCurrentMaterialName(const QString& currentMaterialName) {
|
||||
|
@ -300,14 +323,176 @@ void MaterialEntityItem::setCurrentMaterialName(const QString& currentMaterialNa
|
|||
if (material != _materials.end()) {
|
||||
_currentMaterialName = currentMaterialName;
|
||||
} else if (_materialNames.size() > 0) {
|
||||
setCurrentMaterialName(_materialNames[0]);
|
||||
_currentMaterialName = _materialNames[0];
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialEntityItem::setUserData(const QString& userData) {
|
||||
EntityItem::setUserData(userData);
|
||||
if (_materialURL.startsWith("userData")) {
|
||||
// Trigger material update when user data changes
|
||||
setMaterialURL(_materialURL);
|
||||
if (_userData != userData) {
|
||||
EntityItem::setUserData(userData);
|
||||
if (_materialURL.startsWith("userData")) {
|
||||
// Trigger material update when user data changes
|
||||
setMaterialURL(_materialURL, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialEntityItem::setMaterialPos(const glm::vec2& materialPos) {
|
||||
if (_materialPos != materialPos) {
|
||||
removeMaterial();
|
||||
_materialPos = materialPos;
|
||||
applyMaterial();
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialEntityItem::setMaterialScale(const glm::vec2& materialScale) {
|
||||
if (_materialScale != materialScale) {
|
||||
removeMaterial();
|
||||
_materialScale = materialScale;
|
||||
applyMaterial();
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialEntityItem::setMaterialRot(const float& materialRot) {
|
||||
if (_materialRot != materialRot) {
|
||||
removeMaterial();
|
||||
_materialRot = materialRot;
|
||||
applyMaterial();
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialEntityItem::setBlendFactor(float blendFactor) {
|
||||
if (_blendFactor != blendFactor) {
|
||||
removeMaterial();
|
||||
_blendFactor = blendFactor;
|
||||
applyMaterial();
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialEntityItem::setPriority(quint16 priority) {
|
||||
if (_priority != priority) {
|
||||
removeMaterial();
|
||||
_priority = priority;
|
||||
applyMaterial();
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialEntityItem::setShapeID(quint16 shapeID) {
|
||||
if (_shapeID != shapeID) {
|
||||
removeMaterial();
|
||||
_shapeID = shapeID;
|
||||
applyMaterial();
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialEntityItem::setParentID(const QUuid& parentID) {
|
||||
if (getParentID() != parentID) {
|
||||
removeMaterial();
|
||||
EntityItem::setParentID(parentID);
|
||||
applyMaterial();
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialEntityItem::setClientOnly(bool clientOnly) {
|
||||
if (getClientOnly() != clientOnly) {
|
||||
removeMaterial();
|
||||
EntityItem::setClientOnly(clientOnly);
|
||||
applyMaterial();
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialEntityItem::setOwningAvatarID(const QUuid& owningAvatarID) {
|
||||
if (getOwningAvatarID() != owningAvatarID) {
|
||||
removeMaterial();
|
||||
EntityItem::setOwningAvatarID(owningAvatarID);
|
||||
applyMaterial();
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialEntityItem::removeMaterial() {
|
||||
graphics::MaterialPointer material = getMaterial();
|
||||
QUuid parentID = getClientOnly() ? getOwningAvatarID() : getParentID();
|
||||
if (!material || parentID.isNull()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Our parent could be an entity, an avatar, or an overlay
|
||||
EntityTreePointer tree = getTree();
|
||||
if (tree) {
|
||||
EntityItemPointer entity = tree->findEntityByEntityItemID(parentID);
|
||||
if (entity) {
|
||||
entity->removeMaterial(material, getShapeID());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (EntityTree::removeMaterialFromAvatar(parentID, material, getShapeID())) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (EntityTree::removeMaterialFromOverlay(parentID, material, getShapeID())) {
|
||||
return;
|
||||
}
|
||||
|
||||
// if a remove fails, our parent is gone, so we don't need to retry
|
||||
}
|
||||
|
||||
void MaterialEntityItem::applyMaterial() {
|
||||
_retryApply = false;
|
||||
graphics::MaterialPointer material = getMaterial();
|
||||
QUuid parentID = getClientOnly() ? getOwningAvatarID() : getParentID();
|
||||
if (!material || parentID.isNull()) {
|
||||
return;
|
||||
}
|
||||
Transform textureTransform;
|
||||
textureTransform.setTranslation(glm::vec3(_materialPos, 0));
|
||||
textureTransform.setRotation(glm::vec3(0, 0, glm::radians(_materialRot)));
|
||||
textureTransform.setScale(glm::vec3(_materialScale, 1));
|
||||
material->setTextureTransforms(textureTransform);
|
||||
material->setBlendFactor(getBlendFactor());
|
||||
material->setPriority(getPriority());
|
||||
|
||||
// Our parent could be an entity, an avatar, or an overlay
|
||||
EntityTreePointer tree = getTree();
|
||||
if (tree) {
|
||||
EntityItemPointer entity = tree->findEntityByEntityItemID(parentID);
|
||||
if (entity) {
|
||||
entity->addMaterial(material, getShapeID());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (EntityTree::addMaterialToAvatar(parentID, material, getShapeID())) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (EntityTree::addMaterialToOverlay(parentID, material, getShapeID())) {
|
||||
return;
|
||||
}
|
||||
|
||||
// if we've reached this point, we couldn't find our parent, so we need to try again later
|
||||
_retryApply = true;
|
||||
}
|
||||
|
||||
void MaterialEntityItem::postAdd() {
|
||||
removeMaterial();
|
||||
applyMaterial();
|
||||
}
|
||||
|
||||
void MaterialEntityItem::preDelete() {
|
||||
EntityItem::preDelete();
|
||||
removeMaterial();
|
||||
}
|
||||
|
||||
void MaterialEntityItem::postParentFixup() {
|
||||
removeMaterial();
|
||||
applyMaterial();
|
||||
}
|
||||
|
||||
void MaterialEntityItem::update(const quint64& now) {
|
||||
if (_retryApply) {
|
||||
applyMaterial();
|
||||
}
|
||||
|
||||
EntityItem::update(now);
|
||||
}
|
|
@ -23,6 +23,9 @@ public:
|
|||
|
||||
ALLOW_INSTANTIATION // This class can be instantiated
|
||||
|
||||
void update(const quint64& now) override;
|
||||
bool needsToCallUpdate() const override { return true; }
|
||||
|
||||
// methods for getting/setting all properties of an entity
|
||||
virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const override;
|
||||
virtual bool setProperties(const EntityItemProperties& properties) override;
|
||||
|
@ -49,7 +52,7 @@ public:
|
|||
virtual void setUnscaledDimensions(const glm::vec3& value) override;
|
||||
|
||||
QString getMaterialURL() const { return _materialURL; }
|
||||
void setMaterialURL(const QString& materialURLString);
|
||||
void setMaterialURL(const QString& materialURLString, bool userDataChanged = false);
|
||||
|
||||
QString getCurrentMaterialName() const { return _currentMaterialName; }
|
||||
void setCurrentMaterialName(const QString& currentMaterialName);
|
||||
|
@ -58,33 +61,51 @@ public:
|
|||
void setMaterialMode(MaterialMode mode) { _materialMode = mode; }
|
||||
|
||||
float getBlendFactor() const { return _blendFactor; }
|
||||
void setBlendFactor(float blendFactor) { _blendFactor = blendFactor; }
|
||||
void setBlendFactor(float blendFactor);
|
||||
|
||||
int getPriority() const { return _priority; }
|
||||
void setPriority(int priority) { _priority = priority; }
|
||||
quint16 getPriority() const { return _priority; }
|
||||
void setPriority(quint16 priority);
|
||||
|
||||
int getShapeID() const { return _shapeID; }
|
||||
void setShapeID(int shapeID) { _shapeID = shapeID; }
|
||||
quint16 getShapeID() const { return _shapeID; }
|
||||
void setShapeID(quint16 shapeID);
|
||||
|
||||
glm::vec4 getMaterialBounds() const { return _materialBounds; }
|
||||
void setMaterialBounds(const glm::vec4& materialBounds) { _materialBounds = materialBounds; }
|
||||
glm::vec2 getMaterialPos() const { return _materialPos; }
|
||||
void setMaterialPos(const glm::vec2& materialPos);
|
||||
glm::vec2 getMaterialScale() const { return _materialScale; }
|
||||
void setMaterialScale(const glm::vec2& materialScale);
|
||||
float getMaterialRot() const { return _materialRot; }
|
||||
void setMaterialRot(const float& materialRot);
|
||||
|
||||
std::shared_ptr<NetworkMaterial> getMaterial() const;
|
||||
|
||||
void setUserData(const QString& userData) override;
|
||||
void setParentID(const QUuid& parentID) override;
|
||||
void setClientOnly(bool clientOnly) override;
|
||||
void setOwningAvatarID(const QUuid& owningAvatarID) override;
|
||||
|
||||
void applyMaterial();
|
||||
void removeMaterial();
|
||||
|
||||
void postAdd() override;
|
||||
void preDelete() override;
|
||||
void postParentFixup() override;
|
||||
|
||||
private:
|
||||
QString _materialURL;
|
||||
MaterialMode _materialMode { UV };
|
||||
float _blendFactor { 1.0f };
|
||||
int _priority { 0 };
|
||||
int _shapeID { 0 };
|
||||
glm::vec4 _materialBounds { 0, 0, 1, 1 };
|
||||
quint16 _priority { 0 };
|
||||
quint16 _shapeID { 0 };
|
||||
glm::vec2 _materialPos { 0, 0 };
|
||||
glm::vec2 _materialScale { 1, 1 };
|
||||
float _materialRot { 0 };
|
||||
|
||||
QHash<QString, std::shared_ptr<NetworkMaterial>> _materials;
|
||||
std::vector<QString> _materialNames;
|
||||
QString _currentMaterialName;
|
||||
|
||||
bool _retryApply { false };
|
||||
|
||||
void parseJSONMaterial(const QJsonObject& materialJSON);
|
||||
static bool parseJSONColor(const QJsonValue& array, glm::vec3& color, bool& isSRGB);
|
||||
|
||||
|
|
|
@ -721,4 +721,4 @@ bool ModelEntityItem::isAnimatingSomething() const {
|
|||
_animationProperties.getRunning() &&
|
||||
(_animationProperties.getFPS() != 0.0f);
|
||||
});
|
||||
}
|
||||
}
|
|
@ -85,6 +85,7 @@ EntityItemPointer ShapeEntityItem::sphereFactory(const EntityItemID& entityID, c
|
|||
ShapeEntityItem::ShapeEntityItem(const EntityItemID& entityItemID) : EntityItem(entityItemID) {
|
||||
_type = EntityTypes::Shape;
|
||||
_volumeMultiplier *= PI / 6.0f;
|
||||
_material = std::make_shared<graphics::Material>();
|
||||
}
|
||||
|
||||
EntityItemProperties ShapeEntityItem::getProperties(EntityPropertyFlags desiredProperties) const {
|
||||
|
@ -184,6 +185,7 @@ void ShapeEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBit
|
|||
|
||||
void ShapeEntityItem::setColor(const rgbColor& value) {
|
||||
memcpy(_color, value, sizeof(rgbColor));
|
||||
_material->setAlbedo(glm::vec3(_color[0], _color[1], _color[2]) / 255.0f);
|
||||
}
|
||||
|
||||
xColor ShapeEntityItem::getXColor() const {
|
||||
|
@ -204,6 +206,11 @@ void ShapeEntityItem::setColor(const QColor& value) {
|
|||
setAlpha(value.alpha());
|
||||
}
|
||||
|
||||
void ShapeEntityItem::setAlpha(float alpha) {
|
||||
_alpha = alpha;
|
||||
_material->setOpacity(alpha);
|
||||
}
|
||||
|
||||
void ShapeEntityItem::setUnscaledDimensions(const glm::vec3& value) {
|
||||
const float MAX_FLAT_DIMENSION = 0.0001f;
|
||||
if ((_shape == entity::Shape::Circle || _shape == entity::Shape::Quad) && value.y > MAX_FLAT_DIMENSION) {
|
||||
|
|
|
@ -75,7 +75,7 @@ public:
|
|||
void setShape(const QString& shape) { setShape(entity::shapeFromString(shape)); }
|
||||
|
||||
float getAlpha() const { return _alpha; };
|
||||
void setAlpha(float alpha) { _alpha = alpha; }
|
||||
void setAlpha(float alpha);
|
||||
|
||||
const rgbColor& getColor() const { return _color; }
|
||||
void setColor(const rgbColor& value);
|
||||
|
@ -101,6 +101,8 @@ public:
|
|||
virtual void computeShapeInfo(ShapeInfo& info) override;
|
||||
virtual ShapeType getShapeType() const override;
|
||||
|
||||
std::shared_ptr<graphics::Material> getMaterial() { return _material; }
|
||||
|
||||
protected:
|
||||
|
||||
float _alpha { 1 };
|
||||
|
@ -111,6 +113,8 @@ protected:
|
|||
//! prior functionality where new or unsupported shapes are treated as
|
||||
//! ellipsoids.
|
||||
ShapeType _collisionShapeType{ ShapeType::SHAPE_TYPE_ELLIPSOID };
|
||||
|
||||
std::shared_ptr<graphics::Material> _material;
|
||||
};
|
||||
|
||||
#endif // hifi_ShapeEntityItem_h
|
||||
|
|
|
@ -12,9 +12,13 @@
|
|||
|
||||
#include "TextureMap.h"
|
||||
|
||||
#include <Transform.h>
|
||||
|
||||
using namespace graphics;
|
||||
using namespace gpu;
|
||||
|
||||
int materialPointerMetaID = qRegisterMetaType<MaterialPointer>("graphics::MaterialPointer");
|
||||
|
||||
Material::Material() :
|
||||
_key(0),
|
||||
_schemaBuffer(),
|
||||
|
@ -221,4 +225,15 @@ bool Material::calculateMaterialInfo() const {
|
|||
_hasCalculatedTextureInfo = allTextures;
|
||||
}
|
||||
return _hasCalculatedTextureInfo;
|
||||
}
|
||||
|
||||
void Material::setTextureTransforms(const Transform& transform) {
|
||||
for (auto &textureMapItem : _textureMaps) {
|
||||
if (textureMapItem.second) {
|
||||
textureMapItem.second->setTextureTransform(transform);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < NUM_TEXCOORD_TRANSFORMS; i++) {
|
||||
_texMapArrayBuffer.edit<TexMapArraySchema>()._texcoordTransforms[i] = transform.getMatrix();
|
||||
}
|
||||
}
|
|
@ -15,11 +15,14 @@
|
|||
|
||||
#include <bitset>
|
||||
#include <map>
|
||||
#include <queue>
|
||||
|
||||
#include <ColorUtils.h>
|
||||
|
||||
#include <gpu/Resource.h>
|
||||
|
||||
class Transform;
|
||||
|
||||
namespace graphics {
|
||||
|
||||
class TextureMap;
|
||||
|
@ -351,6 +354,14 @@ public:
|
|||
size_t getTextureSize() const { calculateMaterialInfo(); return _textureSize; }
|
||||
bool hasTextureInfo() const { return _hasCalculatedTextureInfo; }
|
||||
|
||||
void setBlendFactor(float blendFactor) { _blendFactor = blendFactor; }
|
||||
float getBlendFactor() { return _blendFactor; }
|
||||
|
||||
void setPriority(quint16 priority) { _priority = priority; }
|
||||
quint16 getPriority() { return _priority; }
|
||||
|
||||
void setTextureTransforms(const Transform& transform);
|
||||
|
||||
private:
|
||||
mutable MaterialKey _key;
|
||||
mutable UniformBufferView _schemaBuffer;
|
||||
|
@ -364,10 +375,35 @@ private:
|
|||
mutable bool _hasCalculatedTextureInfo { false };
|
||||
bool calculateMaterialInfo() const;
|
||||
|
||||
float _blendFactor { 1.0f };
|
||||
quint16 _priority { 0 };
|
||||
|
||||
};
|
||||
typedef std::shared_ptr< Material > MaterialPointer;
|
||||
|
||||
Q_DECLARE_METATYPE(MaterialPointer)
|
||||
|
||||
class MaterialCompare {
|
||||
public:
|
||||
bool operator() (MaterialPointer left, MaterialPointer right) {
|
||||
return left->getPriority() < right->getPriority();
|
||||
}
|
||||
};
|
||||
|
||||
class MultiMaterial : public std::priority_queue<MaterialPointer, std::vector<MaterialPointer>, MaterialCompare> {
|
||||
public:
|
||||
bool remove(const MaterialPointer& value) {
|
||||
auto it = std::find(c.begin(), c.end(), value);
|
||||
if (it != c.end()) {
|
||||
c.erase(it);
|
||||
std::make_heap(c.begin(), c.end(), comp);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -549,7 +549,6 @@ graphics::TextureMapPointer NetworkMaterial::fetchTextureMap(const QUrl& url, im
|
|||
auto map = std::make_shared<graphics::TextureMap>();
|
||||
if (texture) {
|
||||
map->setTextureSource(texture->_textureSource);
|
||||
emit textureFinished();
|
||||
}
|
||||
|
||||
return map;
|
||||
|
@ -728,6 +727,7 @@ void NetworkMaterial::setTextures(const QVariantMap& textureMap) {
|
|||
|
||||
if (!occlusionName.isEmpty()) {
|
||||
auto url = textureMap.contains(occlusionName) ? textureMap[occlusionName].toUrl() : QUrl();
|
||||
// FIXME: we need to handle the occlusion map transform here
|
||||
auto map = fetchTextureMap(url, image::TextureUsage::OCCLUSION_TEXTURE, MapChannel::OCCLUSION_MAP);
|
||||
setTextureMap(MapChannel::OCCLUSION_MAP, map);
|
||||
}
|
||||
|
|
|
@ -156,8 +156,7 @@ private:
|
|||
virtual ~ModelCache() = default;
|
||||
};
|
||||
|
||||
class NetworkMaterial : public QObject, public graphics::Material {
|
||||
Q_OBJECT
|
||||
class NetworkMaterial : public graphics::Material {
|
||||
public:
|
||||
using MapChannel = graphics::Material::MapChannel;
|
||||
|
||||
|
@ -174,9 +173,6 @@ public:
|
|||
void setScatteringMap(const QString& url);
|
||||
void setLightmapMap(const QString& url);
|
||||
|
||||
signals:
|
||||
void textureFinished();
|
||||
|
||||
protected:
|
||||
friend class Geometry;
|
||||
|
||||
|
|
|
@ -381,6 +381,17 @@ bool OctreePacketData::appendValue(float value) {
|
|||
return success;
|
||||
}
|
||||
|
||||
bool OctreePacketData::appendValue(const glm::vec2& value) {
|
||||
const unsigned char* data = (const unsigned char*)&value;
|
||||
int length = sizeof(value);
|
||||
bool success = append(data, length);
|
||||
if (success) {
|
||||
_bytesOfValues += length;
|
||||
_totalBytesOfValues += length;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
bool OctreePacketData::appendValue(const glm::vec3& value) {
|
||||
const unsigned char* data = (const unsigned char*)&value;
|
||||
int length = sizeof(value);
|
||||
|
|
|
@ -164,6 +164,9 @@ public:
|
|||
/// appends a float value to the end of the stream, may fail if new data stream is too long to fit in packet
|
||||
bool appendValue(float value);
|
||||
|
||||
/// appends a vec2 to the end of the stream, may fail if new data stream is too long to fit in packet
|
||||
bool appendValue(const glm::vec2& value);
|
||||
|
||||
/// appends a non-position vector to the end of the stream, may fail if new data stream is too long to fit in packet
|
||||
bool appendValue(const glm::vec3& value);
|
||||
|
||||
|
@ -250,8 +253,8 @@ public:
|
|||
static quint64 getTotalBytesOfColor() { return _totalBytesOfColor; } /// total bytes of color
|
||||
|
||||
static int unpackDataFromBytes(const unsigned char* dataBytes, float& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); }
|
||||
static int unpackDataFromBytes(const unsigned char* dataBytes, glm::vec2& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); }
|
||||
static int unpackDataFromBytes(const unsigned char* dataBytes, glm::vec3& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); }
|
||||
static int unpackDataFromBytes(const unsigned char* dataBytes, glm::vec4& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); }
|
||||
static int unpackDataFromBytes(const unsigned char* dataBytes, bool& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); }
|
||||
static int unpackDataFromBytes(const unsigned char* dataBytes, quint64& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); }
|
||||
static int unpackDataFromBytes(const unsigned char* dataBytes, uint32_t& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); }
|
||||
|
|
|
@ -47,7 +47,7 @@ template <> void payloadRender(const MeshPartPayload::Pointer& payload, RenderAr
|
|||
|
||||
MeshPartPayload::MeshPartPayload(const std::shared_ptr<const graphics::Mesh>& mesh, int partIndex, graphics::MaterialPointer material) {
|
||||
updateMeshPart(mesh, partIndex);
|
||||
updateMaterial(material);
|
||||
addMaterial(material);
|
||||
}
|
||||
|
||||
void MeshPartPayload::updateMeshPart(const std::shared_ptr<const graphics::Mesh>& drawMesh, int partIndex) {
|
||||
|
@ -67,8 +67,12 @@ void MeshPartPayload::updateTransform(const Transform& transform, const Transfor
|
|||
_worldBound.transform(_drawTransform);
|
||||
}
|
||||
|
||||
void MeshPartPayload::updateMaterial(graphics::MaterialPointer drawMaterial) {
|
||||
_drawMaterial = drawMaterial;
|
||||
void MeshPartPayload::addMaterial(graphics::MaterialPointer material) {
|
||||
_drawMaterials.push(material);
|
||||
}
|
||||
|
||||
void MeshPartPayload::removeMaterial(graphics::MaterialPointer material) {
|
||||
_drawMaterials.remove(material);
|
||||
}
|
||||
|
||||
void MeshPartPayload::updateKey(bool isVisible, bool isLayered, uint8_t tagBits) {
|
||||
|
@ -85,8 +89,8 @@ void MeshPartPayload::updateKey(bool isVisible, bool isLayered, uint8_t tagBits)
|
|||
builder.withLayered();
|
||||
}
|
||||
|
||||
if (_drawMaterial) {
|
||||
auto matKey = _drawMaterial->getKey();
|
||||
if (_drawMaterials.top()) {
|
||||
auto matKey = _drawMaterials.top()->getKey();
|
||||
if (matKey.isTranslucent()) {
|
||||
builder.withTransparent();
|
||||
}
|
||||
|
@ -105,8 +109,8 @@ Item::Bound MeshPartPayload::getBound() const {
|
|||
|
||||
ShapeKey MeshPartPayload::getShapeKey() const {
|
||||
graphics::MaterialKey drawMaterialKey;
|
||||
if (_drawMaterial) {
|
||||
drawMaterialKey = _drawMaterial->getKey();
|
||||
if (_drawMaterials.top()) {
|
||||
drawMaterialKey = _drawMaterials.top()->getKey();
|
||||
}
|
||||
|
||||
ShapeKey::Builder builder;
|
||||
|
@ -160,7 +164,7 @@ void MeshPartPayload::render(RenderArgs* args) {
|
|||
bindMesh(batch);
|
||||
|
||||
// apply material properties
|
||||
args->_shapePipeline->bindMaterial(_drawMaterial, batch, args->_enableTexturing);
|
||||
args->_shapePipeline->bindMaterial(_drawMaterials.top(), batch, args->_enableTexturing);
|
||||
args->_details._materialSwitches++;
|
||||
|
||||
// Draw!
|
||||
|
@ -252,7 +256,7 @@ void ModelMeshPartPayload::initCache(const ModelPointer& model) {
|
|||
|
||||
auto networkMaterial = model->getGeometry()->getShapeMaterial(_shapeID);
|
||||
if (networkMaterial) {
|
||||
_drawMaterial = networkMaterial;
|
||||
addMaterial(networkMaterial);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -298,8 +302,8 @@ void ModelMeshPartPayload::updateKey(bool isVisible, bool isLayered, uint8_t tag
|
|||
builder.withDeformed();
|
||||
}
|
||||
|
||||
if (_drawMaterial) {
|
||||
auto matKey = _drawMaterial->getKey();
|
||||
if (_drawMaterials.top()) {
|
||||
auto matKey = _drawMaterials.top()->getKey();
|
||||
if (matKey.isTranslucent()) {
|
||||
builder.withTransparent();
|
||||
}
|
||||
|
@ -329,8 +333,8 @@ void ModelMeshPartPayload::setShapeKey(bool invalidateShapeKey, bool isWireframe
|
|||
}
|
||||
|
||||
graphics::MaterialKey drawMaterialKey;
|
||||
if (_drawMaterial) {
|
||||
drawMaterialKey = _drawMaterial->getKey();
|
||||
if (_drawMaterials.top()) {
|
||||
drawMaterialKey = _drawMaterials.top()->getKey();
|
||||
}
|
||||
|
||||
bool isTranslucent = drawMaterialKey.isTranslucent();
|
||||
|
@ -411,7 +415,7 @@ void ModelMeshPartPayload::render(RenderArgs* args) {
|
|||
bindMesh(batch);
|
||||
|
||||
// apply material properties
|
||||
args->_shapePipeline->bindMaterial(_drawMaterial, batch, args->_enableTexturing);
|
||||
args->_shapePipeline->bindMaterial(_drawMaterials.top(), batch, args->_enableTexturing);
|
||||
args->_details._materialSwitches++;
|
||||
|
||||
// Draw!
|
||||
|
|
|
@ -39,8 +39,6 @@ public:
|
|||
virtual void notifyLocationChanged() {}
|
||||
void updateTransform(const Transform& transform, const Transform& offsetTransform);
|
||||
|
||||
virtual void updateMaterial(graphics::MaterialPointer drawMaterial);
|
||||
|
||||
// Render Item interface
|
||||
virtual render::ItemKey getKey() const;
|
||||
virtual render::Item::Bound getBound() const;
|
||||
|
@ -63,13 +61,16 @@ public:
|
|||
mutable graphics::Box _worldBound;
|
||||
std::shared_ptr<const graphics::Mesh> _drawMesh;
|
||||
|
||||
std::shared_ptr<graphics::Material> _drawMaterial;
|
||||
graphics::MultiMaterial _drawMaterials;
|
||||
graphics::Mesh::Part _drawPart;
|
||||
|
||||
size_t getVerticesCount() const { return _drawMesh ? _drawMesh->getNumVertices() : 0; }
|
||||
size_t getMaterialTextureSize() { return _drawMaterial ? _drawMaterial->getTextureSize() : 0; }
|
||||
int getMaterialTextureCount() { return _drawMaterial ? _drawMaterial->getTextureCount() : 0; }
|
||||
bool hasTextureInfo() const { return _drawMaterial ? _drawMaterial->hasTextureInfo() : false; }
|
||||
size_t getMaterialTextureSize() { return _drawMaterials.top() ? _drawMaterials.top()->getTextureSize() : 0; }
|
||||
int getMaterialTextureCount() { return _drawMaterials.top() ? _drawMaterials.top()->getTextureCount() : 0; }
|
||||
bool hasTextureInfo() const { return _drawMaterials.top() ? _drawMaterials.top()->hasTextureInfo() : false; }
|
||||
|
||||
void addMaterial(graphics::MaterialPointer material);
|
||||
void removeMaterial(graphics::MaterialPointer material);
|
||||
|
||||
protected:
|
||||
render::ItemKey _itemKey{ render::ItemKey::Builder::opaqueShape().build() };
|
||||
|
|
|
@ -1524,6 +1524,50 @@ bool Model::isRenderable() const {
|
|||
return !_meshStates.empty() || (isLoaded() && _renderGeometry->getMeshes().empty());
|
||||
}
|
||||
|
||||
void Model::addMaterial(graphics::MaterialPointer material, quint16 shapeID) {
|
||||
if (shapeID < _modelMeshRenderItemIDs.size()) {
|
||||
render::Transaction transaction;
|
||||
auto itemID = _modelMeshRenderItemIDs[shapeID];
|
||||
bool visible = isVisible();
|
||||
uint8_t viewTagBits = getViewTagBits();
|
||||
bool layeredInFront = isLayeredInFront();
|
||||
bool layeredInHUD = isLayeredInHUD();
|
||||
bool wireframe = isWireframe();
|
||||
auto meshIndex = _modelMeshRenderItemShapes[shapeID].meshIndex;
|
||||
bool invalidatePayloadShapeKey = shouldInvalidatePayloadShapeKey(meshIndex);
|
||||
transaction.updateItem<ModelMeshPartPayload>(itemID, [material, visible, layeredInFront, layeredInHUD, viewTagBits,
|
||||
invalidatePayloadShapeKey, wireframe](ModelMeshPartPayload& data) {
|
||||
data.addMaterial(material);
|
||||
// if the material changed, we might need to update our item key or shape key
|
||||
data.updateKey(visible, layeredInFront || layeredInHUD, viewTagBits);
|
||||
data.setShapeKey(invalidatePayloadShapeKey, wireframe);
|
||||
});
|
||||
AbstractViewStateInterface::instance()->getMain3DScene()->enqueueTransaction(transaction);
|
||||
}
|
||||
}
|
||||
|
||||
void Model::removeMaterial(graphics::MaterialPointer material, quint16 shapeID) {
|
||||
if (shapeID < _modelMeshRenderItemIDs.size()) {
|
||||
render::Transaction transaction;
|
||||
auto itemID = _modelMeshRenderItemIDs[shapeID];
|
||||
bool visible = isVisible();
|
||||
uint8_t viewTagBits = getViewTagBits();
|
||||
bool layeredInFront = isLayeredInFront();
|
||||
bool layeredInHUD = isLayeredInHUD();
|
||||
bool wireframe = isWireframe();
|
||||
auto meshIndex = _modelMeshRenderItemShapes[shapeID].meshIndex;
|
||||
bool invalidatePayloadShapeKey = shouldInvalidatePayloadShapeKey(meshIndex);
|
||||
transaction.updateItem<ModelMeshPartPayload>(itemID, [material, visible, layeredInFront, layeredInHUD, viewTagBits,
|
||||
invalidatePayloadShapeKey, wireframe](ModelMeshPartPayload& data) {
|
||||
data.removeMaterial(material);
|
||||
// if the material changed, we might need to update our item key or shape key
|
||||
data.updateKey(visible, layeredInFront || layeredInHUD, viewTagBits);
|
||||
data.setShapeKey(invalidatePayloadShapeKey, wireframe);
|
||||
});
|
||||
AbstractViewStateInterface::instance()->getMain3DScene()->enqueueTransaction(transaction);
|
||||
}
|
||||
}
|
||||
|
||||
class CollisionRenderGeometry : public Geometry {
|
||||
public:
|
||||
CollisionRenderGeometry(graphics::MeshPointer mesh) {
|
||||
|
|
|
@ -318,6 +318,9 @@ public:
|
|||
|
||||
void scaleToFit();
|
||||
|
||||
void addMaterial(graphics::MaterialPointer material, quint16 shapeID);
|
||||
void removeMaterial(graphics::MaterialPointer material, quint16 shapeID);
|
||||
|
||||
public slots:
|
||||
void loadURLFinished(bool success);
|
||||
|
||||
|
|
|
@ -342,7 +342,7 @@ var toolBar = (function () {
|
|||
|
||||
var buttonHandlers = {}; // only used to tablet mode
|
||||
|
||||
function addButton(name, image, handler) {
|
||||
function addButton(name, handler) {
|
||||
buttonHandlers[name] = handler;
|
||||
}
|
||||
|
||||
|
@ -399,7 +399,7 @@ var toolBar = (function () {
|
|||
|
||||
function handleNewMaterialDialogResult(result) {
|
||||
if (result) {
|
||||
var json = result.textInput;
|
||||
var materialURL = result.textInput;
|
||||
var materialMode;
|
||||
switch (result.comboBox) {
|
||||
case MATERIAL_MODE_PROJECTED:
|
||||
|
@ -409,11 +409,13 @@ var toolBar = (function () {
|
|||
shapeType = "uv";
|
||||
}
|
||||
|
||||
if (json) {
|
||||
var DEFAULT_LAYERED_MATERIAL_PRIORITY = 1;
|
||||
if (materialURL) {
|
||||
createNewEntity({
|
||||
type: "Material",
|
||||
materialURL: json,
|
||||
materialMode: materialMode
|
||||
materialURL: materialURL,
|
||||
materialMode: materialMode,
|
||||
priority: DEFAULT_LAYERED_MATERIAL_PRIORITY
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -475,32 +477,22 @@ var toolBar = (function () {
|
|||
that.toggle();
|
||||
});
|
||||
|
||||
addButton("importEntitiesButton", "assets-01.svg", function() {
|
||||
addButton("importEntitiesButton", function() {
|
||||
Window.browseChanged.connect(onFileOpenChanged);
|
||||
Window.browseAsync("Select Model to Import", "", "*.json");
|
||||
});
|
||||
|
||||
addButton("openAssetBrowserButton", "assets-01.svg", function() {
|
||||
addButton("openAssetBrowserButton", function() {
|
||||
Window.showAssetServer();
|
||||
});
|
||||
|
||||
addButton("newModelButton", "model-01.svg", function () {
|
||||
|
||||
var SHAPE_TYPES = [];
|
||||
SHAPE_TYPES[SHAPE_TYPE_NONE] = "No Collision";
|
||||
SHAPE_TYPES[SHAPE_TYPE_SIMPLE_HULL] = "Basic - Whole model";
|
||||
SHAPE_TYPES[SHAPE_TYPE_SIMPLE_COMPOUND] = "Good - Sub-meshes";
|
||||
SHAPE_TYPES[SHAPE_TYPE_STATIC_MESH] = "Exact - All polygons";
|
||||
SHAPE_TYPES[SHAPE_TYPE_BOX] = "Box";
|
||||
SHAPE_TYPES[SHAPE_TYPE_SPHERE] = "Sphere";
|
||||
var SHAPE_TYPE_DEFAULT = SHAPE_TYPE_STATIC_MESH;
|
||||
|
||||
addButton("newModelButton", function () {
|
||||
// tablet version of new-model dialog
|
||||
var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
|
||||
tablet.pushOntoStack("hifi/tablet/NewModelDialog.qml");
|
||||
});
|
||||
|
||||
addButton("newCubeButton", "cube-01.svg", function () {
|
||||
addButton("newCubeButton", function () {
|
||||
createNewEntity({
|
||||
type: "Box",
|
||||
dimensions: DEFAULT_DIMENSIONS,
|
||||
|
@ -512,7 +504,7 @@ var toolBar = (function () {
|
|||
});
|
||||
});
|
||||
|
||||
addButton("newSphereButton", "sphere-01.svg", function () {
|
||||
addButton("newSphereButton", function () {
|
||||
createNewEntity({
|
||||
type: "Sphere",
|
||||
dimensions: DEFAULT_DIMENSIONS,
|
||||
|
@ -524,7 +516,7 @@ var toolBar = (function () {
|
|||
});
|
||||
});
|
||||
|
||||
addButton("newLightButton", "light-01.svg", function () {
|
||||
addButton("newLightButton", function () {
|
||||
createNewEntity({
|
||||
type: "Light",
|
||||
dimensions: DEFAULT_LIGHT_DIMENSIONS,
|
||||
|
@ -543,7 +535,7 @@ var toolBar = (function () {
|
|||
});
|
||||
});
|
||||
|
||||
addButton("newTextButton", "text-01.svg", function () {
|
||||
addButton("newTextButton", function () {
|
||||
createNewEntity({
|
||||
type: "Text",
|
||||
dimensions: {
|
||||
|
@ -566,7 +558,7 @@ var toolBar = (function () {
|
|||
});
|
||||
});
|
||||
|
||||
addButton("newWebButton", "web-01.svg", function () {
|
||||
addButton("newWebButton", function () {
|
||||
createNewEntity({
|
||||
type: "Web",
|
||||
dimensions: {
|
||||
|
@ -578,7 +570,7 @@ var toolBar = (function () {
|
|||
});
|
||||
});
|
||||
|
||||
addButton("newZoneButton", "zone-01.svg", function () {
|
||||
addButton("newZoneButton", function () {
|
||||
createNewEntity({
|
||||
type: "Zone",
|
||||
dimensions: {
|
||||
|
@ -589,7 +581,7 @@ var toolBar = (function () {
|
|||
});
|
||||
});
|
||||
|
||||
addButton("newParticleButton", "particle-01.svg", function () {
|
||||
addButton("newParticleButton", function () {
|
||||
createNewEntity({
|
||||
type: "ParticleEffect",
|
||||
isEmitting: true,
|
||||
|
@ -642,15 +634,10 @@ var toolBar = (function () {
|
|||
});
|
||||
});
|
||||
|
||||
addButton("newMaterialButton", "model-01.svg", function () {
|
||||
var MATERIAL_MODES = [];
|
||||
MATERIAL_MODES[MATERIAL_MODE_UV] = "UV space material";
|
||||
MATERIAL_MODES[MATERIAL_MODE_PROJECTED] = "3D projected material";
|
||||
var MATERIAL_MODE_DEFAULT = MATERIAL_MODE_UV;
|
||||
|
||||
addButton("newMaterialButton", function () {
|
||||
// tablet version of new material dialog
|
||||
var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
|
||||
tablet.pushOntoStack("NewMaterialDialog.qml");
|
||||
tablet.pushOntoStack("hifi/tablet/NewMaterialDialog.qml");
|
||||
});
|
||||
|
||||
that.setActive(false);
|
||||
|
|
|
@ -645,14 +645,14 @@ hr {
|
|||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.text label, .url label, .number label, .textarea label, .rgb label, .xyz label, .pyr label, .dropdown label, .gen label {
|
||||
.text label, .url label, .number label, .textarea label, .xy label, .wh label, .rgb label, .xyz label,.pyr label, .dropdown label, .gen label {
|
||||
float: left;
|
||||
margin-left: 1px;
|
||||
margin-bottom: 3px;
|
||||
margin-top: -2px;
|
||||
}
|
||||
|
||||
.text legend, .url legend, .number legend, .textarea legend, .rgb legend, .xyz legend, .pyr legend, .dropdown legend, .gen legend {
|
||||
.text legend, .url legend, .number legend, .textarea legend, .xy legend, .wh legend, .rgb legend, .xyz legend, .pyr legend, .dropdown legend, .gen legend {
|
||||
float: left;
|
||||
margin-left: 1px;
|
||||
margin-bottom: 3px;
|
||||
|
@ -667,7 +667,7 @@ hr {
|
|||
clear: both;
|
||||
float: left;
|
||||
}
|
||||
.xyz > div, .pyr > div, .gen > div {
|
||||
.xy > div, .wh > div, .xyz > div, .pyr > div, .gen > div {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
|
@ -841,6 +841,12 @@ div.refresh input[type="button"] {
|
|||
margin-right: -6px;
|
||||
}
|
||||
|
||||
.xy .tuple input {
|
||||
padding-left: 25px;
|
||||
}
|
||||
.wh .tuple input {
|
||||
padding-left: 45px;
|
||||
}
|
||||
.rgb .tuple input {
|
||||
padding-left: 65px;
|
||||
}
|
||||
|
|
|
@ -787,7 +787,7 @@
|
|||
|
||||
<div class="material-group material-section property number">
|
||||
<label>Priority </label>
|
||||
<input type="number" id="property-priority">
|
||||
<input type="number" id="property-priority" min="0">
|
||||
</div>
|
||||
|
||||
<div class="material-group material-section property number">
|
||||
|
@ -795,13 +795,26 @@
|
|||
<input type="number" id="property-shape-id" min="0">
|
||||
</div>
|
||||
|
||||
<div class="material-group material-section property tuple">
|
||||
<label>Material Bounds </label>
|
||||
<div><input type="number" class="x" id="property-material-bounds-x" min="0" max="1" step="0.1"><label for="property-material-bounds-x">Left:</label></div>
|
||||
<div><input type="number" class="y" id="property-material-bounds-y" min="0" max="1" step="0.1"><label for="property-material-bounds-y">Top:</label></div>
|
||||
<div><input type="number" class="z" id="property-material-bounds-z" min="0" max="1" step="0.1"><label for="property-material-bounds-z">Right:</label></div>
|
||||
<div><input type="number" class="w" id="property-material-bounds-w" min="0" max="1" step="0.1"><label for="property-material-bounds-w">Bottom:</label></div>
|
||||
</div>
|
||||
<fieldset>
|
||||
<div class="material-group material-section property xy fstuple">
|
||||
<label>Material Position </label>
|
||||
<div class="tuple">
|
||||
<div><input type="number" class="x" id="property-material-pos-x" min="0" max="1" step="0.1"><label for="property-material-pos-x">X:</label></div>
|
||||
<div><input type="number" class="y" id="property-material-pos-y" min="0" max="1" step="0.1"><label for="property-material-pos-y">Y:</label></div>
|
||||
</div>
|
||||
|
||||
<div class="material-group material-section property wh fstuple">
|
||||
<label>Material Scale </label>
|
||||
<div class="tuple">
|
||||
<div><input type="number" class="x" id="property-material-scale-x" min="0" step="0.1"><label for="property-material-scale-x">Width:</label></div>
|
||||
<div><input type="number" class="y" id="property-material-scale-y" min="0" step="0.1"><label for="property-material-scale-y">Height:</label></div>
|
||||
</div>
|
||||
|
||||
<div class="material-group material-section property number">
|
||||
<label>Material Rotation <span class="unit">deg</span></label>
|
||||
<input type="number" id="property-material-rot" step="0.1">
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
</fieldset>
|
||||
</fieldset>
|
||||
|
|
|
@ -25,7 +25,7 @@ var ICON_FOR_TYPE = {
|
|||
PolyVox: "",
|
||||
Multiple: "",
|
||||
PolyLine: "",
|
||||
Material: ""
|
||||
Material: ""
|
||||
};
|
||||
|
||||
var EDITOR_TIMEOUT_DURATION = 1500;
|
||||
|
@ -167,6 +167,17 @@ function createEmitGroupTextPropertyUpdateFunction(group, propertyName) {
|
|||
};
|
||||
}
|
||||
|
||||
function createEmitVec2PropertyUpdateFunction(property, elX, elY) {
|
||||
return function () {
|
||||
var properties = {};
|
||||
properties[property] = {
|
||||
x: elX.value,
|
||||
y: elY.value
|
||||
};
|
||||
updateProperties(properties);
|
||||
};
|
||||
}
|
||||
|
||||
function createEmitVec3PropertyUpdateFunction(property, elX, elY, elZ) {
|
||||
return function() {
|
||||
var properties = {};
|
||||
|
@ -192,19 +203,6 @@ function createEmitGroupVec3PropertyUpdateFunction(group, property, elX, elY, el
|
|||
};
|
||||
}
|
||||
|
||||
function createEmitVec4PropertyUpdateFunction(property, elX, elY, elZ, elW) {
|
||||
return function () {
|
||||
var properties = {};
|
||||
properties[property] = {
|
||||
x: elX.value,
|
||||
y: elY.value,
|
||||
z: elZ.value,
|
||||
w: elW.value
|
||||
};
|
||||
updateProperties(properties);
|
||||
};
|
||||
}
|
||||
|
||||
function createEmitVec3PropertyUpdateFunctionWithMultiplier(property, elX, elY, elZ, multiplier) {
|
||||
return function() {
|
||||
var properties = {};
|
||||
|
@ -638,10 +636,11 @@ function loaded() {
|
|||
var elBlendFactor = document.getElementById("property-blend-factor");
|
||||
var elPriority = document.getElementById("property-priority");
|
||||
var elShapeID = document.getElementById("property-shape-id");
|
||||
var elMaterialBoundsX = document.getElementById("property-material-bounds-x");
|
||||
var elMaterialBoundsY = document.getElementById("property-material-bounds-y");
|
||||
var elMaterialBoundsZ = document.getElementById("property-material-bounds-z");
|
||||
var elMaterialBoundsW = document.getElementById("property-material-bounds-w");
|
||||
var elMaterialPosX = document.getElementById("property-material-pos-x");
|
||||
var elMaterialPosY = document.getElementById("property-material-pos-y");
|
||||
var elMaterialScaleX = document.getElementById("property-material-scale-x");
|
||||
var elMaterialScaleY = document.getElementById("property-material-scale-y");
|
||||
var elMaterialRot = document.getElementById("property-material-rot");
|
||||
|
||||
var elWebSourceURL = document.getElementById("property-web-source-url");
|
||||
var elWebDPI = document.getElementById("property-web-dpi");
|
||||
|
@ -1134,10 +1133,11 @@ function loaded() {
|
|||
elBlendFactor.value = properties.blendFactor.toFixed(2);
|
||||
elPriority.value = properties.priority;
|
||||
elShapeID.value = properties.shapeID;
|
||||
elMaterialBoundsX.value = properties.materialBounds.x.toFixed(2);
|
||||
elMaterialBoundsY.value = properties.materialBounds.y.toFixed(2);
|
||||
elMaterialBoundsZ.value = properties.materialBounds.z.toFixed(2);
|
||||
//elMaterialBoundsW.value = properties.materialBounds.w.toFixed(2);
|
||||
elMaterialPosX.value = properties.materialPos.x.toFixed(4);
|
||||
elMaterialPosY.value = properties.materialPos.y.toFixed(4);
|
||||
elMaterialScaleX.value = properties.materialScale.x.toFixed(4);
|
||||
elMaterialScaleY.value = properties.materialScale.y.toFixed(4);
|
||||
elMaterialRot.value = properties.materialRot.toFixed(2);
|
||||
}
|
||||
|
||||
if (properties.locked) {
|
||||
|
@ -1411,15 +1411,16 @@ function loaded() {
|
|||
elMaterialURL.addEventListener('change', createEmitTextPropertyUpdateFunction('materialURL'));
|
||||
elMaterialMode.addEventListener('change', createEmitTextPropertyUpdateFunction('materialMode'));
|
||||
elBlendFactor.addEventListener('change', createEmitNumberPropertyUpdateFunction('blendFactor', 2));
|
||||
elPriority.addEventListener('change', createEmitNumberPropertyUpdateFunction('priority'));
|
||||
elShapeID.addEventListener('change', createEmitNumberPropertyUpdateFunction('shapeID'));
|
||||
elPriority.addEventListener('change', createEmitNumberPropertyUpdateFunction('priority', 0));
|
||||
elShapeID.addEventListener('change', createEmitNumberPropertyUpdateFunction('shapeID', 0));
|
||||
|
||||
var materialBoundsChangeFunction = createEmitVec4PropertyUpdateFunction('materialBounds',
|
||||
elMaterialBoundsX, elMaterialBoundsY, elMaterialBoundsZ, elMaterialBoundsW);
|
||||
elMaterialBoundsX.addEventListener('change', materialBoundsChangeFunction);
|
||||
elMaterialBoundsY.addEventListener('change', materialBoundsChangeFunction);
|
||||
elMaterialBoundsZ.addEventListener('change', materialBoundsChangeFunction);
|
||||
elMaterialBoundsW.addEventListener('change', materialBoundsChangeFunction);
|
||||
var materialPosChangeFunction = createEmitVec2PropertyUpdateFunction('materialPos', elMaterialPosX, elMaterialPosY);
|
||||
elMaterialPosX.addEventListener('change', materialPosChangeFunction);
|
||||
elMaterialPosY.addEventListener('change', materialPosChangeFunction);
|
||||
var materialScaleChangeFunction = createEmitVec2PropertyUpdateFunction('materialScale', elMaterialScaleX, elMaterialScaleY);
|
||||
elMaterialScaleX.addEventListener('change', materialScaleChangeFunction);
|
||||
elMaterialScaleY.addEventListener('change', materialScaleChangeFunction);
|
||||
elMaterialRot.addEventListener('change', createEmitNumberPropertyUpdateFunction('materialRot', 2));
|
||||
|
||||
elTextText.addEventListener('change', createEmitTextPropertyUpdateFunction('text'));
|
||||
elTextFaceCamera.addEventListener('change', createEmitCheckedPropertyUpdateFunction('faceCamera'));
|
||||
|
|
138
tools/jsdoc/package-lock.json
generated
Normal file
138
tools/jsdoc/package-lock.json
generated
Normal file
|
@ -0,0 +1,138 @@
|
|||
{
|
||||
"name": "hifiJSDoc",
|
||||
"requires": true,
|
||||
"lockfileVersion": 1,
|
||||
"dependencies": {
|
||||
"babylon": {
|
||||
"version": "7.0.0-beta.19",
|
||||
"resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.19.tgz",
|
||||
"integrity": "sha512-Vg0C9s/REX6/WIXN37UKpv5ZhRi6A4pjHlpkE34+8/a6c2W1Q692n3hmc+SZG5lKRnaExLUbxtJ1SVT+KaCQ/A=="
|
||||
},
|
||||
"bluebird": {
|
||||
"version": "3.5.1",
|
||||
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz",
|
||||
"integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA=="
|
||||
},
|
||||
"catharsis": {
|
||||
"version": "0.8.9",
|
||||
"resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.8.9.tgz",
|
||||
"integrity": "sha1-mMyJDKZS3S7w5ws3klMQ/56Q/Is=",
|
||||
"requires": {
|
||||
"underscore-contrib": "0.3.0"
|
||||
}
|
||||
},
|
||||
"escape-string-regexp": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
|
||||
},
|
||||
"graceful-fs": {
|
||||
"version": "4.1.11",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
|
||||
"integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg="
|
||||
},
|
||||
"js2xmlparser": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-3.0.0.tgz",
|
||||
"integrity": "sha1-P7YOqgicVED5MZ9RdgzNB+JJlzM=",
|
||||
"requires": {
|
||||
"xmlcreate": "1.0.2"
|
||||
}
|
||||
},
|
||||
"jsdoc": {
|
||||
"version": "3.5.5",
|
||||
"resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.5.5.tgz",
|
||||
"integrity": "sha512-6PxB65TAU4WO0Wzyr/4/YhlGovXl0EVYfpKbpSroSj0qBxT4/xod/l40Opkm38dRHRdQgdeY836M0uVnJQG7kg==",
|
||||
"requires": {
|
||||
"babylon": "7.0.0-beta.19",
|
||||
"bluebird": "3.5.1",
|
||||
"catharsis": "0.8.9",
|
||||
"escape-string-regexp": "1.0.5",
|
||||
"js2xmlparser": "3.0.0",
|
||||
"klaw": "2.0.0",
|
||||
"marked": "0.3.12",
|
||||
"mkdirp": "0.5.1",
|
||||
"requizzle": "0.2.1",
|
||||
"strip-json-comments": "2.0.1",
|
||||
"taffydb": "2.6.2",
|
||||
"underscore": "1.8.3"
|
||||
}
|
||||
},
|
||||
"klaw": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/klaw/-/klaw-2.0.0.tgz",
|
||||
"integrity": "sha1-WcEo4Nxc5BAgEVEZTuucv4WGUPY=",
|
||||
"requires": {
|
||||
"graceful-fs": "4.1.11"
|
||||
}
|
||||
},
|
||||
"marked": {
|
||||
"version": "0.3.12",
|
||||
"resolved": "https://registry.npmjs.org/marked/-/marked-0.3.12.tgz",
|
||||
"integrity": "sha512-k4NaW+vS7ytQn6MgJn3fYpQt20/mOgYM5Ft9BYMfQJDz2QT6yEeS9XJ8k2Nw8JTeWK/znPPW2n3UJGzyYEiMoA=="
|
||||
},
|
||||
"minimist": {
|
||||
"version": "0.0.8",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
|
||||
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
|
||||
},
|
||||
"mkdirp": {
|
||||
"version": "0.5.1",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
|
||||
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
|
||||
"requires": {
|
||||
"minimist": "0.0.8"
|
||||
}
|
||||
},
|
||||
"requizzle": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.1.tgz",
|
||||
"integrity": "sha1-aUPDUwxNmn5G8c3dUcFY/GcM294=",
|
||||
"requires": {
|
||||
"underscore": "1.6.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"underscore": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz",
|
||||
"integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag="
|
||||
}
|
||||
}
|
||||
},
|
||||
"strip-json-comments": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
|
||||
"integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo="
|
||||
},
|
||||
"taffydb": {
|
||||
"version": "2.6.2",
|
||||
"resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.6.2.tgz",
|
||||
"integrity": "sha1-fLy2S1oUG2ou/CxdLGe04VCyomg="
|
||||
},
|
||||
"underscore": {
|
||||
"version": "1.8.3",
|
||||
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz",
|
||||
"integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI="
|
||||
},
|
||||
"underscore-contrib": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/underscore-contrib/-/underscore-contrib-0.3.0.tgz",
|
||||
"integrity": "sha1-ZltmwkeD+PorGMn4y7Dix9SMJsc=",
|
||||
"requires": {
|
||||
"underscore": "1.6.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"underscore": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz",
|
||||
"integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag="
|
||||
}
|
||||
}
|
||||
},
|
||||
"xmlcreate": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-1.0.2.tgz",
|
||||
"integrity": "sha1-+mv3YqYKQT+z3Y9LA8WyaSONMI8="
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue