First working fade

This commit is contained in:
Olivier Prat 2017-07-10 15:27:09 +02:00
parent 06d69d04c3
commit 267531cc1a
9 changed files with 221 additions and 87 deletions

View file

@ -61,7 +61,7 @@ namespace render {
template <> uint32_t metaFetchMetaSubItems(const AvatarSharedPointer& avatar, ItemIDs& subItems) {
auto avatarPtr = static_pointer_cast<Avatar>(avatar);
if (avatarPtr->getSkeletonModel()) {
auto metaSubItems = avatarPtr->getSkeletonModel()->fetchRenderItemIDs();
auto& metaSubItems = avatarPtr->getSkeletonModel()->fetchRenderItemIDs();
subItems.insert(subItems.end(), metaSubItems.begin(), metaSubItems.end());
return (uint32_t) metaSubItems.size();
}

View file

@ -217,8 +217,9 @@ namespace render {
}
template <> uint32_t metaFetchMetaSubItems(const RenderableModelEntityItemMeta::Pointer& payload, ItemIDs& subItems) {
auto modelEntity = std::static_pointer_cast<RenderableModelEntityItem>(payload->entity);
if (modelEntity->hasModel()) {
auto metaSubItems = modelEntity->getModelNotSafe()->fetchRenderItemIDs();
auto model = modelEntity->getModelNotSafe();
if (modelEntity->hasModel() && model) {
auto& metaSubItems = model->fetchRenderItemIDs();
subItems.insert(subItems.end(), metaSubItems.begin(), metaSubItems.end());
return (uint32_t) metaSubItems.size();
}
@ -489,6 +490,17 @@ ModelPointer RenderableModelEntityItem::getModelNotSafe() {
return _model;
}
void RenderableModelEntityItem::setModelURLFinished(bool success) {
if (success) {
const render::ScenePointer& scene = AbstractViewStateInterface::instance()->getMain3DScene();
render::Transaction transaction;
const auto& item = scene->getItem(_myMetaItem);
transaction.transitionItem(_myMetaItem, render::Transition::ELEMENT_ENTER_LEAVE_DOMAIN);
scene->enqueueTransaction(transaction);
}
}
ModelPointer RenderableModelEntityItem::getModel() {
// make sure our renderer is setup
if (!_myRenderer) {
@ -506,6 +518,7 @@ ModelPointer RenderableModelEntityItem::getModel() {
// If we don't have a model, allocate one *immediately*
if (!_model) {
_model = _myRenderer->allocateModel(getModelURL(), _myRenderer->getEntityLoadingPriority(*this), this);
QObject::connect(_model.get(), &Model::setURLFinished, this, &RenderableModelEntityItem::setModelURLFinished);
_needsInitialSimulation = true;
// If we need to change URLs, update it *after rendering* (to avoid access violations)
} else if (QUrl(getModelURL()) != _model->getURL()) {

View file

@ -12,16 +12,21 @@
#ifndef hifi_RenderableModelEntityItem_h
#define hifi_RenderableModelEntityItem_h
#include <QObject>
#include <QString>
#include <QStringList>
#include <ModelEntityItem.h>
#include <AnimationCache.h>
#include <model-networking\ModelCache.h>
#include "RenderableEntityItem.h"
class Model;
class EntityTreeRenderer;
class RenderableModelEntityItem : public ModelEntityItem, RenderableEntityInterface {
class RenderableModelEntityItem : public QObject, public ModelEntityItem, RenderableEntityInterface {
Q_OBJECT
public:
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
@ -116,6 +121,10 @@ public:
return _animation;
}
public slots:
void setModelURLFinished(bool success);
private:
QVariantMap parseTexturesToMap(QString textures);
void remapTextures();

View file

@ -464,6 +464,7 @@ FadeJob::FadeJob()
{
auto texturePath = PathUtils::resourcesPath() + "images/fadeMask.png";
_fadeMaskMap = DependencyManager::get<TextureCache>()->getImageTexture(texturePath, image::TextureUsage::STRICT_TEXTURE);
_previousTime = usecTimestampNow();
}
void FadeJob::configure(const Config& config) {
@ -493,76 +494,91 @@ void FadeJob::run(const render::RenderContextPointer& renderContext) {
auto transitionStage = scene->getStage<render::TransitionStage>(render::TransitionStage::getName());
uint64_t now = usecTimestampNow();
const double deltaTime = (int64_t(now) - int64_t(_previousTime)) / double(USECS_PER_SECOND);
render::Transaction transaction;
bool hasTransactions = false;
// And now update fade effect
for (auto transitionId : *transitionStage) {
auto& state = transitionStage->editTransition(transitionId);
update(*jobConfig, scene, state, deltaTime);
if (!update(*jobConfig, scene, state, deltaTime)) {
// Remove transition for this item
transaction.transitionItem(state.itemId, render::Transition::NONE);
hasTransactions = true;
}
}
if (hasTransactions) {
scene->enqueueTransaction(transaction);
}
_previousTime = now;
}
void FadeJob::update(const Config& config, const render::ScenePointer& scene, render::Transition& transition, const double deltaTime) const {
bool FadeJob::update(const Config& config, const render::ScenePointer& scene, render::Transition& transition, const double deltaTime) const {
auto& eventConfig = config.events[transition.eventType];
auto& item = scene->getItem(transition.itemId);
auto& aabb = item.getBound();
auto& dimensions = aabb.getDimensions();
const double eventDuration = (double)eventConfig.duration;
const FadeConfig::Timing timing = (FadeConfig::Timing) eventConfig.timing;
bool continueTransition = true;
assert(timing < render::Transition::EVENT_CATEGORY_COUNT);
if (item.exist()) {
auto& aabb = item.getBound();
auto& dimensions = aabb.getDimensions();
switch (transition.eventType) {
case render::Transition::ELEMENT_ENTER_LEAVE_DOMAIN:
transition.threshold = 1.f - computeElementEnterThreshold(transition.time, eventConfig.duration, timing);
transition.threshold = (transition.threshold - 0.5f)*_thresholdScale[transition.eventType] + 0.5f;
transition.noiseOffset = aabb.calcCenter();
transition.baseOffset = transition.noiseOffset - dimensions.y;
transition.baseInvSize.x = 1.f / dimensions.x;
transition.baseInvSize.y = 1.f / dimensions.y;
transition.baseInvSize.z = 1.f / dimensions.z;
assert(timing < render::Transition::EVENT_CATEGORY_COUNT);
switch (transition.eventType) {
case render::Transition::ELEMENT_ENTER_LEAVE_DOMAIN:
transition.threshold = 1.f - computeElementEnterRatio(transition.time, eventConfig.duration, timing);
transition.threshold = (transition.threshold - 0.5f)*_thresholdScale[transition.eventType] + 0.5f;
transition.noiseOffset = aabb.calcCenter();
transition.baseOffset = transition.noiseOffset - dimensions.y;
transition.baseInvSize.x = 1.f / dimensions.x;
transition.baseInvSize.y = 1.f / dimensions.y;
transition.baseInvSize.z = 1.f / dimensions.z;
continueTransition = transition.threshold > 0.f;
break;
case render::Transition::BUBBLE_ISECT_OWNER:
{
/* const glm::vec3 cameraPos = renderContext->args->getViewFrustum().getPosition();
glm::vec3 delta = itemBounds.bound.calcCenter() - cameraPos;
float distance = glm::length(delta);
delta = glm::normalize(delta) * std::max(0.f, distance - 0.5f);
_editBaseOffset = cameraPos + delta*_editThreshold;
_editThreshold = 0.33f;*/
}
break;
case render::Transition::BUBBLE_ISECT_OWNER:
{
/* const glm::vec3 cameraPos = renderContext->args->getViewFrustum().getPosition();
glm::vec3 delta = itemBounds.bound.calcCenter() - cameraPos;
float distance = glm::length(delta);
delta = glm::normalize(delta) * std::max(0.f, distance - 0.5f);
_editBaseOffset = cameraPos + delta*_editThreshold;
_editThreshold = 0.33f;*/
}
break;
case render::Transition::BUBBLE_ISECT_TRESPASSER:
{
// _editBaseOffset = glm::vec3{ 0.f, 0.f, 0.f };
}
break;
case render::Transition::USER_ENTER_LEAVE_DOMAIN:
{
/* _editBaseOffset = itemBounds.bound.calcCenter();
_editBaseOffset.y -= itemBounds.bound.getDimensions().y / 2.f;*/
}
break;
case render::Transition::AVATAR_CHANGE:
case render::Transition::BUBBLE_ISECT_TRESPASSER:
{
// _editBaseOffset = glm::vec3{ 0.f, 0.f, 0.f };
}
break;
default:
assert(false);
case render::Transition::USER_ENTER_LEAVE_DOMAIN:
{
/* _editBaseOffset = itemBounds.bound.calcCenter();
_editBaseOffset.y -= itemBounds.bound.getDimensions().y / 2.f;*/
}
break;
case render::Transition::AVATAR_CHANGE:
break;
default:
assert(false);
}
}
transition.time += deltaTime;
// renderContext->jobConfig->setProperty("threshold", threshold);
return continueTransition;
}
float FadeJob::computeElementEnterThreshold(double time, const double period, FadeConfig::Timing timing) const {
float FadeJob::computeElementEnterRatio(double time, const double period, FadeConfig::Timing timing) {
assert(period > 0.0);
float fadeAlpha = 1.0f;
const double INV_FADE_PERIOD = 1.0 / period;

View file

@ -193,8 +193,8 @@ private:
float _thresholdScale[render::Transition::EVENT_CATEGORY_COUNT];
uint64_t _previousTime{ 0 };
void update(const Config& config, const render::ScenePointer& scene, render::Transition& transition, const double deltaTime) const;
float computeElementEnterThreshold(double time, const double period, FadeConfig::Timing timing) const;
bool update(const Config& config, const render::ScenePointer& scene, render::Transition& transition, const double deltaTime) const;
static float computeElementEnterRatio(double time, const double period, FadeConfig::Timing timing);
const render::Item* findNearestItem(const render::RenderContextPointer& renderContext, const render::Varying& input, float& minIsectDistance) const;
};

View file

@ -104,7 +104,8 @@ void initDeferredPipelines(ShapePlumber& plumber, const render::ShapePipeline::B
void initForwardPipelines(ShapePlumber& plumber);
void addPlumberPipeline(ShapePlumber& plumber,
const ShapeKey& key, const gpu::ShaderPointer& vertex, const gpu::ShaderPointer& pixel);
const ShapeKey& key, const gpu::ShaderPointer& vertex, const gpu::ShaderPointer& pixel,
const render::ShapePipeline::BatchSetter& batchSetter, const render::ShapePipeline::ItemSetter& itemSetter);
void batchSetter(const ShapePipeline& pipeline, gpu::Batch& batch, RenderArgs* args);
void lightBatchSetter(const ShapePipeline& pipeline, gpu::Batch& batch, RenderArgs* args);
@ -228,30 +229,30 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip
auto simpleTranslucentUnlitFadePixel = gpu::Shader::createPixel(std::string(simple_transparent_textured_unlit_fade_frag));
using Key = render::ShapeKey;
auto addPipeline = std::bind(&addPlumberPipeline, std::ref(plumber), _1, _2, _3);
auto addPipeline = std::bind(&addPlumberPipeline, std::ref(plumber), _1, _2, _3, _4, _5);
// TODO: Refactor this to use a filter
// Opaques
addPipeline(
Key::Builder().withMaterial(),
modelVertex, modelPixel);
modelVertex, modelPixel, nullptr, nullptr);
addPipeline(
Key::Builder(),
simpleVertex, simplePixel);
simpleVertex, simplePixel, nullptr, nullptr);
addPipeline(
Key::Builder().withMaterial().withUnlit(),
modelVertex, modelUnlitPixel);
modelVertex, modelUnlitPixel, nullptr, nullptr);
addPipeline(
Key::Builder().withUnlit(),
simpleVertex, simpleUnlitPixel);
simpleVertex, simpleUnlitPixel, nullptr, nullptr);
addPipeline(
Key::Builder().withMaterial().withTangents(),
modelNormalMapVertex, modelNormalMapPixel);
modelNormalMapVertex, modelNormalMapPixel, nullptr, nullptr);
addPipeline(
Key::Builder().withMaterial().withSpecular(),
modelVertex, modelSpecularMapPixel);
modelVertex, modelSpecularMapPixel, nullptr, nullptr);
addPipeline(
Key::Builder().withMaterial().withTangents().withSpecular(),
modelNormalMapVertex, modelNormalSpecularMapPixel);
modelNormalMapVertex, modelNormalSpecularMapPixel, nullptr, nullptr);
// Same thing but with Fade on
addPipeline(
Key::Builder().withMaterial().withFade(),
@ -278,29 +279,29 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip
// Translucents
addPipeline(
Key::Builder().withMaterial().withTranslucent(),
modelVertex, modelTranslucentPixel);
modelVertex, modelTranslucentPixel, nullptr, nullptr);
addPipeline(
Key::Builder().withTranslucent(),
simpleVertex, simpleTranslucentPixel);
simpleVertex, simpleTranslucentPixel, nullptr, nullptr);
addPipeline(
Key::Builder().withMaterial().withTranslucent().withUnlit(),
modelVertex, modelTranslucentUnlitPixel);
modelVertex, modelTranslucentUnlitPixel, nullptr, nullptr);
addPipeline(
Key::Builder().withTranslucent().withUnlit(),
simpleVertex, simpleTranslucentUnlitPixel);
simpleVertex, simpleTranslucentUnlitPixel, nullptr, nullptr);
addPipeline(
Key::Builder().withMaterial().withTranslucent().withTangents(),
modelNormalMapVertex, modelTranslucentPixel);
modelNormalMapVertex, modelTranslucentPixel, nullptr, nullptr);
addPipeline(
Key::Builder().withMaterial().withTranslucent().withSpecular(),
modelVertex, modelTranslucentPixel);
modelVertex, modelTranslucentPixel, nullptr, nullptr);
addPipeline(
Key::Builder().withMaterial().withTranslucent().withTangents().withSpecular(),
modelNormalMapVertex, modelTranslucentPixel);
modelNormalMapVertex, modelTranslucentPixel, nullptr, nullptr);
addPipeline(
// FIXME: Ignore lightmap for translucents meshpart
Key::Builder().withMaterial().withTranslucent().withLightmap(),
modelVertex, modelTranslucentPixel);
modelVertex, modelTranslucentPixel, nullptr, nullptr);
// Same thing but with Fade on
addPipeline(
Key::Builder().withMaterial().withTranslucent().withFade(),
@ -331,16 +332,16 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip
// Lightmapped
addPipeline(
Key::Builder().withMaterial().withLightmap(),
modelLightmapVertex, modelLightmapPixel);
modelLightmapVertex, modelLightmapPixel, nullptr, nullptr);
addPipeline(
Key::Builder().withMaterial().withLightmap().withTangents(),
modelLightmapNormalMapVertex, modelLightmapNormalMapPixel);
modelLightmapNormalMapVertex, modelLightmapNormalMapPixel, nullptr, nullptr);
addPipeline(
Key::Builder().withMaterial().withLightmap().withSpecular(),
modelLightmapVertex, modelLightmapSpecularMapPixel);
modelLightmapVertex, modelLightmapSpecularMapPixel, nullptr, nullptr);
addPipeline(
Key::Builder().withMaterial().withLightmap().withTangents().withSpecular(),
modelLightmapNormalMapVertex, modelLightmapNormalSpecularMapPixel);
modelLightmapNormalMapVertex, modelLightmapNormalSpecularMapPixel, nullptr, nullptr);
// Same thing but with Fade on
addPipeline(
Key::Builder().withMaterial().withLightmap().withFade(),
@ -358,16 +359,16 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip
// Skinned
addPipeline(
Key::Builder().withMaterial().withSkinned(),
skinModelVertex, modelPixel);
skinModelVertex, modelPixel, nullptr, nullptr);
addPipeline(
Key::Builder().withMaterial().withSkinned().withTangents(),
skinModelNormalMapVertex, modelNormalMapPixel);
skinModelNormalMapVertex, modelNormalMapPixel, nullptr, nullptr);
addPipeline(
Key::Builder().withMaterial().withSkinned().withSpecular(),
skinModelVertex, modelSpecularMapPixel);
skinModelVertex, modelSpecularMapPixel, nullptr, nullptr);
addPipeline(
Key::Builder().withMaterial().withSkinned().withTangents().withSpecular(),
skinModelNormalMapVertex, modelNormalSpecularMapPixel);
skinModelNormalMapVertex, modelNormalSpecularMapPixel, nullptr, nullptr);
// Same thing but with Fade on
addPipeline(
Key::Builder().withMaterial().withSkinned().withFade(),
@ -385,16 +386,16 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip
// Skinned and Translucent
addPipeline(
Key::Builder().withMaterial().withSkinned().withTranslucent(),
skinModelVertex, modelTranslucentPixel);
skinModelVertex, modelTranslucentPixel, nullptr, nullptr);
addPipeline(
Key::Builder().withMaterial().withSkinned().withTranslucent().withTangents(),
skinModelNormalMapVertex, modelTranslucentPixel);
skinModelNormalMapVertex, modelTranslucentPixel, nullptr, nullptr);
addPipeline(
Key::Builder().withMaterial().withSkinned().withTranslucent().withSpecular(),
skinModelVertex, modelTranslucentPixel);
skinModelVertex, modelTranslucentPixel, nullptr, nullptr);
addPipeline(
Key::Builder().withMaterial().withSkinned().withTranslucent().withTangents().withSpecular(),
skinModelNormalMapVertex, modelTranslucentPixel);
skinModelNormalMapVertex, modelTranslucentPixel, nullptr, nullptr);
// Same thing but with Fade on
addPipeline(
Key::Builder().withMaterial().withSkinned().withTranslucent().withFade(),
@ -412,10 +413,10 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip
// Depth-only
addPipeline(
Key::Builder().withDepthOnly(),
modelShadowVertex, modelShadowPixel);
modelShadowVertex, modelShadowPixel, nullptr, nullptr);
addPipeline(
Key::Builder().withSkinned().withDepthOnly(),
skinModelShadowVertex, modelShadowPixel);
skinModelShadowVertex, modelShadowPixel, nullptr, nullptr);
// Same thing but with Fade on
addPipeline(
Key::Builder().withDepthOnly().withFade(),
@ -440,7 +441,7 @@ void initForwardPipelines(render::ShapePlumber& plumber) {
auto modelNormalSpecularMapPixel = gpu::Shader::createPixel(std::string(forward_model_normal_specular_map_frag));
using Key = render::ShapeKey;
auto addPipeline = std::bind(&addPlumberPipeline, std::ref(plumber), _1, _2, _3);
auto addPipeline = std::bind(&addPlumberPipeline, std::ref(plumber), _1, _2, _3, nullptr, nullptr);
// Opaques
addPipeline(
Key::Builder().withMaterial(),
@ -473,7 +474,8 @@ void initForwardPipelines(render::ShapePlumber& plumber) {
}
void addPlumberPipeline(ShapePlumber& plumber,
const ShapeKey& key, const gpu::ShaderPointer& vertex, const gpu::ShaderPointer& pixel) {
const ShapeKey& key, const gpu::ShaderPointer& vertex, const gpu::ShaderPointer& pixel,
const render::ShapePipeline::BatchSetter& extraBatchSetter, const render::ShapePipeline::ItemSetter& itemSetter) {
// These key-values' pipelines are added by this functor in addition to the key passed
assert(!key.isWireframe());
assert(!key.isDepthBiased());
@ -510,8 +512,18 @@ void addPlumberPipeline(ShapePlumber& plumber,
state->setDepthBiasSlopeScale(1.0f);
}
plumber.addPipeline(builder.build(), program, state,
key.isTranslucent() ? &lightBatchSetter : &batchSetter);
auto baseBatchSetter = key.isTranslucent() ? &lightBatchSetter : &batchSetter;
render::ShapePipeline::BatchSetter finalBatchSetter;
if (extraBatchSetter) {
finalBatchSetter = [baseBatchSetter, extraBatchSetter](const ShapePipeline& pipeline, gpu::Batch& batch, render::Args* args) {
baseBatchSetter(pipeline, batch, args);
extraBatchSetter(pipeline, batch, args);
};
}
else {
finalBatchSetter = baseBatchSetter;
}
plumber.addPipeline(builder.build(), program, state, finalBatchSetter, itemSetter);
}
}

View file

@ -13,6 +13,7 @@
#include <numeric>
#include <gpu/Batch.h>
#include "Logging.h"
#include "TransitionStage.h"
using namespace render;
@ -30,6 +31,11 @@ void Transaction::removeItem(ItemID id) {
_removedItems.emplace_back(id);
}
void Transaction::transitionItem(ItemID id, Transition::Type transition) {
_transitioningItems.emplace_back(id);
_transitionTypes.emplace_back(transition);
}
void Transaction::updateItem(ItemID id, const UpdateFunctorPointer& functor) {
_updatedItems.emplace_back(id);
_updateFunctors.emplace_back(functor);
@ -46,6 +52,8 @@ void Transaction::merge(const Transaction& transaction) {
_updatedItems.insert(_updatedItems.end(), transaction._updatedItems.begin(), transaction._updatedItems.end());
_updateFunctors.insert(_updateFunctors.end(), transaction._updateFunctors.begin(), transaction._updateFunctors.end());
_resetSelections.insert(_resetSelections.end(), transaction._resetSelections.begin(), transaction._resetSelections.end());
_transitioningItems.insert(_transitioningItems.end(), transaction._transitioningItems.begin(), transaction._transitioningItems.end());
_transitionTypes.insert(_transitionTypes.end(), transaction._transitionTypes.begin(), transaction._transitionTypes.end());
}
@ -115,6 +123,9 @@ void Scene::processTransactionQueue() {
// removes
removeItems(consolidatedTransaction._removedItems);
// Transitions
transitionItems(consolidatedTransaction._transitioningItems, consolidatedTransaction._transitionTypes);
// Update the numItemsAtomic counter AFTER the pending changes went through
_numAllocatedItems.exchange(maxID);
}
@ -216,6 +227,67 @@ void Scene::updateItems(const ItemIDs& ids, UpdateFunctors& functors) {
}
}
void Scene::transitionItems(const ItemIDs& ids, const TransitionTypes& types) {
auto transitionType = types.begin();
auto transitionStage = getStage<TransitionStage>(TransitionStage::getName());
for (auto itemId : ids) {
auto transitionId = INVALID_INDEX;
if (*transitionType != Transition::NONE) {
transitionId = transitionStage->addTransition(itemId, *transitionType);
}
setItemTransition(itemId, transitionId);
// next loop
transitionType++;
}
}
void Scene::collectSubItems(ItemID parentId, ItemIDs& subItems) const {
// Access the true item
auto& item = _items[parentId];
if (item.exist()) {
// Recursivelly collect the subitems
auto subItemBeginIndex = subItems.size();
auto subItemCount = item.fetchMetaSubItems(subItems);
for (auto i = subItemBeginIndex; i < (subItemBeginIndex + subItemCount); i++) {
collectSubItems(subItems[i], subItems);
}
}
}
void Scene::setItemTransition(ItemID itemId, Index transitionId) {
// Access the true item
auto& item = _items[itemId];
if (item.exist()) {
ItemIDs subItems;
item.setTransitionId(transitionId);
// Sub-items share the same transition Id
collectSubItems(itemId, subItems);
for (auto subItemId : subItems) {
auto& subItem = _items[subItemId];
subItem.setTransitionId(transitionId);
}
}
else {
qWarning() << "Collecting sub items on item without payload";
}
}
void Scene::resetItemTransition(ItemID itemId) {
// Access the true item
auto& item = _items[itemId];
auto transitionStage = getStage<TransitionStage>(TransitionStage::getName());
transitionStage->removeTransition(item.getTransitionId());
setItemTransition(itemId, Transition::NONE);
}
// THis fucntion is thread safe
Selection Scene::getSelection(const Selection::Name& name) const {
std::unique_lock<std::mutex> lock(_selectionsMutex);

View file

@ -16,6 +16,7 @@
#include "SpatialTree.h"
#include "Stage.h"
#include "Selection.h"
#include "Transition.h"
namespace render {
@ -39,6 +40,8 @@ public:
void resetItem(ItemID id, const PayloadPointer& payload);
void removeItem(ItemID id);
void transitionItem(ItemID id, Transition::Type transition);
template <class T> void updateItem(ItemID id, std::function<void(T&)> func) {
updateItem(id, std::make_shared<UpdateFunctor<T>>(func));
}
@ -54,10 +57,12 @@ public:
// Checkers if there is work to do when processing the transaction
bool touchTransactions() const { return !_resetSelections.empty(); }
ItemIDs _resetItems;
ItemIDs _resetItems;
Payloads _resetPayloads;
ItemIDs _removedItems;
ItemIDs _updatedItems;
ItemIDs _transitioningItems;
TransitionTypes _transitionTypes;
UpdateFunctors _updateFunctors;
Selections _resetSelections;
@ -123,6 +128,8 @@ public:
}
void resetStage(const Stage::Name& name, const StagePointer& stage);
void setItemTransition(ItemID id, Index transitionId);
void resetItemTransition(ItemID id);
protected:
// Thread safe elements that can be accessed from anywhere
@ -141,6 +148,9 @@ protected:
void resetItems(const ItemIDs& ids, Payloads& payloads);
void removeItems(const ItemIDs& ids);
void updateItems(const ItemIDs& ids, UpdateFunctors& functors);
void transitionItems(const ItemIDs& ids, const TransitionTypes& types);
void collectSubItems(ItemID parentId, ItemIDs& subItems) const;
// The Selection map
mutable std::mutex _selectionsMutex; // mutable so it can be used in the thread safe getSelection const method

View file

@ -27,7 +27,8 @@ namespace render {
AVATAR_CHANGE,
// Don't forget to modify Fade.slh to reflect the change in number of categories
EVENT_CATEGORY_COUNT
EVENT_CATEGORY_COUNT,
NONE = EVENT_CATEGORY_COUNT
};
Type eventType{ ELEMENT_ENTER_LEAVE_DOMAIN };
@ -41,6 +42,7 @@ namespace render {
};
typedef std::shared_ptr<Transition> TransitionPointer;
typedef std::vector<Transition::Type> TransitionTypes;
}
#endif // hifi_render_Transition_h