diff --git a/lib/flowViewport/API/CMakeLists.txt b/lib/flowViewport/API/CMakeLists.txt index 2229b0c326..5c42732fd5 100644 --- a/lib/flowViewport/API/CMakeLists.txt +++ b/lib/flowViewport/API/CMakeLists.txt @@ -5,6 +5,10 @@ set(HEADERS fvpInformationInterface.h fvpInformationClient.h fvpDataProducerSceneIndexInterface.h + fvpFilteringSceneIndexClient.h + fvpFilteringSceneIndexClientFwd.h + fvpFilteringSceneIndexInterface.h + fvpViewportAPITokens.h ) # ----------------------------------------------------------------------------- diff --git a/lib/flowViewport/API/fvpDataProducerSceneIndexInterface.h b/lib/flowViewport/API/fvpDataProducerSceneIndexInterface.h index 6f42666dc5..420a924847 100644 --- a/lib/flowViewport/API/fvpDataProducerSceneIndexInterface.h +++ b/lib/flowViewport/API/fvpDataProducerSceneIndexInterface.h @@ -19,6 +19,7 @@ //Local headers #include "flowViewport/api.h" +#include "flowViewport/API/fvpViewportAPITokens.h" //Hydra headers #include @@ -38,12 +39,6 @@ namespace FVP_NS_DEF /// Interface accessor static FVP_API DataProducerSceneIndexInterface& get(); - /// Use this string in the viewport identifier parameters, named "hydraViewportId" in this class, to apply the data producer scene index to all viewports. - static FVP_API const std::string allViewports; - - /// Use this string in the AddDataProducerSceneIndex method for the "rendererNames" parameter to apply to all renderers. - static FVP_API const std::string allRenderers; - /** * @brief Adds a custom data producer scene index. * @@ -77,8 +72,8 @@ namespace FVP_NS_DEF */ virtual bool addDataProducerSceneIndex(const PXR_NS::HdSceneIndexBaseRefPtr& customDataProducerSceneIndex, void* dccNode = nullptr, - const std::string& hydraViewportId = allViewports, - const std::string& rendererNames = allRenderers, + const std::string& hydraViewportId = PXR_NS::FvpViewportAPITokens->allViewports, + const std::string& rendererNames = PXR_NS::FvpViewportAPITokens->allRenderers, const PXR_NS::SdfPath& customDataProducerSceneIndexRootPathForInsertion = PXR_NS::SdfPath::AbsoluteRootPath() ) = 0; @@ -94,7 +89,7 @@ namespace FVP_NS_DEF */ virtual void removeViewportDataProducerSceneIndex(const PXR_NS::HdSceneIndexBaseRefPtr& customDataProducerSceneIndex, - const std::string& hydraViewportId = allViewports + const std::string& hydraViewportId = PXR_NS::FvpViewportAPITokens->allViewports ) = 0; }; diff --git a/lib/flowViewport/API/fvpFilteringSceneIndexClient.h b/lib/flowViewport/API/fvpFilteringSceneIndexClient.h new file mode 100644 index 0000000000..222059036b --- /dev/null +++ b/lib/flowViewport/API/fvpFilteringSceneIndexClient.h @@ -0,0 +1,157 @@ +// +// Copyright 2023 Autodesk, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + + +/// Is the definition of a customer Hydra client to register a set of callbacks for a Hydra viewport. +#ifndef FLOW_VIEWPORT_API_FILTERING_SCENE_INDEX_CLIENT_H +#define FLOW_VIEWPORT_API_FILTERING_SCENE_INDEX_CLIENT_H + +#include "flowViewport/api.h" +#include "flowViewport/API/fvpViewportAPITokens.h" + +#include + +namespace FVP_NS_DEF +{ + ///Subclass this to create a callbacks FilteringSceneIndexClient and register it through the FilteringSceneIndexInterface class + class FilteringSceneIndexClient + { + public: + /** + * A Category is a container in which you want your filtering scene index or scene index chain to go to. + * The filtering scene indices inside a Category don't have any specific priority when they are called. + */ + enum class Category + { + /// kSelectionHighlighting is to register a filtering scene index to do custom selection highlighting (still a WIP) + kSelectionHighlighting, + /** kSceneFiltering is to register a filtering scene index applied to the primitives from the scene, + * including usd stages, DCC native objects and custom data producer scene indices primitives. + */ + kSceneFiltering, + }; + + /** + * @brief Callback function to append a scene index. + * + * This callback function gets called for you to append a scene index to a Hydra viewport scene index, like a filtering scene index. + * A typical case is when a new Hydra viewport is created, after some internal managment of this scene index, we call this function so you can append one scene index + * or a chain of scene indices and return the last element of the chain. + * The returned value of this function is the last custom scene index of a a chain that you want to append to this scene index, + * or just return the input scene index passed if you don't want to append any scene index. + * + * @param[in] displayName is a display name to be associated with your plugin. + * @param[in] category is the container in which you want your filtering scene index (or filtering scene index chain) to go into. + * @param[in] rendererNames is the names of the renderers you want this client to be associated to. + * If there are several, separate them with for example a coma, like "GL, Arnold", we actually look for the renderer name in this string. + * If you want your client to work on any renderer please use FvpViewportAPITokens->allRenderers. + * @param[in] dccNode is a MObject* for Maya, if you provide the pointer value, then we automatically track some events such as visibility changed, + * node deleted/undeleted and we remove/add automatically your filtering scene indices from the viewport. Meaning if the maya node is visible your filtering + * scene indices are applied to the scene, if the node is not visible (or deleted) your filtering scene indices are removed from the scene. + * If it is a nullptr, your filtering scene indices will stay applied to the viewport(s) until you remove them. + * + * @param[in] inputArgs is a container data source handle to deal with the possibility to send custom data from our Hydra viewport plugin for the creation of your scene index. + * This parameter is currently not used by the Hydra viewport plugin but is left for possible future use. + */ + FilteringSceneIndexClient(const std::string& displayName, const Category category, const std::string& rendererNames, void* dccNode): + _displayName{displayName}, _category{category}, _rendererNames{rendererNames}, _dccNode{dccNode} + {} + + /** + * @brief Callback function to append a scene index. + * + * This callback function gets called for you to append a scene index to a Hydra viewport scene index, like a filtering scene index. + * A typical case is when a new Hydra viewport is created, after some internal managment of this scene index, we call this function so you can append one scene index + * or a chain of scene indices and return the last element of the chain. + * The returned value of this function is the last custom scene index of a a chain that you want to append to this scene index, + * or just return the input scene index passed if you don't want to append any scene index. + * + * @param[in] inputSceneIndex is a HdSceneIndexBaseRefPtr which was created by our Hydra viewport plugin. This could be the Hydra viewport scene index or it could be some appended + * scene index, as a chain of scene indices is appended to the Hydra viewport scene index if several filtering scene index clients are registered. + * So don't assume it's the Hydra viewport scene index. + * @param[in] inputArgs is a container data source handle to deal with the possibility to send custom data from our Hydra viewport plugin for the creation of your scene index. + * This parameter is currently not used by the Hydra viewport plugin but is left for possible future use. + * + * @return If you don't want to append a scene index, just return _inputSceneIndex. + * If you want to append a scene index or a scene indices chain, you should return the last scene index of the scene indices chain to append. + */ + virtual PXR_NS::HdSceneIndexBaseRefPtr appendSceneIndex(const PXR_NS::HdSceneIndexBaseRefPtr& inputSceneIndex, const PXR_NS::HdContainerDataSourceHandle& inputArgs) = 0; + + /// Destructor + virtual ~FilteringSceneIndexClient() = default; + + /** + * @brief Get the display name. + * @return the display name. + */ + const std::string& getDisplayName() const {return _displayName;} + + /** + * @brief Get the Category. + * @return the Category. + */ + const Category getCategory() const {return _category;} + + /** + * @brief Get the renderer names. + * @return the renderer names. + */ + const std::string& getRendererNames() const {return _rendererNames;} + + /** + * @brief Set the dcc node. + */ + void setDccNode(void* dccNode) {_dccNode = dccNode;} + + /** + * @brief Get the dcc node. + * @return the dcc node. + */ + void* getDccNode() const {return _dccNode;} + + bool operator == (const FilteringSceneIndexClient& other)const + { + return _displayName == other._displayName && + _category == other._category && + _rendererNames == other._rendererNames && + _dccNode == other._dccNode; + } + + protected: + /**_displayName is a display name to be associated with your plugin. + */ + const std::string _displayName {"Unnamed"}; + + /**_category is the container in which you want your filtering scene index (or filtering scene index chain) to go into. + */ + const Category _category {Category::kSceneFiltering}; + + /**_rendererNames is the names of the renderers you want this client to be associated to. + * If there are several, separate them with comas, like "GL, Arnold" + * If you want your client to work on any renderer please use FvpViewportAPITokens->allRenderers. + */ + const std::string _rendererNames = PXR_NS::FvpViewportAPITokens->allRenderers; + + /**_dccNode is a MObject* for Maya, if you provide the pointer value, then we automatically track some events such as visibility changed, + * node deleted/undeleted and we remove/add automatically your filtering scene indices from the viewport. Meaning if the maya node is visible your filtering + * scene indices are applied to the scene, if the node is not visible (or deleted) your filtering scene indices are removed from the scene. + * If it is a nullptr, your filtering scene indices will stay applied to the viewport(s) until you remove them. + */ + void* _dccNode = nullptr; + }; +}//end of namespace + +#endif //FLOW_VIEWPORT_API_FILTERING_SCENE_INDEX_CLIENT_H diff --git a/lib/flowViewport/API/fvpFilteringSceneIndexClientFwd.h b/lib/flowViewport/API/fvpFilteringSceneIndexClientFwd.h new file mode 100644 index 0000000000..3fb5c2dfa1 --- /dev/null +++ b/lib/flowViewport/API/fvpFilteringSceneIndexClientFwd.h @@ -0,0 +1,35 @@ +// +// Copyright 2023 Autodesk, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + + +/// Is the forward declaration of a FilteringSceneIndexClient + +#ifndef FLOW_VIEWPORT_API_FILTERING_SCENE_INDEX_CLIENT_FWD_H +#define FLOW_VIEWPORT_API_FILTERING_SCENE_INDEX_CLIENT_FWD_H + +#include "flowViewport/api.h" + +#include + +//Is the forward declaration of the FilteringSceneIndexClient class and FilteringSceneIndexClientPtr +namespace FVP_NS_DEF +{ + class FilteringSceneIndexClient; + using FilteringSceneIndexClientPtr = std::shared_ptr; + +}//end of namespace + +#endif //FLOW_VIEWPORT_API_FILTERING_SCENE_INDEX_CLIENT_FWD_H diff --git a/lib/flowViewport/API/fvpFilteringSceneIndexInterface.h b/lib/flowViewport/API/fvpFilteringSceneIndexInterface.h new file mode 100644 index 0000000000..22f1c28e21 --- /dev/null +++ b/lib/flowViewport/API/fvpFilteringSceneIndexInterface.h @@ -0,0 +1,65 @@ +// +// Copyright 2023 Autodesk, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#ifndef FLOW_VIEWPORT_API_FILTERING_SCENE_INDEX_INTERFACE_H +#define FLOW_VIEWPORT_API_FILTERING_SCENE_INDEX_INTERFACE_H + +//Local headers +#include "flowViewport/api.h" +#include "flowViewport/sceneIndex/fvpRenderIndexProxyFwd.h" +#include "flowViewport/API/fvpFilteringSceneIndexClientFwd.h" + +//Std headers +#include + +namespace FVP_NS_DEF +{ + /** + * Interface to register a callbacks FilteringSceneIndexClient and append custom filtering scene indices to Hydra viewports scene indices. + * To get an instance of the FilteringSceneIndexInterface class, please use : + * Fvp::FilteringSceneIndexInterface& filteringSceneIndexInterface = Fvp::FilteringSceneIndexInterface::get(); + * + * The filtering scene indices added to a hydra viewport will act on all kind of data : DCC native data, USD stages and custom primitives added by data producer scene indices. + */ + class FilteringSceneIndexInterface + { + public: + + ///Interface accessor + static FVP_API FilteringSceneIndexInterface& get(); + + /** + * @brief Register a callbacks SceneIndexClient instance + * + * @param[in] client is a FilteringSceneIndexClient. + * + * @return true if it succeded, false otherwise like the client if already registered. + */ + virtual bool registerFilteringSceneIndexClient(const std::shared_ptr& client) = 0; + + /** + * @brief Unregister an SceneIndexClient instance + * + * Unregister an SceneIndexClient instance, to stop receiving notifications. + * + * @param[in] client is the FilteringSceneIndexClient to remove. + */ + virtual void unregisterFilteringSceneIndexClient(const std::shared_ptr& client)= 0; + }; + +}//end of namespace + +#endif //FLOW_VIEWPORT_API_FILTERING_SCENE_INDEX_INTERFACE_H diff --git a/lib/flowViewport/API/fvpInformationInterface.h b/lib/flowViewport/API/fvpInformationInterface.h index 70b68e74a6..96795af357 100644 --- a/lib/flowViewport/API/fvpInformationInterface.h +++ b/lib/flowViewport/API/fvpInformationInterface.h @@ -47,14 +47,21 @@ namespace FVP_NS_DEF : _viewportId(viewportId), _cameraName(cameraName) {} ///_viewportId is a Hydra viewport string identifier which is unique for all hydra viewports during a session - const std::string _viewportId; + std::string _viewportId; ///_cameraName is the name of the camera/viewport when the viewport was created, it is not updated if the camera's name has changed. - const std::string _cameraName; + std::string _cameraName; ///_rendererName is the Hydra viewport renderer name (example : "GL" for Storm or "Arnold" for the Arnold render delegate) std::string _rendererName; + ViewportInformation& operator = (const ViewportInformation& other){ + _viewportId = other._viewportId; + _cameraName = other._cameraName; + _rendererName = other._rendererName; + return *this; + } + bool operator ==(const ViewportInformation& other)const{ return _viewportId == other._viewportId && _cameraName == other._cameraName && diff --git a/lib/flowViewport/API/fvpViewportAPITokens.h b/lib/flowViewport/API/fvpViewportAPITokens.h new file mode 100644 index 0000000000..ecf76bd95d --- /dev/null +++ b/lib/flowViewport/API/fvpViewportAPITokens.h @@ -0,0 +1,42 @@ +// +// Copyright 2023 Autodesk, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + + +/// Is the definition of a customer Hydra client to register a set of callbacks for a Hydra viewport. +#ifndef FLOW_VIEWPORT_API_VIEWPORT_API_TOKENS_H +#define FLOW_VIEWPORT_API_VIEWPORT_API_TOKENS_H + +#include "flowViewport/api.h" + +#include + +// *** TODO / FIXME *** Figure out how to put tokens into non-Pixar namespace. + +PXR_NAMESPACE_OPEN_SCOPE + +// clang-format off +#define FVP_VIEWPORT_API_TOKENS\ + /** Use this string in the viewport identifier parameters, named "hydraViewportId" in this class, to apply the data producer scene index to all viewports.*/\ + (allViewports) \ + /** Use this string for the "rendererNames" parameter to apply to all renderers.*/\ + (allRenderers) +// clang-format on + +TF_DECLARE_PUBLIC_TOKENS(FvpViewportAPITokens, FVP_API, FVP_VIEWPORT_API_TOKENS); + +PXR_NAMESPACE_CLOSE_SCOPE + +#endif //FLOW_VIEWPORT_API_VIEWPORT_API_TOKENS_H diff --git a/lib/flowViewport/API/interfacesImp/CMakeLists.txt b/lib/flowViewport/API/interfacesImp/CMakeLists.txt index f0390f6bdd..9a77bfe82e 100644 --- a/lib/flowViewport/API/interfacesImp/CMakeLists.txt +++ b/lib/flowViewport/API/interfacesImp/CMakeLists.txt @@ -7,6 +7,7 @@ target_sources(${TARGET_NAME} fvpVersionInterfaceImp.cpp fvpInformationInterfaceImp.cpp fvpDataProducerSceneIndexInterfaceImp.cpp + fvpFilteringSceneIndexInterfaceImp.cpp ) set(HEADERS @@ -14,6 +15,7 @@ set(HEADERS fvpVersionInterfaceImp.h fvpInformationInterfaceImp.h fvpDataProducerSceneIndexInterfaceImp.h + fvpFilteringSceneIndexInterfaceImp.h ) # ----------------------------------------------------------------------------- diff --git a/lib/flowViewport/API/interfacesImp/fvpDataProducerSceneIndexInterfaceImp.cpp b/lib/flowViewport/API/interfacesImp/fvpDataProducerSceneIndexInterfaceImp.cpp index fcc6428696..f45c6c5d6d 100644 --- a/lib/flowViewport/API/interfacesImp/fvpDataProducerSceneIndexInterfaceImp.cpp +++ b/lib/flowViewport/API/interfacesImp/fvpDataProducerSceneIndexInterfaceImp.cpp @@ -23,7 +23,7 @@ //Hydra headers #include -//STL Headers +//Std Headers #include namespace @@ -41,9 +41,6 @@ PXR_NAMESPACE_USING_DIRECTIVE namespace FVP_NS_DEF { -const std::string DataProducerSceneIndexInterface::allViewports = "allViewports"; -const std::string DataProducerSceneIndexInterface::allRenderers = "allRenderers"; - DataProducerSceneIndexInterface& DataProducerSceneIndexInterface::get() { return DataProducerSceneIndexInterfaceImp::get(); @@ -67,7 +64,7 @@ bool DataProducerSceneIndexInterfaceImp::addDataProducerSceneIndex(const PXR_NS: if (nullptr == dataProducerSceneIndexData){ return false; } - if (DataProducerSceneIndexInterface::allViewports == hydraViewportId){ + if (PXR_NS::FvpViewportAPITokens->allViewports == hydraViewportId){ //Apply this data producer scene index to all viewports return _AddDataProducerSceneIndexToAllViewports(dataProducerSceneIndexData); } @@ -92,7 +89,7 @@ void DataProducerSceneIndexInterfaceImp::removeAllViewportDataProducerSceneIndic auto& dataProducerSceneIndicesDataForthisViewport = viewportInformationAndSceneIndicesPerViewportData.GetDataProducerSceneIndicesData(); - for (auto& dataProducerSceneIndicesData : dataProducerSceneIndicesDataForthisViewport){ + for (const auto& dataProducerSceneIndicesData : dataProducerSceneIndicesDataForthisViewport){ //Remove it from the render index if (dataProducerSceneIndicesData){ const auto& sceneIndex = dataProducerSceneIndicesData->GetDataProducerLastSceneIndexChain(); @@ -110,16 +107,15 @@ void DataProducerSceneIndexInterfaceImp::removeAllViewportDataProducerSceneIndic void DataProducerSceneIndexInterfaceImp::removeViewportDataProducerSceneIndex(const PXR_NS::HdSceneIndexBaseRefPtr& customDataProducerSceneIndex, const std::string& hydraViewportId /*= allViewports*/) { - if (DataProducerSceneIndexInterface::allViewports == hydraViewportId){ + if (PXR_NS::FvpViewportAPITokens->allViewports == hydraViewportId){ //It was applied to all viewports - ViewportInformationAndSceneIndicesPerViewportDataSet& allViewportsInfoAndSceneIndices = + ViewportInformationAndSceneIndicesPerViewportDataVector& allViewportsInfoAndSceneIndices = ViewportInformationAndSceneIndicesPerViewportDataManager::Get().GetAllViewportInfoAndData(); //We need to remove it from all viewports where it was applied. for (auto& viewportInfoAndData : allViewportsInfoAndSceneIndices){ - ViewportInformationAndSceneIndicesPerViewportData& nonConstViewportInfoAndData = const_cast(viewportInfoAndData); - nonConstViewportInfoAndData.RemoveViewportDataProducerSceneIndex(customDataProducerSceneIndex); + viewportInfoAndData.RemoveViewportDataProducerSceneIndex(customDataProducerSceneIndex); } //Also remove it from the dataProducerSceneIndicesThatApplyToAllViewports array @@ -194,7 +190,7 @@ void DataProducerSceneIndexInterfaceImp::_AddDataProducerSceneIndexToThisViewpor //Check if there is some filtering per Hydra renderer const std::string& viewportRendererName = viewportInformation._rendererName; const std::string& dataProducerSceneIndexApplyToRendererNames = dataProducerSceneIndexData->GetRendererNames(); - if ( (! viewportRendererName.empty() )&& (dataProducerSceneIndexApplyToRendererNames != DataProducerSceneIndexInterface::allRenderers) ){ + if ( (! viewportRendererName.empty() )&& (dataProducerSceneIndexApplyToRendererNames != PXR_NS::FvpViewportAPITokens->allRenderers) ){ //Filtering per renderer is applied if (std::string::npos == dataProducerSceneIndexApplyToRendererNames.find(viewportRendererName)){ return; //Ignore the current hydra viewport renderer name is not part of the supported renderers for this data producer scene index diff --git a/lib/flowViewport/API/interfacesImp/fvpDataProducerSceneIndexInterfaceImp.h b/lib/flowViewport/API/interfacesImp/fvpDataProducerSceneIndexInterfaceImp.h index a567dc45af..ee7b6bd407 100644 --- a/lib/flowViewport/API/interfacesImp/fvpDataProducerSceneIndexInterfaceImp.h +++ b/lib/flowViewport/API/interfacesImp/fvpDataProducerSceneIndexInterfaceImp.h @@ -24,8 +24,9 @@ #include "flowViewport/API/fvpDataProducerSceneIndexInterface.h" #include "flowViewport/API/fvpInformationInterface.h" #include "flowViewport/API/perViewportSceneIndicesData/fvpDataProducerSceneIndexDataAbstractFactory.h" +#include "flowViewport/API/fvpViewportAPITokens.h" -//STL Headers +//Std Headers #include namespace FVP_NS_DEF { @@ -45,12 +46,12 @@ class DataProducerSceneIndexInterfaceImp : public DataProducerSceneIndexInterfac ///From FVP_NS_DEF::DataProducerSceneIndexInterface bool addDataProducerSceneIndex(const PXR_NS::HdSceneIndexBaseRefPtr& customDataProducerSceneIndex, void* dccNode = nullptr, - const std::string& hydraViewportId = allViewports, - const std::string& rendererNames = allRenderers, + const std::string& hydraViewportId = PXR_NS::FvpViewportAPITokens->allViewports, + const std::string& rendererNames = PXR_NS::FvpViewportAPITokens->allRenderers, const PXR_NS::SdfPath& customDataProducerSceneIndexRootPathForInsertion = PXR_NS::SdfPath::AbsoluteRootPath() )override; void removeViewportDataProducerSceneIndex(const PXR_NS::HdSceneIndexBaseRefPtr& customDataProducerSceneIndex, - const std::string& hydraViewportId = allViewports)override; + const std::string& hydraViewportId = PXR_NS::FvpViewportAPITokens->allViewports)override; //Called by flow viewport ///hydraViewportSceneIndexAdded is called when a new hydra viewport is created by the ViewportInformationAndSceneIndicesPerViewportDataManager, it's not a callback. diff --git a/lib/flowViewport/API/interfacesImp/fvpFilteringSceneIndexInterfaceImp.cpp b/lib/flowViewport/API/interfacesImp/fvpFilteringSceneIndexInterfaceImp.cpp new file mode 100644 index 0000000000..eee2610bc4 --- /dev/null +++ b/lib/flowViewport/API/interfacesImp/fvpFilteringSceneIndexInterfaceImp.cpp @@ -0,0 +1,208 @@ +// +// Copyright 2023 Autodesk, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +//Local headers +#include "fvpFilteringSceneIndexInterfaceImp.h" +#include "flowViewport/API/perViewportSceneIndicesData/fvpFilteringSceneIndicesChainManager.h" + +//Std headers +#include + +namespace +{ + std::mutex selectionHighlightFilteringClient_mutex; + std::mutex sceneFilteringClient_mutex; + + //Set of scene Filtering scene index data, they belong to the Fpv::FilteringSceneIndexClient::Category::kSceneFiltering + std::set sceneFilteringSceneIndicesData; + + //Set of selection highlighting Filtering scene index data, they belong to the Fpv::FilteringSceneIndexClient::Category::kSelectionHighlighting + std::set selectionHighlightFilteringSceneIndicesData; + + // Abstract factory to create the scene index data, an implementation is provided by the DCC + FVP_NS::FilteringSceneIndexDataAbstractFactory* sceneIndexDataFactory{nullptr}; +} + +PXR_NAMESPACE_USING_DIRECTIVE + +namespace FVP_NS_DEF { + +FilteringSceneIndexInterface& FilteringSceneIndexInterface::get() +{ + return FilteringSceneIndexInterfaceImp::get(); +} + +FilteringSceneIndexInterfaceImp& FilteringSceneIndexInterfaceImp::get() +{ + static FilteringSceneIndexInterfaceImp theInterface; + return theInterface; +} + +FilteringSceneIndexInterfaceImp::~FilteringSceneIndexInterfaceImp() +{ +} + +bool FilteringSceneIndexInterfaceImp::registerFilteringSceneIndexClient(const std::shared_ptr& client) +{ + switch(client->getCategory()){ + case Fvp::FilteringSceneIndexClient::Category::kSceneFiltering:{ + return _CreateSceneFilteringSceneIndicesData(client); + } + break; + case Fvp::FilteringSceneIndexClient::Category::kSelectionHighlighting:{ + return _CreateSelectionHighlightFilteringSceneIndicesData(client); + } + break; + default:{ + TF_AXIOM(0);//Should never happen + } + } + return false; +} + +bool FilteringSceneIndexInterfaceImp::_CreateSceneFilteringSceneIndicesData(const std::shared_ptr& client) +{ + TF_AXIOM(sceneIndexDataFactory); + + bool bNeedToUpdateViewportsFilteringSceneIndicesChain = false; + + //Block for the lock lifetime + { + std::lock_guard lock(sceneFilteringClient_mutex); + + auto findResult = std::find_if(sceneFilteringSceneIndicesData.cbegin(), sceneFilteringSceneIndicesData.cend(), + [&client](const PXR_NS::FVP_NS_DEF::FilteringSceneIndexDataBaseRefPtr& filteringSIData) { return filteringSIData->getClient() == client;}); + if (findResult != sceneFilteringSceneIndicesData.cend()){ + return false; + } + + //Call the abstract scene index data factory to create a subclass of FilteringSceneIndexDataBase + PXR_NS::FVP_NS_DEF::FilteringSceneIndexDataBaseRefPtr data = sceneIndexDataFactory->createFilteringSceneIndexDataBase(client); + sceneFilteringSceneIndicesData.insert(data); + bNeedToUpdateViewportsFilteringSceneIndicesChain = true; + } + + if (bNeedToUpdateViewportsFilteringSceneIndicesChain){ + FilteringSceneIndicesChainManager::get().updateFilteringSceneIndicesChain(client->getRendererNames()); + } + + return true; +} + +bool FilteringSceneIndexInterfaceImp::_CreateSelectionHighlightFilteringSceneIndicesData(const std::shared_ptr& client) +{ + TF_AXIOM(sceneIndexDataFactory); + + //Block for the lock lifetime + { + std::lock_guard lock(selectionHighlightFilteringClient_mutex); + + auto findResult = std::find_if(selectionHighlightFilteringSceneIndicesData.cbegin(), selectionHighlightFilteringSceneIndicesData.cend(), + [&client](const PXR_NS::FVP_NS_DEF::FilteringSceneIndexDataBaseRefPtr& filteringSIData) { return filteringSIData->getClient() == client;}); + if (findResult != selectionHighlightFilteringSceneIndicesData.cend()){ + return false; + } + + //Call the abstract scene index data factory to create a subclass of FilteringSceneIndexDataBase + PXR_NS::FVP_NS_DEF::FilteringSceneIndexDataBaseRefPtr data = sceneIndexDataFactory->createFilteringSceneIndexDataBase(client); + selectionHighlightFilteringSceneIndicesData.insert(data); + } + + //TODO add it somewhere in selection highlight + + return true; +} + +void FilteringSceneIndexInterfaceImp::_DestroySceneFilteringSceneIndicesData(const std::shared_ptr<::FVP_NS_DEF::FilteringSceneIndexClient>& client) +{ + + bool bNeedToUpdateViewportsFilteringSceneIndicesChain = false; + std::string rendererNames; + + //Block for the lock lifetime + { + std::lock_guard lock(sceneFilteringClient_mutex); + + auto findResult = std::find_if(sceneFilteringSceneIndicesData.cbegin(), sceneFilteringSceneIndicesData.cend(), + [&client](const PXR_NS::FVP_NS_DEF::FilteringSceneIndexDataBaseRefPtr& filteringSIData) { return filteringSIData->getClient() == client;}); + if (findResult != sceneFilteringSceneIndicesData.cend()){ + const auto& filteringSIData = (*findResult); + rendererNames = (filteringSIData) + ? filteringSIData->getClient()->getRendererNames() + : FvpViewportAPITokens->allRenderers; + + sceneFilteringSceneIndicesData.erase(findResult);//This also decreases ref count + + bNeedToUpdateViewportsFilteringSceneIndicesChain = true; + } + } + + if (bNeedToUpdateViewportsFilteringSceneIndicesChain){ + //Update the filtering scene indices chain from the viewports that were using this filtering scene index client + FilteringSceneIndicesChainManager::get().updateFilteringSceneIndicesChain(rendererNames); + } +} + +void FilteringSceneIndexInterfaceImp::_DestroySelectionHighlightFilteringSceneIndicesData(const std::shared_ptr& client) +{ + //Block for the lock lifetime + { + std::lock_guard lock(selectionHighlightFilteringClient_mutex); + + auto findResult = std::find_if(selectionHighlightFilteringSceneIndicesData.cbegin(), selectionHighlightFilteringSceneIndicesData.cend(), + [&client](const PXR_NS::FVP_NS_DEF::FilteringSceneIndexDataBaseRefPtr& filteringSIData) { return filteringSIData->getClient() == client;}); + if (findResult != selectionHighlightFilteringSceneIndicesData.cend()){ + selectionHighlightFilteringSceneIndicesData.erase(findResult);//Also decreases ref count + } + } +} + +void FilteringSceneIndexInterfaceImp::unregisterFilteringSceneIndexClient(const std::shared_ptr& client) +{ + switch(client->getCategory()){ + case Fvp::FilteringSceneIndexClient::Category::kSceneFiltering:{ + _DestroySceneFilteringSceneIndicesData(client); + } + break; + case Fvp::FilteringSceneIndexClient::Category::kSelectionHighlighting:{ + _DestroySelectionHighlightFilteringSceneIndicesData(client); + } + break; + default:{ + TF_AXIOM(0);//Should never happen + } + } +} + +const std::set& FilteringSceneIndexInterfaceImp::getSceneFilteringSceneIndicesData()const +{ + std::lock_guard lock(sceneFilteringClient_mutex); + return sceneFilteringSceneIndicesData; +} + +const std::set& FilteringSceneIndexInterfaceImp::getSelectionHighlightFilteringSceneIndicesData() const +{ + std::lock_guard lock(selectionHighlightFilteringClient_mutex); + return selectionHighlightFilteringSceneIndicesData; +} + +void FilteringSceneIndexInterfaceImp::setSceneIndexDataFactory(FilteringSceneIndexDataAbstractFactory& factory) +{ + sceneIndexDataFactory = &factory; +} + +}//End of namespace FVP_NS_DEF + diff --git a/lib/flowViewport/API/interfacesImp/fvpFilteringSceneIndexInterfaceImp.h b/lib/flowViewport/API/interfacesImp/fvpFilteringSceneIndexInterfaceImp.h new file mode 100644 index 0000000000..ad3bb3bdfc --- /dev/null +++ b/lib/flowViewport/API/interfacesImp/fvpFilteringSceneIndexInterfaceImp.h @@ -0,0 +1,64 @@ +// +// Copyright 2023 Autodesk, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#ifndef FLOW_VIEWPORT_API_INTERFACESIMP_FILTERING_SCENE_INDEX_INTERFACE_IMP_H +#define FLOW_VIEWPORT_API_INTERFACESIMP_FILTERING_SCENE_INDEX_INTERFACE_IMP_H + +//Local headers +#include "flowViewport/api.h" +#include "flowViewport/API/fvpFilteringSceneIndexInterface.h"//Viewport API headers +#include "flowViewport/API/fvpFilteringSceneIndexClient.h" +#include "flowViewport/API/perViewportSceneIndicesData/fvpFilteringSceneIndexDataAbstractFactory.h" + +//Std headers +#include + +namespace FVP_NS_DEF { + +///Is a singleton, use Fvp::FilteringSceneIndexInterfaceImp& filteringSceneIndexInterfaceImp = Fvp::FilteringSceneIndexInterfaceImp::Get() to get an instance of that interface +class FilteringSceneIndexInterfaceImp : public FilteringSceneIndexInterface +{ +public: + FilteringSceneIndexInterfaceImp() = default; + virtual ~FilteringSceneIndexInterfaceImp(); + + ///Interface accessor + static FVP_API FilteringSceneIndexInterfaceImp& get(); + + //From FVP_NS_DEF::FilteringSceneIndexInterface + bool registerFilteringSceneIndexClient(const std::shared_ptr& client) override; + void unregisterFilteringSceneIndexClient(const std::shared_ptr& client) override; + + //Called by the DCC + FVP_API + void setSceneIndexDataFactory(FilteringSceneIndexDataAbstractFactory& factory); + + //Called by Flow viewport + const std::set& getSceneFilteringSceneIndicesData() const; + const std::set& getSelectionHighlightFilteringSceneIndicesData() const; + +private : + bool _CreateSceneFilteringSceneIndicesData(const std::shared_ptr& client); + bool _CreateSelectionHighlightFilteringSceneIndicesData(const std::shared_ptr& client); + void _DestroySceneFilteringSceneIndicesData(const std::shared_ptr& client); + void _DestroySelectionHighlightFilteringSceneIndicesData(const std::shared_ptr& client); + +}; + +} //end of namespace FVP_NS_DEF + + +#endif // FLOW_VIEWPORT_API_INTERFACESIMP_FILTERING_SCENE_INDEX_INTERFACE_IMP_H \ No newline at end of file diff --git a/lib/flowViewport/API/interfacesImp/fvpInformationInterfaceImp.cpp b/lib/flowViewport/API/interfacesImp/fvpInformationInterfaceImp.cpp index a46623ad8c..26dccc5bc2 100644 --- a/lib/flowViewport/API/interfacesImp/fvpInformationInterfaceImp.cpp +++ b/lib/flowViewport/API/interfacesImp/fvpInformationInterfaceImp.cpp @@ -88,7 +88,7 @@ void InformationInterfaceImp::SceneIndexRemoved(const InformationInterface::View void InformationInterfaceImp::GetViewportsInformation(ViewportInformationSet& outHydraViewportInformationArray)const { outHydraViewportInformationArray.clear(); - const ViewportInformationAndSceneIndicesPerViewportDataSet& allViewportInformationAndSceneIndicesPerViewportData = + const ViewportInformationAndSceneIndicesPerViewportDataVector& allViewportInformationAndSceneIndicesPerViewportData = ViewportInformationAndSceneIndicesPerViewportDataManager::Get().GetAllViewportInfoAndData(); for (const ViewportInformationAndSceneIndicesPerViewportData& viewportInformationAndSceneIndicesPerViewportData : allViewportInformationAndSceneIndicesPerViewportData){ const InformationInterface::ViewportInformation& viewportInfo = viewportInformationAndSceneIndicesPerViewportData.GetViewportInformation(); diff --git a/lib/flowViewport/API/interfacesImp/fvpSelectionInterfaceImp.cpp b/lib/flowViewport/API/interfacesImp/fvpSelectionInterfaceImp.cpp index d525e7dd71..57fee1f414 100644 --- a/lib/flowViewport/API/interfacesImp/fvpSelectionInterfaceImp.cpp +++ b/lib/flowViewport/API/interfacesImp/fvpSelectionInterfaceImp.cpp @@ -17,7 +17,7 @@ //Local headers #include "fvpSelectionInterfaceImp.h" -//STL +//Std Headers #include namespace{ diff --git a/lib/flowViewport/API/perViewportSceneIndicesData/CMakeLists.txt b/lib/flowViewport/API/perViewportSceneIndicesData/CMakeLists.txt index b06b020251..fb33710423 100644 --- a/lib/flowViewport/API/perViewportSceneIndicesData/CMakeLists.txt +++ b/lib/flowViewport/API/perViewportSceneIndicesData/CMakeLists.txt @@ -6,6 +6,9 @@ target_sources(${TARGET_NAME} fvpViewportInformationAndSceneIndicesPerViewportData.cpp fvpViewportInformationAndSceneIndicesPerViewportDataManager.cpp fvpDataProducerSceneIndexDataBase.cpp + fvpFilteringSceneIndexDataBase.cpp + fvpFilteringSceneIndicesChainManager.cpp + fvpViewportAPITokens.cpp ) set(HEADERS @@ -13,6 +16,9 @@ set(HEADERS fvpViewportInformationAndSceneIndicesPerViewportDataManager.h fvpDataProducerSceneIndexDataAbstractFactory.h fvpDataProducerSceneIndexDataBase.h + fvpFilteringSceneIndexDataAbstractFactory.h + fvpFilteringSceneIndexDataBase.h + fvpFilteringSceneIndicesChainManager.h ) # ----------------------------------------------------------------------------- diff --git a/lib/flowViewport/API/perViewportSceneIndicesData/fvpDataProducerSceneIndexDataAbstractFactory.h b/lib/flowViewport/API/perViewportSceneIndicesData/fvpDataProducerSceneIndexDataAbstractFactory.h index dcd577e4b1..a24275406e 100644 --- a/lib/flowViewport/API/perViewportSceneIndicesData/fvpDataProducerSceneIndexDataAbstractFactory.h +++ b/lib/flowViewport/API/perViewportSceneIndicesData/fvpDataProducerSceneIndexDataAbstractFactory.h @@ -21,13 +21,13 @@ namespace FVP_NS_DEF { -/** Since Flow viewport is DCC agnostic, the DCC will implement a concrete factory subclassing that class to provide specific -* DCC implementation of the classes mentioned. +/** Since Flow viewport is DCC agnostic, the DCC will implement a concrete factory subclassing that class to provide a specific +* DCC implementation of DataProducerSceneIndexDataBaseRefPtr. */ class DataProducerSceneIndexDataAbstractFactory { public: - /// The DCC will create a subclass of DataProducerSceneIndexDataBaseRefPtr with specific DCC variables that flow viewport cannot manage since it's DCC agnostic + /// The DCC will create a subclass of DataProducerSceneIndexDataBaseRefPtr with specific DCC variables that Flow viewport cannot manage since it's DCC agnostic virtual PXR_NS::FVP_NS_DEF::DataProducerSceneIndexDataBaseRefPtr createDataProducerSceneIndexDataBase( const PXR_NS::FVP_NS_DEF::DataProducerSceneIndexDataBase::CreationParameters& params) = 0; }; diff --git a/lib/flowViewport/API/perViewportSceneIndicesData/fvpDataProducerSceneIndexDataBase.h b/lib/flowViewport/API/perViewportSceneIndicesData/fvpDataProducerSceneIndexDataBase.h index b4cd278e8f..d25f35ec21 100644 --- a/lib/flowViewport/API/perViewportSceneIndicesData/fvpDataProducerSceneIndexDataBase.h +++ b/lib/flowViewport/API/perViewportSceneIndicesData/fvpDataProducerSceneIndexDataBase.h @@ -88,7 +88,7 @@ TF_DECLARE_WEAK_AND_REF_PTRS(DataProducerSceneIndexDataBase);//Be able to use Re void* _dccNode; //The following members are optional and only used when a dccNode was passed in the constructor - /** Is a filtering scene index that modifies the parent prim from the retained scene index to update the transfor/visibility when it is updated in the DCC. + /** Is a filtering scene index that modifies the parent prim from the retained scene index to update the transform/visibility when it is updated in the DCC. It is used only when a dccNode was passed.*/ ParentDataModifierSceneIndexRefPtr _parentDataModifierSceneIndex = nullptr; /// ParentPath prim used to be the parent of all prims from _dataProducerSceneIndex, used only when a dccNode was passed diff --git a/lib/flowViewport/API/perViewportSceneIndicesData/fvpFilteringSceneIndexDataAbstractFactory.h b/lib/flowViewport/API/perViewportSceneIndicesData/fvpFilteringSceneIndexDataAbstractFactory.h new file mode 100644 index 0000000000..271a8d0cf5 --- /dev/null +++ b/lib/flowViewport/API/perViewportSceneIndicesData/fvpFilteringSceneIndexDataAbstractFactory.h @@ -0,0 +1,37 @@ +// +// Copyright 2023 Autodesk +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef FLOW_VIEWPORT_API_PERVIEWPORTSCENEINDICESDATA_FILTERING_SCENE_INDEX_DATA_ABSTRACT_FACTORY_H +#define FLOW_VIEWPORT_API_PERVIEWPORTSCENEINDICESDATA_FILTERING_SCENE_INDEX_DATA_ABSTRACT_FACTORY_H + +//Flow Viewport headers +#include "fvpFilteringSceneIndexDataBase.h" + +namespace FVP_NS_DEF { + +/** Since Flow viewport is DCC agnostic, the DCC will implement a concrete factory subclassing that class to provide a specific +* DCC implementation of FilteringSceneIndexDataBaseRefPtr. +*/ +class FilteringSceneIndexDataAbstractFactory +{ +public: + /// The DCC will create a subclass of FilteringSceneIndexDataBaseRefPtr with specific DCC variables that Flow viewport cannot manage since it's DCC agnostic + virtual PXR_NS::FVP_NS_DEF::FilteringSceneIndexDataBaseRefPtr createFilteringSceneIndexDataBase(const std::shared_ptr<::Fvp::FilteringSceneIndexClient>& client) = 0; +}; + +}//End of namespace FVP_NS_DEF { + +#endif //FLOW_VIEWPORT_API_PERVIEWPORTSCENEINDICESDATA_FILTERING_SCENE_INDEX_DATA_ABSTRACT_FACTORY_H + diff --git a/lib/flowViewport/API/perViewportSceneIndicesData/fvpFilteringSceneIndexDataBase.cpp b/lib/flowViewport/API/perViewportSceneIndicesData/fvpFilteringSceneIndexDataBase.cpp new file mode 100644 index 0000000000..6fc96393e0 --- /dev/null +++ b/lib/flowViewport/API/perViewportSceneIndicesData/fvpFilteringSceneIndexDataBase.cpp @@ -0,0 +1,41 @@ +// +// Copyright 2023 Autodesk +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + + +//Local headers +#include "fvpFilteringSceneIndexDataBase.h" +#include "flowViewport/API/fvpFilteringSceneIndexClient.h" +#include "flowViewport/API/perViewportSceneIndicesData/fvpFilteringSceneIndicesChainManager.h" + +PXR_NAMESPACE_OPEN_SCOPE + +namespace FVP_NS_DEF { + +FilteringSceneIndexDataBase::FilteringSceneIndexDataBase(const std::shared_ptr<::Fvp::FilteringSceneIndexClient>& filteringSIClient) + : _client {filteringSIClient} +{ +} + +void FilteringSceneIndexDataBase::updateVisibilityFromDCCNode(bool isVisible) +{ + _isVisible = isVisible; + const std::string& rendererNames = _client->getRendererNames(); + ::Fvp::FilteringSceneIndicesChainManager::get().updateFilteringSceneIndicesChain(rendererNames); +} + +}//End of namespace FVP_NS_DEF + +PXR_NAMESPACE_CLOSE_SCOPE \ No newline at end of file diff --git a/lib/flowViewport/API/perViewportSceneIndicesData/fvpFilteringSceneIndexDataBase.h b/lib/flowViewport/API/perViewportSceneIndicesData/fvpFilteringSceneIndexDataBase.h new file mode 100644 index 0000000000..b58e8bda6b --- /dev/null +++ b/lib/flowViewport/API/perViewportSceneIndicesData/fvpFilteringSceneIndexDataBase.h @@ -0,0 +1,64 @@ +// +// Copyright 2023 Autodesk +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef FLOW_VIEWPORT_API_PERVIEWPORTSCENEINDICESDATA_FILTERING_SCENE_INDEX_DATA_BASE_H +#define FLOW_VIEWPORT_API_PERVIEWPORTSCENEINDICESDATA_FILTERING_SCENE_INDEX_DATA_BASE_H + +//Flow Viewport headers +#include "flowViewport/api.h" +#include "flowViewport/API/fvpFilteringSceneIndexInterface.h" + +//Hydra headers +#include +#include + +//The Pixar's namespace needs to be at the highest namespace level for TF_DECLARE_WEAK_AND_REF_PTRS to work. +PXR_NAMESPACE_OPEN_SCOPE + +namespace FVP_NS_DEF { + +class FilteringSceneIndexDataBase;//Predeclaration +TF_DECLARE_WEAK_AND_REF_PTRS(FilteringSceneIndexDataBase);//Be able to use Ref counting pointers on FilteringSceneIndexDataBase + +/** In this class, we store a filtering scene index client and all the filtering scene indices that this client has appended to a viewport, the filtering scene indices +* could be applied to different viewports +*/ + class FVP_API FilteringSceneIndexDataBase : public TfRefBase, public TfWeakBase +{ +public: + + ~FilteringSceneIndexDataBase() override = default; + + void updateVisibilityFromDCCNode(bool isVisible); + std::shared_ptr<::Fvp::FilteringSceneIndexClient> getClient() {return _client;} + bool getVisible() const{return _isVisible;} + void setVisible(bool visible) {_isVisible = visible;} + +protected: + FilteringSceneIndexDataBase(const std::shared_ptr<::Fvp::FilteringSceneIndexClient>& filteringSIClient); + + /// Filtering scene index client, not owned by this class + const std::shared_ptr<::Fvp::FilteringSceneIndexClient> _client; + + ///_isVisible is true when the filteringSceneIndices should be visible and false when they are not such as when the hosting node has been hidden/deleted. + bool _isVisible = true; +}; + +}//End of namespace FVP_NS_DEF { + +PXR_NAMESPACE_CLOSE_SCOPE + +#endif //FLOW_VIEWPORT_API_PERVIEWPORTSCENEINDICESDATA_FILTERING_SCENE_INDEX_DATA_BASE_H + diff --git a/lib/flowViewport/API/perViewportSceneIndicesData/fvpFilteringSceneIndicesChainManager.cpp b/lib/flowViewport/API/perViewportSceneIndicesData/fvpFilteringSceneIndicesChainManager.cpp new file mode 100644 index 0000000000..b804ac1a60 --- /dev/null +++ b/lib/flowViewport/API/perViewportSceneIndicesData/fvpFilteringSceneIndicesChainManager.cpp @@ -0,0 +1,169 @@ +// +// Copyright 2023 Autodesk +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +//Local headers +#include "fvpFilteringSceneIndicesChainManager.h" +#include "flowViewport/sceneIndex/fvpRenderIndexProxy.h" +#include "flowViewport/API/interfacesImp/fvpFilteringSceneIndexInterfaceImp.h" +#include "flowViewport/API/perViewportSceneIndicesData/fvpViewportInformationAndSceneIndicesPerViewportDataManager.h" + +//Hydra headers +#include +#include + +PXR_NAMESPACE_USING_DIRECTIVE + +namespace FVP_NS_DEF { + +//Singleton access +FilteringSceneIndicesChainManager& FilteringSceneIndicesChainManager::get() +{ + static FilteringSceneIndicesChainManager FilteringSceneIndicesChainManager; + return FilteringSceneIndicesChainManager; +} + +FilteringSceneIndicesChainManager::~FilteringSceneIndicesChainManager() +{ +} + +HdSceneIndexBaseRefPtr FilteringSceneIndicesChainManager::createFilteringSceneIndicesChain(ViewportInformationAndSceneIndicesPerViewportData& viewportInformationAndSceneIndicesPerViewportData, + const HdSceneIndexBaseRefPtr& inputFilteringSceneIndex /*= nullptr*/) +{ + HdSceneIndexBaseRefPtr inputSceneIndex = inputFilteringSceneIndex; + if (nullptr == inputSceneIndex){ + inputSceneIndex = viewportInformationAndSceneIndicesPerViewportData.GetInputSceneIndex(); + }else{ + viewportInformationAndSceneIndicesPerViewportData.SetInputSceneIndex(inputSceneIndex); + } + TF_AXIOM(inputSceneIndex); + + if ( ! _enabled){ + return inputSceneIndex; + } + + if (viewportInformationAndSceneIndicesPerViewportData.GetLastFilteringSceneIndex() != nullptr){ + TF_CODING_ERROR("viewportInformationAndSceneIndicesPerViewportData->GetLastFilteringSceneIndex() != nullptr should not happen, \ + you should call DestroyFilteringSceneIndicesChain before calling the current function"); + return nullptr;//Not an empty filtering scene indices chain + } + + //Append the filtering scene indices chain tp the merging scene index from renderIndexProxy + _AppendFilteringSceneIndicesChain(viewportInformationAndSceneIndicesPerViewportData, inputSceneIndex); + + if (viewportInformationAndSceneIndicesPerViewportData.GetLastFilteringSceneIndex() == nullptr){ + TF_CODING_ERROR("viewportInformationAndSceneIndicesPerViewportData->GetLastFilteringSceneIndex() == nullptr is invalid here"); + return nullptr; + } + + //Add the last element of the filtering scene indices chain to the render index + return viewportInformationAndSceneIndicesPerViewportData.GetLastFilteringSceneIndex(); +} + +void FilteringSceneIndicesChainManager::destroyFilteringSceneIndicesChain(ViewportInformationAndSceneIndicesPerViewportData& viewportInformationAndSceneIndicesPerViewportData) +{ + HdSceneIndexBaseRefPtr& lastSceneIndex = viewportInformationAndSceneIndicesPerViewportData.GetLastFilteringSceneIndex(); + if (nullptr == lastSceneIndex){ + return; + } + + auto renderIndexProxy = viewportInformationAndSceneIndicesPerViewportData.GetRenderIndexProxy(); + TF_AXIOM(renderIndexProxy); + auto renderIndex = renderIndexProxy->GetRenderIndex(); + TF_AXIOM(renderIndex); + renderIndex->RemoveSceneIndex(lastSceneIndex);//Remove the whole chain from the render index + + //Remove a ref on it which should cascade the same on its references + lastSceneIndex.Reset(); +} + +void FilteringSceneIndicesChainManager::updateFilteringSceneIndicesChain(const std::string& rendererDisplayNames) +{ + /* rendererDisplayName is a string containing either FvpViewportAPITokens->allRenderers meaning this should apply to all renderers + * or it contains one or more renderers display names such as ("GL, Arnold") and in this case we must update + * only the viewports filtering scene indices chain which are using this renderer. + */ + + ViewportInformationAndSceneIndicesPerViewportDataVector& allViewportInformationAndSceneIndicesPerViewport = + ViewportInformationAndSceneIndicesPerViewportDataManager::Get().GetAllViewportInfoAndData(); + + for (auto& viewportInformationAndSceneIndicesPerViewportData : allViewportInformationAndSceneIndicesPerViewport){ + + //Check the renderer name + const std::string& rendererDisplayName = viewportInformationAndSceneIndicesPerViewportData.GetViewportInformation()._rendererName; + if ( (FvpViewportAPITokens->allRenderers != rendererDisplayNames) && (! rendererDisplayName.empty()) ){ + //Filtering per renderer is applied + if (std::string::npos == rendererDisplayNames.find(rendererDisplayName)){ + continue; //Ignore this filtering scene indices chain since the renderer is different + } + } + + const auto& renderIndexProxy = viewportInformationAndSceneIndicesPerViewportData.GetRenderIndexProxy(); + destroyFilteringSceneIndicesChain(viewportInformationAndSceneIndicesPerViewportData); + createFilteringSceneIndicesChain(viewportInformationAndSceneIndicesPerViewportData); + const auto& lastSceneIndex = viewportInformationAndSceneIndicesPerViewportData.GetLastFilteringSceneIndex(); + TF_AXIOM(lastSceneIndex && renderIndexProxy && renderIndexProxy->GetRenderIndex()); + renderIndexProxy->GetRenderIndex()->InsertSceneIndex(lastSceneIndex, SdfPath::AbsoluteRootPath()); + } +} + +void FilteringSceneIndicesChainManager::_AppendFilteringSceneIndicesChain( ViewportInformationAndSceneIndicesPerViewportData& viewportInformationAndSceneIndicesPerViewportData, + const HdSceneIndexBaseRefPtr& inputScene) +{ + TF_AXIOM(inputScene); + + HdContainerDataSourceHandle _inputArgs = nullptr;//Possibility to send custom data for scene index registration + + const std::string& rendererDisplayName = viewportInformationAndSceneIndicesPerViewportData.GetViewportInformation()._rendererName; + + HdSceneIndexBaseRefPtr& lastSceneIndex = viewportInformationAndSceneIndicesPerViewportData.GetLastFilteringSceneIndex(); + //Set the merging scene index as the last element to use this scene index as the input scene index of filtering scene indices + lastSceneIndex = inputScene; + + //Call our Hydra viewport API mechanism for custom filtering scene index clients + const auto& viewportFilteringSceneIndicesData = FilteringSceneIndexInterfaceImp::get().getSceneFilteringSceneIndicesData(); + for (const auto& filteringSceneIndexData : viewportFilteringSceneIndicesData) { + auto client = filteringSceneIndexData->getClient(); + const std::string& rendererNames = client->getRendererNames(); + //Filter by render delegate name + if ( (FvpViewportAPITokens->allRenderers != rendererNames) && rendererNames.find(rendererDisplayName) == std::string::npos){ + //Ignore that client info, it is not targeted for this renderer + continue; + } + + const bool isVisible = filteringSceneIndexData->getVisible(); + if (! isVisible){ + continue; //We should not append not visible filtering scene indices + } + + auto tempAppendedSceneIndex = client->appendSceneIndex(lastSceneIndex, _inputArgs); + if ((lastSceneIndex != tempAppendedSceneIndex)){ + //A new scene index was appended, it can also be a chain of scene indices but we need only the last element + lastSceneIndex = tempAppendedSceneIndex; + } + } +} + +void FilteringSceneIndicesChainManager::setEnabled(bool enable) +{ + if (_enabled != enable){ + _enabled = enable; + } + + //Update all viewports + updateFilteringSceneIndicesChain(FvpViewportAPITokens->allRenderers); +} + +}//End of namespace FVP_NS_DEF \ No newline at end of file diff --git a/lib/flowViewport/API/perViewportSceneIndicesData/fvpFilteringSceneIndicesChainManager.h b/lib/flowViewport/API/perViewportSceneIndicesData/fvpFilteringSceneIndicesChainManager.h new file mode 100644 index 0000000000..67ef165f60 --- /dev/null +++ b/lib/flowViewport/API/perViewportSceneIndicesData/fvpFilteringSceneIndicesChainManager.h @@ -0,0 +1,99 @@ +// +// Copyright 2023 Autodesk +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#ifndef FLOW_VIEWPORT_API_PERVIEWPORTSCENEINDICESDATA_FILTERING_SCENE_INDEX_CHAIN_MANAGER +#define FLOW_VIEWPORT_API_PERVIEWPORTSCENEINDICESDATA_FILTERING_SCENE_INDEX_CHAIN_MANAGER + +//Local headers +#include "flowViewport/api.h" +#include "flowViewport/sceneIndex/fvpRenderIndexProxyFwd.h" + +//Hydra headers +#include + +//Std headers +#include + +namespace FVP_NS_DEF { + +class RenderIndexProxy; //Predeclaration +class ViewportInformationAndSceneIndicesPerViewportData;//Predeclaration + +/**Is a singleton to manage the custom filtering scene indices chain which is appended after the merging scene index +* To access this class, use Fvp::FilteringSceneIndicesChainManager& filteringSceneIndicesChainManager = Fvp::FilteringSceneIndicesChainManager::get(); +*/ +class FVP_API FilteringSceneIndicesChainManager +{ +public: + /// Destructor + ~FilteringSceneIndicesChainManager(); + + ///Singleton accessor + static FilteringSceneIndicesChainManager& get(); + + /** + * @brief Create the filtering scene indices chain for this viewport. + * @param[in] viewportInformationAndSceneIndicesPerViewportData is the ViewportInformationAndSceneIndicesPerViewportData from the hydra viewport. + * @param[in] inputFilteringSceneIndex is the input scene index for your filtering scene index. + * @return the latest scene index from the custom filtering scene indices chain + */ + PXR_NS::HdSceneIndexBaseRefPtr createFilteringSceneIndicesChain(ViewportInformationAndSceneIndicesPerViewportData& viewportInformationAndSceneIndicesPerViewportData, + const PXR_NS::HdSceneIndexBaseRefPtr& inputFilteringSceneIndex = nullptr); + + /** + * @brief Removes from the render index the last element of the filtering scene indices chain for this viewport and delete the whole chain + * @param[in] viewportInformationAndSceneIndicesPerViewportData is the ViewportInformationAndSceneIndicesPerViewportData from the hydra viewport. + */ + void destroyFilteringSceneIndicesChain(ViewportInformationAndSceneIndicesPerViewportData& viewportInformationAndSceneIndicesPerViewportData); + + /** + * @brief Update the whole filtering scene indices chains. + * + * Update the whole chain by destroying it then create it again (use case is : a new FilteringSceneIndexClient was registered / unregistered + * so we must re-create the filtering scene indices chain with this change. + * We update only the viewports whose renderer display name is in rendererDisplayName. + * + * @param[in] rendererDisplayNames is a string containing either nothing ("") meaning this should apply to all renderers + * or it contains one or more renderers display names such as ("GL, Arnold") and in this case we must update + * only the viewports filtering scene indices chain which are using this renderer. + */ + void updateFilteringSceneIndicesChain(const std::string& rendererDisplayNames); + + // For debugging purpose : enable/disable the filtering scene indices chain as a global switch. + void setEnabled(bool enabled); + bool getEnabled()const {return _enabled;} + +private: + /** + * @brief Create the filtering scene indices chain for this viewport. + * @param[in] viewportInformationAndSceneIndicesPerViewportData is the ViewportInformationAndSceneIndicesPerViewportData from the hydra viewport. + * @param[in] inputFilteringSceneIndex is the input scene index for your filtering scene index. + */ + void _AppendFilteringSceneIndicesChain( ViewportInformationAndSceneIndicesPerViewportData& viewportInformationAndSceneIndicesPerViewportData, + const PXR_NS::HdSceneIndexBaseRefPtr& inputScene); + + /// Private constructor + FilteringSceneIndicesChainManager() = default; + + ///Enable/Disable the Filtering scene indices chain for debugging purpose + bool _enabled {true}; +}; + + +}//End of namespace FVP_NS_DEF + +#endif //FLOW_VIEWPORT_API_PERVIEWPORTSCENEINDICESDATA_FILTERING_SCENE_INDEX_CHAIN_MANAGER + diff --git a/lib/flowViewport/API/perViewportSceneIndicesData/fvpViewportAPITokens.cpp b/lib/flowViewport/API/perViewportSceneIndicesData/fvpViewportAPITokens.cpp new file mode 100644 index 0000000000..db6f06668f --- /dev/null +++ b/lib/flowViewport/API/perViewportSceneIndicesData/fvpViewportAPITokens.cpp @@ -0,0 +1,24 @@ +// Copyright 2023 Autodesk +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#include "flowViewport/API/fvpViewportAPITokens.h" + +// *** TODO / FIXME *** Figure out how to put tokens into non-Pixar namespace. + +PXR_NAMESPACE_OPEN_SCOPE + +TF_DEFINE_PUBLIC_TOKENS(FvpViewportAPITokens, FVP_VIEWPORT_API_TOKENS); + +PXR_NAMESPACE_CLOSE_SCOPE diff --git a/lib/flowViewport/API/perViewportSceneIndicesData/fvpViewportInformationAndSceneIndicesPerViewportData.cpp b/lib/flowViewport/API/perViewportSceneIndicesData/fvpViewportInformationAndSceneIndicesPerViewportData.cpp index 97fc9f261f..f02d04b32d 100644 --- a/lib/flowViewport/API/perViewportSceneIndicesData/fvpViewportInformationAndSceneIndicesPerViewportData.cpp +++ b/lib/flowViewport/API/perViewportSceneIndicesData/fvpViewportInformationAndSceneIndicesPerViewportData.cpp @@ -19,6 +19,7 @@ #include "flowViewport/API/interfacesImp/fvpInformationInterfaceImp.h" #include "flowViewport/sceneIndex/fvpRenderIndexProxy.h" #include "flowViewport/API/interfacesImp/fvpDataProducerSceneIndexInterfaceImp.h" +#include "flowViewport/API/perViewportSceneIndicesData/fvpFilteringSceneIndicesChainManager.h" //Hydra headers #include @@ -39,6 +40,8 @@ ViewportInformationAndSceneIndicesPerViewportData::ViewportInformationAndSceneIn ViewportInformationAndSceneIndicesPerViewportData::~ViewportInformationAndSceneIndicesPerViewportData() { DataProducerSceneIndexInterfaceImp::get().removeAllViewportDataProducerSceneIndices(*this); + //Remove custom filtering scene indices chain + FilteringSceneIndicesChainManager::get().destroyFilteringSceneIndicesChain(*this); } void ViewportInformationAndSceneIndicesPerViewportData::RemoveViewportDataProducerSceneIndex(const PXR_NS::HdSceneIndexBaseRefPtr& customDataProducerSceneIndex) @@ -71,7 +74,7 @@ void ViewportInformationAndSceneIndicesPerViewportData::_AddAllDataProducerScene } //Add all data producer scene index to the merging scene index through the render index proxy - for (auto& dataProducerSceneIndexData : _dataProducerSceneIndicesData){ + for (const auto& dataProducerSceneIndexData : _dataProducerSceneIndicesData){ // Add the data producer scene index to the merging scene index if (dataProducerSceneIndexData && dataProducerSceneIndexData->GetDataProducerLastSceneIndexChain()) { _renderIndexProxy->InsertSceneIndex(dataProducerSceneIndexData->GetDataProducerLastSceneIndexChain(), diff --git a/lib/flowViewport/API/perViewportSceneIndicesData/fvpViewportInformationAndSceneIndicesPerViewportData.h b/lib/flowViewport/API/perViewportSceneIndicesData/fvpViewportInformationAndSceneIndicesPerViewportData.h index 44bf9a56c0..fd56d79d64 100644 --- a/lib/flowViewport/API/perViewportSceneIndicesData/fvpViewportInformationAndSceneIndicesPerViewportData.h +++ b/lib/flowViewport/API/perViewportSceneIndicesData/fvpViewportInformationAndSceneIndicesPerViewportData.h @@ -37,8 +37,8 @@ class ViewportInformationAndSceneIndicesPerViewportData ~ViewportInformationAndSceneIndicesPerViewportData(); const InformationInterface::ViewportInformation& GetViewportInformation()const { return _viewportInformation;} - const PXR_NS::HdSceneIndexBaseRefPtr& GetLastFilteringSceneIndexOfTheChain() const {return _lastFilteringSceneIndexOfTheChain;} - void SetRenderIndexProxy(const Fvp::RenderIndexProxyPtr& renderIndexProxy); + PXR_NS::HdSceneIndexBaseRefPtr& GetLastFilteringSceneIndex() {return _lastFilteringSceneIndex;} + const PXR_NS::HdSceneIndexBaseRefPtr& GetLastFilteringSceneIndex() const {return _lastFilteringSceneIndex;} const Fvp::RenderIndexProxyPtr GetRenderIndexProxy() const {return _renderIndexProxy;} void SetInputSceneIndex(const PXR_NS::HdSceneIndexBaseRefPtr& inputSceneIndex) {_inputSceneIndex = inputSceneIndex;} const PXR_NS::HdSceneIndexBaseRefPtr& GetInputSceneIndex() const {return _inputSceneIndex;} @@ -46,9 +46,14 @@ class ViewportInformationAndSceneIndicesPerViewportData std::set& GetDataProducerSceneIndicesData() {return _dataProducerSceneIndicesData;} void RemoveViewportDataProducerSceneIndex(const PXR_NS::HdSceneIndexBaseRefPtr& customDataProducerSceneIndex); - //Needed by std::set - bool operator < (const ViewportInformationAndSceneIndicesPerViewportData& other)const{ - return _viewportInformation < other._viewportInformation; //Is for std::set. + //Needed by std::vector + ViewportInformationAndSceneIndicesPerViewportData& operator = (const ViewportInformationAndSceneIndicesPerViewportData& other){ + _viewportInformation = other._viewportInformation; + _dataProducerSceneIndicesData = other._dataProducerSceneIndicesData; + _inputSceneIndex = other._inputSceneIndex; + _lastFilteringSceneIndex = other._lastFilteringSceneIndex; + _renderIndexProxy = other._renderIndexProxy; + return *this; } private: @@ -62,7 +67,7 @@ class ViewportInformationAndSceneIndicesPerViewportData PXR_NS::HdSceneIndexBaseRefPtr _inputSceneIndex {nullptr}; /// The last scene index of the custom filtering scene indices chain for this viewport - PXR_NS::HdSceneIndexBaseRefPtr _lastFilteringSceneIndexOfTheChain {nullptr}; + PXR_NS::HdSceneIndexBaseRefPtr _lastFilteringSceneIndex {nullptr}; ///Is a render index proxy per viewport to avoid accessing directly the render index Fvp::RenderIndexProxyPtr _renderIndexProxy {nullptr}; @@ -71,7 +76,7 @@ class ViewportInformationAndSceneIndicesPerViewportData void _AddAllDataProducerSceneIndexToMergingSCeneIndex(); }; -using ViewportInformationAndSceneIndicesPerViewportDataSet = std::set; +using ViewportInformationAndSceneIndicesPerViewportDataVector = std::vector; } //End of namespace FVP_NS_DEF diff --git a/lib/flowViewport/API/perViewportSceneIndicesData/fvpViewportInformationAndSceneIndicesPerViewportDataManager.cpp b/lib/flowViewport/API/perViewportSceneIndicesData/fvpViewportInformationAndSceneIndicesPerViewportDataManager.cpp index 2784f809e2..9393c23fde 100644 --- a/lib/flowViewport/API/perViewportSceneIndicesData/fvpViewportInformationAndSceneIndicesPerViewportDataManager.cpp +++ b/lib/flowViewport/API/perViewportSceneIndicesData/fvpViewportInformationAndSceneIndicesPerViewportDataManager.cpp @@ -19,16 +19,17 @@ #include "flowViewport/API/interfacesImp/fvpDataProducerSceneIndexInterfaceImp.h" #include "flowViewport/API/interfacesImp/fvpInformationInterfaceImp.h" #include "flowViewport/sceneIndex/fvpRenderIndexProxy.h" +#include "flowViewport/API/perViewportSceneIndicesData/fvpFilteringSceneIndicesChainManager.h" //Hydra headers #include -//STL Headers +//Std Headers #include namespace { - std::mutex viewportInformationAndSceneIndicesPerViewportDataSet_mutex; + std::mutex viewportInformationAndSceneIndicesPerViewportData_mutex; std::set dummyEmptyArray; } @@ -43,11 +44,16 @@ ViewportInformationAndSceneIndicesPerViewportDataManager& ViewportInformationAnd } //A new Hydra viewport was created -void ViewportInformationAndSceneIndicesPerViewportDataManager::AddViewportInformation(const InformationInterface::ViewportInformation& viewportInfo, const Fvp::RenderIndexProxyPtr& renderIndexProxy) +void ViewportInformationAndSceneIndicesPerViewportDataManager::AddViewportInformation(const InformationInterface::ViewportInformation& viewportInfo, const Fvp::RenderIndexProxyPtr& renderIndexProxy, + const HdSceneIndexBaseRefPtr& inputSceneIndexForCustomFiltering) { + TF_AXIOM(renderIndexProxy && inputSceneIndexForCustomFiltering); + + ViewportInformationAndSceneIndicesPerViewportData* newElement = nullptr; + //Add it in our array if it is not already inside { - std::lock_guard lock(viewportInformationAndSceneIndicesPerViewportDataSet_mutex); + std::lock_guard lock(viewportInformationAndSceneIndicesPerViewportData_mutex); const auto& viewportId = viewportInfo._viewportId; auto findResult = std::find_if(_viewportsInformationAndSceneIndicesPerViewportData.begin(), _viewportsInformationAndSceneIndicesPerViewportData.end(), @@ -56,7 +62,8 @@ void ViewportInformationAndSceneIndicesPerViewportDataManager::AddViewportInform return;//It is already inside our array } - _viewportsInformationAndSceneIndicesPerViewportData.insert(ViewportInformationAndSceneIndicesPerViewportData(viewportInfo, renderIndexProxy)); + ViewportInformationAndSceneIndicesPerViewportData temp(viewportInfo, renderIndexProxy); + newElement = &(_viewportsInformationAndSceneIndicesPerViewportData.emplace_back(temp)); } //Call this to let the data producer scene indices that apply to all viewports to be added to this new viewport as well @@ -64,11 +71,21 @@ void ViewportInformationAndSceneIndicesPerViewportDataManager::AddViewportInform //Let the registered clients know a new viewport has been added InformationInterfaceImp::Get().SceneIndexAdded(viewportInfo); + + //Add the custom filtering scene indices to the merging scene index + TF_AXIOM(newElement); + const HdSceneIndexBaseRefPtr lastFilteringSceneIndex = FilteringSceneIndicesChainManager::get().createFilteringSceneIndicesChain(*newElement, + inputSceneIndexForCustomFiltering); + + //Insert the last filtering scene index into the render index + auto renderIndex = renderIndexProxy->GetRenderIndex(); + TF_AXIOM(renderIndex); + renderIndex->InsertSceneIndex(lastFilteringSceneIndex, SdfPath::AbsoluteRootPath()); } void ViewportInformationAndSceneIndicesPerViewportDataManager::RemoveViewportInformation(const std::string& modelPanel) { - std::lock_guard lock(viewportInformationAndSceneIndicesPerViewportDataSet_mutex); + std::lock_guard lock(viewportInformationAndSceneIndicesPerViewportData_mutex); auto findResult = std::find_if(_viewportsInformationAndSceneIndicesPerViewportData.begin(), _viewportsInformationAndSceneIndicesPerViewportData.end(), [&modelPanel](const ViewportInformationAndSceneIndicesPerViewportData& other) { return other.GetViewportInformation()._viewportId == modelPanel;}); @@ -81,7 +98,7 @@ void ViewportInformationAndSceneIndicesPerViewportDataManager::RemoveViewportInf if(renderIndexProxy){ //Destroy the custom filtering scene indices chain auto renderIndex = renderIndexProxy->GetRenderIndex(); - const auto& filteringSceneIndex = findResult->GetLastFilteringSceneIndexOfTheChain(); + const auto& filteringSceneIndex = findResult->GetLastFilteringSceneIndex(); if (renderIndex && filteringSceneIndex){ renderIndex->RemoveSceneIndex(filteringSceneIndex);//Remove the whole chain from the render index } @@ -93,7 +110,7 @@ void ViewportInformationAndSceneIndicesPerViewportDataManager::RemoveViewportInf const ViewportInformationAndSceneIndicesPerViewportData* ViewportInformationAndSceneIndicesPerViewportDataManager::GetViewportInfoAndDataFromViewportId(const std::string& viewportId)const { - std::lock_guard lock(viewportInformationAndSceneIndicesPerViewportDataSet_mutex); + std::lock_guard lock(viewportInformationAndSceneIndicesPerViewportData_mutex); auto findResult = std::find_if(_viewportsInformationAndSceneIndicesPerViewportData.cbegin(), _viewportsInformationAndSceneIndicesPerViewportData.cend(), [&viewportId](const ViewportInformationAndSceneIndicesPerViewportData& other) { return other.GetViewportInformation()._viewportId == viewportId;}); @@ -107,9 +124,9 @@ const ViewportInformationAndSceneIndicesPerViewportData* ViewportInformationAndS ViewportInformationAndSceneIndicesPerViewportData* ViewportInformationAndSceneIndicesPerViewportDataManager::GetViewportInfoAndDataFromViewportId(const std::string& viewportId) { - std::lock_guard lock(viewportInformationAndSceneIndicesPerViewportDataSet_mutex); + std::lock_guard lock(viewportInformationAndSceneIndicesPerViewportData_mutex); - ViewportInformationAndSceneIndicesPerViewportDataSet::iterator findResult = std::find_if(_viewportsInformationAndSceneIndicesPerViewportData.begin(), _viewportsInformationAndSceneIndicesPerViewportData.end(), + ViewportInformationAndSceneIndicesPerViewportDataVector::iterator findResult = std::find_if(_viewportsInformationAndSceneIndicesPerViewportData.begin(), _viewportsInformationAndSceneIndicesPerViewportData.end(), [&viewportId](const ViewportInformationAndSceneIndicesPerViewportData& other) { return other.GetViewportInformation()._viewportId == viewportId;}); if (findResult != _viewportsInformationAndSceneIndicesPerViewportData.end()){ ViewportInformationAndSceneIndicesPerViewportData& data = const_cast(*findResult); @@ -122,7 +139,7 @@ ViewportInformationAndSceneIndicesPerViewportData* ViewportInformationAndSceneIn const std::set& ViewportInformationAndSceneIndicesPerViewportDataManager::GetDataProducerSceneIndicesDataFromViewportId(const std::string& viewportId)const { - std::lock_guard lock(viewportInformationAndSceneIndicesPerViewportDataSet_mutex); + std::lock_guard lock(viewportInformationAndSceneIndicesPerViewportData_mutex); for (const auto& viewportInformationAndSceneIndicesPerViewportData : _viewportsInformationAndSceneIndicesPerViewportData){ const auto& viewportIdFromContainer = viewportInformationAndSceneIndicesPerViewportData.GetViewportInformation()._viewportId; @@ -136,7 +153,7 @@ ViewportInformationAndSceneIndicesPerViewportDataManager::GetDataProducerSceneIn bool ViewportInformationAndSceneIndicesPerViewportDataManager::ModelPanelIsAlreadyRegistered(const std::string& modelPanel)const { - std::lock_guard lock(viewportInformationAndSceneIndicesPerViewportDataSet_mutex); + std::lock_guard lock(viewportInformationAndSceneIndicesPerViewportData_mutex); auto findResult = std::find_if(_viewportsInformationAndSceneIndicesPerViewportData.cbegin(), _viewportsInformationAndSceneIndicesPerViewportData.cend(), [&modelPanel](const ViewportInformationAndSceneIndicesPerViewportData& other) { return other.GetViewportInformation()._viewportId == modelPanel;}); @@ -147,7 +164,7 @@ bool ViewportInformationAndSceneIndicesPerViewportDataManager::ModelPanelIsAlrea void ViewportInformationAndSceneIndicesPerViewportDataManager::RemoveAllViewportsInformation() { //Block for the lifetime of the lock - std::lock_guard lock(viewportInformationAndSceneIndicesPerViewportDataSet_mutex); + std::lock_guard lock(viewportInformationAndSceneIndicesPerViewportData_mutex); for(auto& viewportInfoAndData :_viewportsInformationAndSceneIndicesPerViewportData){ @@ -158,7 +175,7 @@ void ViewportInformationAndSceneIndicesPerViewportDataManager::RemoveAllViewport if(renderIndexProxy){ //Destroy the custom filtering scene indices chain auto renderIndex = renderIndexProxy->GetRenderIndex(); - const auto& filteringSceneIndex = viewportInfoAndData.GetLastFilteringSceneIndexOfTheChain(); + const auto& filteringSceneIndex = viewportInfoAndData.GetLastFilteringSceneIndex(); if (renderIndex && filteringSceneIndex){ renderIndex->RemoveSceneIndex(filteringSceneIndex);//Remove the whole chain from the render index } diff --git a/lib/flowViewport/API/perViewportSceneIndicesData/fvpViewportInformationAndSceneIndicesPerViewportDataManager.h b/lib/flowViewport/API/perViewportSceneIndicesData/fvpViewportInformationAndSceneIndicesPerViewportDataManager.h index 3ba0f6467e..139bb84844 100644 --- a/lib/flowViewport/API/perViewportSceneIndicesData/fvpViewportInformationAndSceneIndicesPerViewportDataManager.h +++ b/lib/flowViewport/API/perViewportSceneIndicesData/fvpViewportInformationAndSceneIndicesPerViewportDataManager.h @@ -39,14 +39,15 @@ class FVP_API ViewportInformationAndSceneIndicesPerViewportDataManager /// Manager accessor static ViewportInformationAndSceneIndicesPerViewportDataManager& Get(); - ///A new Hydra viewport was created - void AddViewportInformation(const InformationInterface::ViewportInformation& viewportInfo, const Fvp::RenderIndexProxyPtr& renderIndexProxy); + //A new Hydra viewport was created, we need inputSceneIndexForCustomFiltering to be used as an input scene index for custom filtering scene indices + void AddViewportInformation(const InformationInterface::ViewportInformation& viewportInfo, const Fvp::RenderIndexProxyPtr& renderIndexProxy, + const PXR_NS::HdSceneIndexBaseRefPtr& inputSceneIndexForCustomFiltering); - ///A Hydra viewport was deleted + //A Hydra viewport was deleted void RemoveViewportInformation(const std::string& modelPanel); - const ViewportInformationAndSceneIndicesPerViewportDataSet& GetAllViewportInfoAndData() const {return _viewportsInformationAndSceneIndicesPerViewportData;} - ViewportInformationAndSceneIndicesPerViewportDataSet& GetAllViewportInfoAndData() {return _viewportsInformationAndSceneIndicesPerViewportData;} + const ViewportInformationAndSceneIndicesPerViewportDataVector& GetAllViewportInfoAndData() const {return _viewportsInformationAndSceneIndicesPerViewportData;} + ViewportInformationAndSceneIndicesPerViewportDataVector& GetAllViewportInfoAndData() {return _viewportsInformationAndSceneIndicesPerViewportData;} const ViewportInformationAndSceneIndicesPerViewportData* GetViewportInfoAndDataFromViewportId(const std::string& viewportId)const; ViewportInformationAndSceneIndicesPerViewportData* GetViewportInfoAndDataFromViewportId(const std::string& viewportId); @@ -58,7 +59,7 @@ class FVP_API ViewportInformationAndSceneIndicesPerViewportDataManager private: ///Hydra viewport information - ViewportInformationAndSceneIndicesPerViewportDataSet _viewportsInformationAndSceneIndicesPerViewportData; + ViewportInformationAndSceneIndicesPerViewportDataVector _viewportsInformationAndSceneIndicesPerViewportData; ViewportInformationAndSceneIndicesPerViewportDataManager() = default; }; diff --git a/lib/flowViewport/API/samples/CMakeLists.txt b/lib/flowViewport/API/samples/CMakeLists.txt index 2be4c6cedd..c57ecac5c1 100644 --- a/lib/flowViewport/API/samples/CMakeLists.txt +++ b/lib/flowViewport/API/samples/CMakeLists.txt @@ -6,12 +6,16 @@ target_sources(${TARGET_NAME} fvpSelectionClientExample.cpp fvpInformationClientExample.cpp fvpDataProducerSceneIndexExample.cpp + fvpFilteringSceneIndexExample.cpp + fvpFilteringSceneIndexClientExample.cpp ) set(HEADERS fvpSelectionClientExample.h fvpInformationClientExample.h fvpDataProducerSceneIndexExample.h + fvpFilteringSceneIndexExample.h + fvpFilteringSceneIndexClientExample.h ) # ----------------------------------------------------------------------------- diff --git a/lib/flowViewport/API/samples/fvpDataProducerSceneIndexExample.cpp b/lib/flowViewport/API/samples/fvpDataProducerSceneIndexExample.cpp index 713187f229..ea9d8c7f05 100644 --- a/lib/flowViewport/API/samples/fvpDataProducerSceneIndexExample.cpp +++ b/lib/flowViewport/API/samples/fvpDataProducerSceneIndexExample.cpp @@ -534,7 +534,7 @@ HdRetainedSceneIndex::AddedPrimEntry DataProducerSceneIndexExample::_CreateCubeP void DataProducerSceneIndexExample::addDataProducerSceneIndex() { if (!_dataProducerSceneIndexAdded && _hydraInterface){ - const bool res = _hydraInterface->addDataProducerSceneIndex(_retainedSceneIndex, _containerNode, DataProducerSceneIndexInterface::allViewports, DataProducerSceneIndexInterface::allRenderers, SdfPath::AbsoluteRootPath()); + const bool res = _hydraInterface->addDataProducerSceneIndex(_retainedSceneIndex, _containerNode, PXR_NS::FvpViewportAPITokens->allViewports, PXR_NS::FvpViewportAPITokens->allRenderers, SdfPath::AbsoluteRootPath()); if (false == res){ TF_CODING_ERROR("_hydraInterface->addDataProducerSceneIndex returned false !"); } @@ -545,7 +545,7 @@ void DataProducerSceneIndexExample::addDataProducerSceneIndex() void DataProducerSceneIndexExample::removeDataProducerSceneIndex() { if (_dataProducerSceneIndexAdded && _hydraInterface){ - _hydraInterface->removeViewportDataProducerSceneIndex(_retainedSceneIndex, DataProducerSceneIndexInterface::allViewports); + _hydraInterface->removeViewportDataProducerSceneIndex(_retainedSceneIndex, PXR_NS::FvpViewportAPITokens->allViewports); _dataProducerSceneIndexAdded = false; } } diff --git a/lib/flowViewport/API/samples/fvpFilteringSceneIndexClientExample.cpp b/lib/flowViewport/API/samples/fvpFilteringSceneIndexClientExample.cpp new file mode 100644 index 0000000000..e1e667e73f --- /dev/null +++ b/lib/flowViewport/API/samples/fvpFilteringSceneIndexClientExample.cpp @@ -0,0 +1,43 @@ +// +// Copyright 2023 Autodesk +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +//Local headers +#include "fvpFilteringSceneIndexClientExample.h" + +PXR_NAMESPACE_USING_DIRECTIVE + +namespace FVP_NS_DEF { + +FilteringSceneIndexClientExample::FilteringSceneIndexClientExample(const std::string& displayName, const Category category, const std::string& rendererNames, void* dccNode): + FilteringSceneIndexClient(displayName, category, rendererNames, dccNode) +{ +} + +//Callback to be able to append a new scene index or scene index chain to this Hydra viewport scene index +HdSceneIndexBaseRefPtr FilteringSceneIndexClientExample::appendSceneIndex(const HdSceneIndexBaseRefPtr& inputSceneIndex, const HdContainerDataSourceHandle& inputArgs) +{ + if (inputSceneIndex){ + //Add a filtering scene index, this will hide some prims matching some criteria. + auto filteringSceneIndex = PXR_NS::FVP_NS_DEF::FilteringSceneIndexExample::New(inputSceneIndex); + + //return the new appended scene index, if you don't want to append a scene index, just return _hydraViewportInputSceneIndex + return filteringSceneIndex; + } + + return inputSceneIndex; +} + +} //End of namespace FVP_NS_DEF \ No newline at end of file diff --git a/lib/flowViewport/API/samples/fvpFilteringSceneIndexClientExample.h b/lib/flowViewport/API/samples/fvpFilteringSceneIndexClientExample.h new file mode 100644 index 0000000000..5f336658cf --- /dev/null +++ b/lib/flowViewport/API/samples/fvpFilteringSceneIndexClientExample.h @@ -0,0 +1,86 @@ +// +// Copyright 2023 Autodesk +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef FLOW_VIEWPORT_EXAMPLES_FILTERING_SCENE_INDEX_CLIENT_EXAMPLE_H +#define FLOW_VIEWPORT_EXAMPLES_FILTERING_SCENE_INDEX_CLIENT_EXAMPLE_H + +//Local headers +#include "flowViewport/api.h" +#include "flowViewport/API/fvpFilteringSceneIndexClient.h" +#include "flowViewport/API/fvpFilteringSceneIndexInterface.h" +#include "flowViewport/API/samples/fvpFilteringSceneIndexExample.h" + +namespace FVP_NS_DEF { + +/** This class is an implementation of FilteringSceneIndexClient which is an example on how to filter Hydra primitives from the scene into a Hydra viewport. +* It will use the scene index filter from the class FilteringSceneIndexExample. +* +* Usage of this class is : +* +* Call FilteringSceneIndexInterface::registerFilteringSceneIndexClient with this instance with for example : +* +* const std::shared_ptr hydraViewportFilteringSceneIndexClient = std::make_shared_ptr("FilteringSceneIndexClientExample", +* Fvp::FilteringSceneIndexClient::Category::kSceneFiltering, +* FvpViewportAPITokens->allRenderers, //We could set only Storm by using "GL" or only Arnold by using "Arnold" or both with "GL, Arnold" +* nullptr);//No node associated, you could still do it later though. +* //Register a filtering scene index client +* Fvp::FilteringSceneIndexInterface& filteringSceneIndexInterface = Fvp::FilteringSceneIndexInterface::get(); +* //Register this filtering scene index client, so it can append custom filtering scene indices to Hydra viewport scene indices +* const bool bResult = filteringSceneIndexInterface.registerFilteringSceneIndexClient(hydraViewportFilteringSceneIndexClient); +* +* The callback FilteringSceneIndexClientExample::appendSceneIndex will be called when a new viewport is created to append your filtering scene index. +* +* If you want to unregister your client, please use : +* Fvp::FilteringSceneIndexInterface& filteringSceneIndexInterface = Fvp::FilteringSceneIndexInterface::get(); +* filteringSceneIndexInterface.unregisterFilteringSceneIndexClient(hydraViewportFilteringSceneIndexClient); +*/ + +class FVP_API FilteringSceneIndexClientExample : public FilteringSceneIndexClient +{ +public: + /// Constructor, please see below for the meaning of the parameters + FilteringSceneIndexClientExample(const std::string& displayName, const Category category, const std::string& rendererNames, void* dccNode); + /// Destructor + ~FilteringSceneIndexClientExample() override = default; + + ///Is called by the DCC's node to set its node pointer, used later in the hydra viewport API + void setDccNode(void* node){_dccNode = node;} + + //From FilteringSceneIndexClient + + /** + * @brief Callback function to append a scene index. + * + * This callback function gets called for you to append a scene index to a Hydra viewport scene index, like a filtering scene index. + * A typical case is when a new Hydra viewport is created, after some internal managment of this scene index, we call this function so you can append one scene index + * or a chain of scene indices and return the last element of the chain. + * The returned value of this function is the last custom scene index of a a chain that you want to append to this scene index, + * or just return the input scene index passed if you don't want to append any scene index. + * + * @param[in] inputSceneIndex is a HdSceneIndexBaseRefPtr which was created by our Hydra viewport plugin. This could be the Hydra viewport scene index or it could be some appended + * scene index, as a chain of scene indices is appended to the Hydra viewport scene index if several filtering scene index clients are registered. + * So don't assume it's the Hydra viewport scene index. + * @param[in] inputArgs is a container data source handle to deal with the possibility to send custom data from our Hydra viewport plugin for the creation of your scene index. + * This parameter is currently not used by the Hydra viewport plugin but is left for possible future use. + * + * @return If you don't want to append a scene index, just return _inputSceneIndex. + * If you want to append a scene index or a scene indices chain, you should return the last scene index of the scene indices chain to append. + */ + PXR_NS::HdSceneIndexBaseRefPtr appendSceneIndex(const PXR_NS::HdSceneIndexBaseRefPtr& inputSceneIndex, const PXR_NS::HdContainerDataSourceHandle& inputArgs)override; +}; + +}//end of namespace FVP_NS_DEF + +#endif //FLOW_VIEWPORT_EXAMPLES_FILTERING_SCENE_INDEX_CLIENT_EXAMPLE_H diff --git a/lib/flowViewport/API/samples/fvpFilteringSceneIndexExample.cpp b/lib/flowViewport/API/samples/fvpFilteringSceneIndexExample.cpp new file mode 100644 index 0000000000..ef8cced189 --- /dev/null +++ b/lib/flowViewport/API/samples/fvpFilteringSceneIndexExample.cpp @@ -0,0 +1,85 @@ +// +// Copyright 2023 Autodesk +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +//Local headers +#include "fvpFilteringSceneIndexExample.h" + +//USD/Hydra headers +#include +#include +#include + +PXR_NAMESPACE_OPEN_SCOPE + +namespace +{ + //As an example, we use a filtering scene index to filter mesh primitives which have more than 10 000 vertices. + bool IsFiltered(const HdSceneIndexPrim& sceneIndexPrim) + { + static bool _hideCameras = false; + static bool _hideSimpleLights = false; + + if (sceneIndexPrim.dataSource){ + + if ((sceneIndexPrim.primType == HdPrimTypeTokens->mesh) || (sceneIndexPrim.primType == HdPrimTypeTokens->basisCurves) ){ + // Retrieve points from source mesh + if (HdSampledDataSourceHandle pointsDs = HdPrimvarsSchema::GetFromParent(sceneIndexPrim.dataSource).GetPrimvar(HdPrimvarsSchemaTokens->points).GetPrimvarValue()) + { + VtValue v = pointsDs->GetValue(0.0f); + if (v.IsHolding>()) { + const VtArray& points = v.Get>(); + const size_t numPoints = points.size(); + if (numPoints > 10000){ + //Hide the prims that have more than 10 000 vertices + return true; + } + } + } + } + + else + if (sceneIndexPrim.primType == HdPrimTypeTokens->camera){ + return _hideCameras; + }else + if (sceneIndexPrim.primType == HdPrimTypeTokens->simpleLight){ + return _hideSimpleLights; + } + } + + return false; + } +} + +namespace FVP_NS_DEF { + +//This is the function where we filter prims +HdSceneIndexPrim FilteringSceneIndexExample::GetPrim(const SdfPath& primPath) const +{ + if (_GetInputSceneIndex()){ + const HdSceneIndexPrim prim = _GetInputSceneIndex()->GetPrim(primPath); + + const bool isThisPrimFiltered = IsFiltered(prim); + if ( ! isThisPrimFiltered){ + return prim;//return only non filtered prims + } + } + + return HdSceneIndexPrim(); +} + +}//end of namespace FVP_NS_DEF + +PXR_NAMESPACE_CLOSE_SCOPE \ No newline at end of file diff --git a/lib/flowViewport/API/samples/fvpFilteringSceneIndexExample.h b/lib/flowViewport/API/samples/fvpFilteringSceneIndexExample.h new file mode 100644 index 0000000000..e5c34292c7 --- /dev/null +++ b/lib/flowViewport/API/samples/fvpFilteringSceneIndexExample.h @@ -0,0 +1,91 @@ +// +// Copyright 2023 Autodesk +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef FLOW_VIEWPORT_EXAMPLES_FILTERING_SCENE_INDEX_EXAMPLE_H +#define FLOW_VIEWPORT_EXAMPLES_FILTERING_SCENE_INDEX_EXAMPLE_H + +//Local headers +#include "flowViewport/api.h" + +//Hydra headers +#include +#include + + +/** This clas is an implementation of a HdSingleInputFilteringSceneIndexBase which is a filtering scene index. +* In this example of filtering scene index we will hide the mesh primitives which have more than 10 000 vertices. +*/ + +//The Pixar's namespace needs to be at the highest namespace level for TF_DECLARE_WEAK_AND_REF_PTRS to work. +PXR_NAMESPACE_OPEN_SCOPE + +namespace FVP_NS_DEF { + +class FilteringSceneIndexExample; +TF_DECLARE_WEAK_AND_REF_PTRS(FilteringSceneIndexExample); + +class FilteringSceneIndexExample : public HdSingleInputFilteringSceneIndexBase +{ +public: + using ParentClass = HdSingleInputFilteringSceneIndexBase; + + static FilteringSceneIndexExampleRefPtr New(const HdSceneIndexBaseRefPtr& inputSceneIndex){ + return TfCreateRefPtr(new FilteringSceneIndexExample(inputSceneIndex)); + } + + // From HdSceneIndexBase + HdSceneIndexPrim GetPrim(const SdfPath& primPath) const override;//Is the useful function where we do filtering + + SdfPathVector GetChildPrimPaths(const SdfPath& primPath) const override{//We leave this function with no filtering for simplicity + if (_GetInputSceneIndex()){ + return _GetInputSceneIndex()->GetChildPrimPaths(primPath); + } + + return {}; + } + + ~FilteringSceneIndexExample() override = default; + +protected: + FilteringSceneIndexExample(const HdSceneIndexBaseRefPtr& inputSceneIndex) : ParentClass(inputSceneIndex) {} + + void _PrimsAdded( + const HdSceneIndexBase& sender, + const HdSceneIndexObserver::AddedPrimEntries& entries) override final + { + _SendPrimsAdded(entries); + } + + void _PrimsRemoved( + const HdSceneIndexBase& sender, + const HdSceneIndexObserver::RemovedPrimEntries& entries) override + { + _SendPrimsRemoved(entries); + } + + void _PrimsDirtied( + const HdSceneIndexBase& sender, + const HdSceneIndexObserver::DirtiedPrimEntries& entries) override + { + _SendPrimsDirtied(entries); + } +}; + +}//end of namespace FVP_NS_DEF + +PXR_NAMESPACE_CLOSE_SCOPE + +#endif //FLOW_VIEWPORT_EXAMPLES_FILTERING_SCENE_INDEX_EXAMPLE_H + diff --git a/lib/flowViewport/API/samples/fvpInformationClientExample.cpp b/lib/flowViewport/API/samples/fvpInformationClientExample.cpp index 89cbd7dd7f..b2b113143f 100644 --- a/lib/flowViewport/API/samples/fvpInformationClientExample.cpp +++ b/lib/flowViewport/API/samples/fvpInformationClientExample.cpp @@ -25,13 +25,13 @@ InformationClientExample::~InformationClientExample() { } -//Callback to be able to act when a Hydra viewport scene index was added, typical use case is an hydra viewport was created. +//Callback to be able to act when a Hydra viewport scene index was added, typical use case is a hydra viewport was created. void InformationClientExample::SceneIndexAdded(const InformationInterface::ViewportInformation& viewportInformation) { } -//Callback to be able to act when a Hydra viewport scene index was removed, typical use case is an hydra viewport was removed. +//Callback to be able to act when a Hydra viewport scene index was removed, typical use case is a hydra viewport was removed. void InformationClientExample::SceneIndexRemoved(const InformationInterface::ViewportInformation& viewportInformation) { } diff --git a/lib/flowViewport/sceneIndex/fvpRenderIndexProxyFwd.h b/lib/flowViewport/sceneIndex/fvpRenderIndexProxyFwd.h index 14b84f8e57..46b5fe44ff 100644 --- a/lib/flowViewport/sceneIndex/fvpRenderIndexProxyFwd.h +++ b/lib/flowViewport/sceneIndex/fvpRenderIndexProxyFwd.h @@ -16,7 +16,7 @@ #define FVP_RENDER_INDEX_PROXY_FWD_H #include "flowViewport/api.h" - +#include namespace FVP_NS_DEF { diff --git a/lib/mayaHydra/flowViewportAPIExamples/flowViewportAPIMayaLocator/flowViewportAPIMayaLocator.cpp b/lib/mayaHydra/flowViewportAPIExamples/flowViewportAPIMayaLocator/flowViewportAPIMayaLocator.cpp index 765b0ff3cc..7fda154274 100644 --- a/lib/mayaHydra/flowViewportAPIExamples/flowViewportAPIMayaLocator/flowViewportAPIMayaLocator.cpp +++ b/lib/mayaHydra/flowViewportAPIExamples/flowViewportAPIMayaLocator/flowViewportAPIMayaLocator.cpp @@ -15,11 +15,13 @@ // //Flow viewport headers +#include #include #include #include #include #include +#include //Maya hydra headers #include @@ -89,6 +91,8 @@ class FlowViewportAPIMayaLocator : public MPxLocatorNode Fvp::DataProducerSceneIndexExample _hydraViewportDataProducerSceneIndexExample; protected: + /// _hydraViewportFilteringSceneIndexClientExample is the filtering scene index example for a Hydra viewport scene index. + std::shared_ptr _hydraViewportFilteringSceneIndexClientExample; /// _hydraViewportInformationClient is the viewport information example for a Hydra viewport. std::shared_ptr _hydraViewportInformationClient; ///To be used in hydra viewport API to pass the Maya node's MObject for setting callbacks for filtering and data producer scene indices @@ -341,6 +345,14 @@ FlowViewportAPIMayaLocator::FlowViewportAPIMayaLocator() //Add a callback after a load scene _cbAfterOpenId = MSceneMessage::addCallback(MSceneMessage::kAfterOpen, afterOpenCallback, ((void*)this)) ; + + //Create a Filtering scene index client + _hydraViewportFilteringSceneIndexClientExample = std::make_shared( + "FilteringSceneIndexClientExample", + Fvp::FilteringSceneIndexClient::Category::kSceneFiltering, + FvpViewportAPITokens->allRenderers, //We could set only Storm by using "GL" or only Arnold by using "Arnold" or both with "GL, Arnold" + nullptr);//DCC node will be filled later + } //This is called only when our node is destroyed and the undo queue flushed. @@ -364,6 +376,10 @@ FlowViewportAPIMayaLocator::~FlowViewportAPIMayaLocator() //The DataProducerSceneIndexExample in its destructor removes itself by calling DataProducerSceneIndexExample::RemoveDataProducerSceneIndex() + //Unregister filtering scene index client + Fvp::FilteringSceneIndexInterface& filteringSceneIndexInterface = Fvp::FilteringSceneIndexInterface::get(); + filteringSceneIndexInterface.unregisterFilteringSceneIndexClient(_hydraViewportFilteringSceneIndexClientExample); + //Unregister viewport information client Fvp::InformationInterface& informationInterface = Fvp::InformationInterface::Get(); informationInterface.UnregisterInformationClient(_hydraViewportInformationClient); @@ -418,13 +434,25 @@ void FlowViewportAPIMayaLocator::SetupFlowViewportInterfaces() } } - //Store the MObject* of the maya node in various classes //Set the maya node as a parent for this data producer scene index so that when the node is hidden/deleted/moved it gets applied to the prims produced GfMatrix4d nodeInvTransform; GetNodeInverseTransform(_thisMObject, nodeInvTransform); _hydraViewportDataProducerSceneIndexExample.setContainerNode(&_thisMObject); _hydraViewportDataProducerSceneIndexExample.setContainerNodeInverseTransform(nodeInvTransform); _hydraViewportDataProducerSceneIndexExample.addDataProducerSceneIndex(); + + //Register a filtering scene index client + Fvp::FilteringSceneIndexInterface& filteringSceneIndexInterface = Fvp::FilteringSceneIndexInterface::get(); + + + //Store the MObject* of the maya node in various classes + _hydraViewportFilteringSceneIndexClientExample->setDccNode(&_thisMObject); + + //Register this filtering scene index client, so it can append custom filtering scene indices to Hydra viewport scene indices + const bool bResult = filteringSceneIndexInterface.registerFilteringSceneIndexClient(_hydraViewportFilteringSceneIndexClientExample); + if(! bResult){ + perror("ERROR : filteringSceneIndexInterface.registerFilteringSceneIndexClient returned false"); + } } MStatus FlowViewportAPIMayaLocator::compute( const MPlug& plug, MDataBlock& dataBlock) diff --git a/lib/mayaHydra/hydraExtensions/sceneIndex/CMakeLists.txt b/lib/mayaHydra/hydraExtensions/sceneIndex/CMakeLists.txt index 61228f65ca..f9188eb888 100644 --- a/lib/mayaHydra/hydraExtensions/sceneIndex/CMakeLists.txt +++ b/lib/mayaHydra/hydraExtensions/sceneIndex/CMakeLists.txt @@ -14,6 +14,8 @@ target_sources(${TARGET_NAME} mayaHydraMayaDataProducerSceneIndexData.cpp mayaHydraMayaDataProducerSceneIndexDataConcreteFactory.cpp mayaHydraSceneIndexDataFactoriesSetup.cpp + mayaHydraMayaFilteringSceneIndexData.cpp + mayaHydraMayaFilteringSceneIndexDataConcreteFactory.cpp ) set(HEADERS @@ -28,6 +30,8 @@ set(HEADERS mayaHydraMayaDataProducerSceneIndexData.h mayaHydraMayaDataProducerSceneIndexDataConcreteFactory.h mayaHydraSceneIndexDataFactoriesSetup.h + mayaHydraMayaFilteringSceneIndexData.h + mayaHydraMayaFilteringSceneIndexDataConcreteFactory.h ) # ----------------------------------------------------------------------------- diff --git a/lib/mayaHydra/hydraExtensions/sceneIndex/mayaHydraMayaDataProducerSceneIndexData.cpp b/lib/mayaHydra/hydraExtensions/sceneIndex/mayaHydraMayaDataProducerSceneIndexData.cpp index 940af1d07b..44d84fadf0 100644 --- a/lib/mayaHydra/hydraExtensions/sceneIndex/mayaHydraMayaDataProducerSceneIndexData.cpp +++ b/lib/mayaHydra/hydraExtensions/sceneIndex/mayaHydraMayaDataProducerSceneIndexData.cpp @@ -61,7 +61,7 @@ namespace //this is how we identify which object we need to deal with. PXR_NS::MayaDataProducerSceneIndexData* mayaDataProducerSceneIndexData = (PXR_NS::MayaDataProducerSceneIndexData*)data; const MObjectHandle objHandle(obj); - if(mayaDataProducerSceneIndexData && mayaDataProducerSceneIndexData->_mObjHandle.isValid() && objHandle.hashCode() == mayaDataProducerSceneIndexData->_mObjHandle.hashCode()){ + if(mayaDataProducerSceneIndexData && mayaDataProducerSceneIndexData->getObjHandle().isValid() && objHandle.hashCode() == mayaDataProducerSceneIndexData->getObjHandle().hashCode()){ mayaDataProducerSceneIndexData->UpdateVisibilityFromDCCNode(true); } } @@ -73,7 +73,7 @@ namespace //this is how we identify which object we need to deal with. PXR_NS::MayaDataProducerSceneIndexData* mayaDataProducerSceneIndexData = (PXR_NS::MayaDataProducerSceneIndexData*)data; const MObjectHandle objHandle(obj); - if(mayaDataProducerSceneIndexData && mayaDataProducerSceneIndexData->_mObjHandle.isValid() && objHandle.hashCode() == mayaDataProducerSceneIndexData->_mObjHandle.hashCode()){ + if(mayaDataProducerSceneIndexData && mayaDataProducerSceneIndexData->getObjHandle().isValid() && objHandle.hashCode() == mayaDataProducerSceneIndexData->getObjHandle().hashCode()){ mayaDataProducerSceneIndexData->UpdateVisibilityFromDCCNode(false); } } diff --git a/lib/mayaHydra/hydraExtensions/sceneIndex/mayaHydraMayaDataProducerSceneIndexData.h b/lib/mayaHydra/hydraExtensions/sceneIndex/mayaHydraMayaDataProducerSceneIndexData.h index 217fca5e5c..801ec927ed 100644 --- a/lib/mayaHydra/hydraExtensions/sceneIndex/mayaHydraMayaDataProducerSceneIndexData.h +++ b/lib/mayaHydra/hydraExtensions/sceneIndex/mayaHydraMayaDataProducerSceneIndexData.h @@ -45,6 +45,18 @@ TF_DECLARE_WEAK_AND_REF_PTRS(MayaDataProducerSceneIndexData);//Be able to use Re ///Destructor ~MayaDataProducerSceneIndexData() override; + /// Get the MObject handle + const MObjectHandle& getObjHandle()const {return _mObjHandle;} + + /// Provide the node name from maya + std::string GetDCCNodeName() const override; + + ///Update transform from maya node + void UpdateTransformFromMayaNode(); + +private: + MayaDataProducerSceneIndexData(const FVP_NS_DEF::DataProducerSceneIndexDataBase::CreationParameters& params); + //The following members are optional and used only when a dccNode was passed in the constructor of DataProducerSceneIndexDataBase /// Is the MObjectHandle of the maya node shape, it may be invalid if no maya node MObject pointer was passed. @@ -55,15 +67,6 @@ TF_DECLARE_WEAK_AND_REF_PTRS(MayaDataProducerSceneIndexData);//Be able to use Re MCallbackIdArray _nodeMessageCallbackIds; /// Are the callbacks Ids set in maya to handle delete and deletion undo/redo MCallbackIdArray _dGMessageCallbackIds; - - /// Provide the node name from maya - std::string GetDCCNodeName() const override; - - ///Update transform from maya node - void UpdateTransformFromMayaNode(); - -private: - MayaDataProducerSceneIndexData(const FVP_NS_DEF::DataProducerSceneIndexDataBase::CreationParameters& params); }; PXR_NAMESPACE_CLOSE_SCOPE diff --git a/lib/mayaHydra/hydraExtensions/sceneIndex/mayaHydraMayaFilteringSceneIndexData.cpp b/lib/mayaHydra/hydraExtensions/sceneIndex/mayaHydraMayaFilteringSceneIndexData.cpp new file mode 100644 index 0000000000..6658494e85 --- /dev/null +++ b/lib/mayaHydra/hydraExtensions/sceneIndex/mayaHydraMayaFilteringSceneIndexData.cpp @@ -0,0 +1,127 @@ +// +// Copyright 2023 Autodesk +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + + +//Local headers +#include "mayaHydraMayaFilteringSceneIndexData.h" +#include "mayaHydraLib/mayaUtils.h" + +//flow viewport headers +#include + +//Maya headers +#include +#include +#include +#include +#include +#include + +namespace +{ + //Callback when an attribute of this a Maya node changes + void attributeChangedCallback(MNodeMessage::AttributeMessage msg, MPlug& plug, MPlug& otherPlug, void* data) + { + if( ! data){ + return; + } + + bool isVisible = false; + if (MayaHydra::IsAMayaVisibilityAttribute(plug, isVisible)){ + PXR_NS::MayaFilteringSceneIndexData* mayaFilteringSceneIndexData = (PXR_NS::MayaFilteringSceneIndexData*)data; + mayaFilteringSceneIndexData->updateVisibilityFromDCCNode(isVisible); + } + } + + //Callback when a node is added + void onDagNodeAdded(MObject& obj, void* data) + { + //Since when an object is recreated (such as doing an undo after a delete of the node), the MObject are different but their MObjectHandle::hasCode() are identical so + //this is how we identify which object we need to deal with. + PXR_NS::MayaFilteringSceneIndexData* mayaFilteringSceneIndexData = (PXR_NS::MayaFilteringSceneIndexData*)data; + const MObjectHandle objHandle(obj); + if(mayaFilteringSceneIndexData&& mayaFilteringSceneIndexData->getObjHandle().isValid() && objHandle.hashCode() == mayaFilteringSceneIndexData->getObjHandle().hashCode()){ + mayaFilteringSceneIndexData->updateVisibilityFromDCCNode(true); + } + } + + //Callback when a node is removed + void onDagNodeRemoved(MObject& obj, void* data) + { + //Since when an object is recreated (such as doing an undo after a delete of the node), the MObject are different but their MObjectHandle::hasCode() are identical so + //this is how we identify which object we need to deal with. + PXR_NS::MayaFilteringSceneIndexData* mayaFilteringSceneIndexData = (PXR_NS::MayaFilteringSceneIndexData*)data; + const MObjectHandle objHandle(obj); + if(mayaFilteringSceneIndexData&& mayaFilteringSceneIndexData->getObjHandle().isValid() && objHandle.hashCode() == mayaFilteringSceneIndexData->getObjHandle().hashCode()){ + mayaFilteringSceneIndexData->updateVisibilityFromDCCNode(false); + } + } +} + +PXR_NAMESPACE_USING_DIRECTIVE + +MayaFilteringSceneIndexData::MayaFilteringSceneIndexData(const std::shared_ptr<::FVP_NS_DEF::FilteringSceneIndexClient>& client) +: PXR_NS::FVP_NS_DEF::FilteringSceneIndexDataBase(client) +{ + //If a maya node is present in client.getDccNode(), add callbacks to handle node deleted/undo/redo and hide/unhide + void* dccNode = client->getDccNode(); + if (dccNode){ + MObject* mObj = reinterpret_cast(dccNode); + _mObjHandle = MObjectHandle(*mObj); + + MCallbackId cbId = MNodeMessage::addAttributeChangedCallback(*mObj, attributeChangedCallback, this); + if (cbId){ + _nodeMessageCallbackIds.append(cbId); + } + + const MDagPath mayaNodeDagPath = MDagPath::getAPathTo(*mObj); + + //Also monitor parent DAG node to be able to update the scene index if the visibility is modified + MDagPath parentDagPath = mayaNodeDagPath; + parentDagPath.pop(); + MObject parentObj = parentDagPath.node(); + cbId = 0; + cbId = MNodeMessage::addAttributeChangedCallback(parentObj, attributeChangedCallback, this); + if (cbId){ + _nodeMessageCallbackIds.append(cbId); + } + + //Get node type name to filter by node type for callbacks + MFnDependencyNode dep(*mObj); + const MString nodeTypeName = dep.typeName(); + + //Setup node added callback, filter by node type using nodeTypeName + cbId = 0; + cbId = MDGMessage::addNodeAddedCallback(onDagNodeAdded, nodeTypeName, this); + if (cbId) { + _dGMessageCallbackIds.append(cbId); + } + + //Setup node remove callback, filter by node type using nodeTypeName + cbId = 0; + cbId = MDGMessage::addNodeRemovedCallback(onDagNodeRemoved, nodeTypeName, this); + if (cbId) { + _dGMessageCallbackIds.append(cbId); + } + } +} + +MayaFilteringSceneIndexData::~MayaFilteringSceneIndexData() +{ + MNodeMessage::removeCallbacks (_nodeMessageCallbackIds); + MMessage::removeCallbacks (_dGMessageCallbackIds); +} + diff --git a/lib/mayaHydra/hydraExtensions/sceneIndex/mayaHydraMayaFilteringSceneIndexData.h b/lib/mayaHydra/hydraExtensions/sceneIndex/mayaHydraMayaFilteringSceneIndexData.h new file mode 100644 index 0000000000..0ecb3c06b9 --- /dev/null +++ b/lib/mayaHydra/hydraExtensions/sceneIndex/mayaHydraMayaFilteringSceneIndexData.h @@ -0,0 +1,66 @@ +// +// Copyright 2023 Autodesk +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef MAYAHYDRA_SCENE_INDEX_MAYA_FILTERING_SCENE_INDEX_DATA_H +#define MAYAHYDRA_SCENE_INDEX_MAYA_FILTERING_SCENE_INDEX_DATA_H + +//Flow Viewport headers +#include +#include +#include + +//Maya headers +#include +#include +#include + +PXR_NAMESPACE_OPEN_SCOPE + +class MayaFilteringSceneIndexData; +TF_DECLARE_WEAK_AND_REF_PTRS(MayaFilteringSceneIndexData);//Be able to use Ref counting pointers on MayaFilteringSceneIndexData + +/**This class is a Maya implementation of FilteringSceneIndexDataBase with specific variables and callbacks for Maya since FilteringSceneIndexDataBase is +* part of Flow viewport which is DCC agnostic. +*/ + class MayaFilteringSceneIndexData : public FVP_NS_DEF::FilteringSceneIndexDataBase +{ +public: + static TfRefPtr New(const std::shared_ptr<::FVP_NS_DEF::FilteringSceneIndexClient>& client) { + return TfCreateRefPtr(new MayaFilteringSceneIndexData(client)); + } + + ~MayaFilteringSceneIndexData() override; + + const MObjectHandle& getObjHandle()const {return _mObjHandle;} + +private: + MayaFilteringSceneIndexData(const std::shared_ptr<::FVP_NS_DEF::FilteringSceneIndexClient>& client); + + ///The following members are optional and used only when a dccNode was passed in the FilteringSceneIndexClient + + /// Is the MObjectHandle of the maya node shape, it may be invalid if no maya node MObject pointer was passed in the FilteringSceneIndexClient. + MObjectHandle _mObjHandle; + + /// Are the callbacks Ids set in maya to forward the changes done in maya on the dataProducer scene index. + MCallbackIdArray _nodeMessageCallbackIds; + + /// Are the callbacks Ids set in maya to handle delete and deletion undo/redo + MCallbackIdArray _dGMessageCallbackIds; +}; + +PXR_NAMESPACE_CLOSE_SCOPE + +#endif //MAYAHYDRA_SCENE_INDEX_MAYA_FILTERING_SCENE_INDEX_DATA_H + diff --git a/lib/mayaHydra/hydraExtensions/sceneIndex/mayaHydraMayaFilteringSceneIndexDataConcreteFactory.cpp b/lib/mayaHydra/hydraExtensions/sceneIndex/mayaHydraMayaFilteringSceneIndexDataConcreteFactory.cpp new file mode 100644 index 0000000000..226ab72914 --- /dev/null +++ b/lib/mayaHydra/hydraExtensions/sceneIndex/mayaHydraMayaFilteringSceneIndexDataConcreteFactory.cpp @@ -0,0 +1,31 @@ +// +// Copyright 2023 Autodesk +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +//Local headers +#include "mayaHydraMayaFilteringSceneIndexDataConcreteFactory.h" +#include "mayaHydraMayaFilteringSceneIndexData.h" + +PXR_NAMESPACE_USING_DIRECTIVE + +namespace MAYAHYDRA_NS_DEF { + +PXR_NS::FVP_NS_DEF::FilteringSceneIndexDataBaseRefPtr +MayaFilteringSceneIndexDataConcreteFactory::createFilteringSceneIndexDataBase(const std::shared_ptr<::FVP_NS_DEF::FilteringSceneIndexClient>& client) +{ + return MayaFilteringSceneIndexData::New(client); +} + +}//end of namespace MAYAHYDRA_NS_DEF \ No newline at end of file diff --git a/lib/mayaHydra/hydraExtensions/sceneIndex/mayaHydraMayaFilteringSceneIndexDataConcreteFactory.h b/lib/mayaHydra/hydraExtensions/sceneIndex/mayaHydraMayaFilteringSceneIndexDataConcreteFactory.h new file mode 100644 index 0000000000..bc3f93fad4 --- /dev/null +++ b/lib/mayaHydra/hydraExtensions/sceneIndex/mayaHydraMayaFilteringSceneIndexDataConcreteFactory.h @@ -0,0 +1,41 @@ +// +// Copyright 2023 Autodesk +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef MAYA_HYDRA_FILTERING_SCENE_INDEX_DATA_CONCRETE_FACTORY_H +#define MAYA_HYDRA_FILTERING_SCENE_INDEX_DATA_CONCRETE_FACTORY_H + +//MayaHydra headers +#include "mayaHydraLib/api.h" +#include "mayaHydraLib/mayaHydra.h" + +//Flow Viewport headers +#include "flowViewport/API/perViewportSceneIndicesData/fvpFilteringSceneIndexDataAbstractFactory.h" + +namespace MAYAHYDRA_NS_DEF { + +/** Since Flow viewport is DCC agnostic, the DCC will implement a concrete factory subclassing that class to provide specific DCC implementation of FilteringSceneIndexDataBaseRefPtr. +*/ +class MayaFilteringSceneIndexDataConcreteFactory : public Fvp::FilteringSceneIndexDataAbstractFactory +{ +public: + /// The DCC will create a subclass of FilteringSceneIndexDataBaseRefPtr with specific DCC variables that Flow viewport cannot manage since it's DCC agnostic + PXR_NS::FVP_NS_DEF::FilteringSceneIndexDataBaseRefPtr + createFilteringSceneIndexDataBase(const std::shared_ptr& client) override; +}; + +}//end of MAYAHYDRA_NS_DEF + +#endif //MAYA_HYDRA_FILTERING_SCENE_INDEX_DATA_CONCRETE_FACTORY_H + diff --git a/lib/mayaHydra/hydraExtensions/sceneIndex/mayaHydraSceneIndexDataFactoriesSetup.cpp b/lib/mayaHydra/hydraExtensions/sceneIndex/mayaHydraSceneIndexDataFactoriesSetup.cpp index 8c0b5efcf3..427c7f7cc0 100644 --- a/lib/mayaHydra/hydraExtensions/sceneIndex/mayaHydraSceneIndexDataFactoriesSetup.cpp +++ b/lib/mayaHydra/hydraExtensions/sceneIndex/mayaHydraSceneIndexDataFactoriesSetup.cpp @@ -22,14 +22,19 @@ //Local headers #include "mayaHydraSceneIndexDataFactoriesSetup.h" #include "mayaHydraMayaDataProducerSceneIndexDataConcreteFactory.h" +#include "mayaHydraMayaFilteringSceneIndexDataConcreteFactory.h" //Flow viewport headers #include +#include namespace MAYAHYDRA_NS_DEF{ SceneIndexDataFactoriesSetup::SceneIndexDataFactoriesSetup() { + static MayaFilteringSceneIndexDataConcreteFactory filteringFactory; + Fvp::FilteringSceneIndexInterfaceImp::get().setSceneIndexDataFactory(filteringFactory); + static MayaDataProducerSceneIndexDataConcreteFactory dataProducerFactory; Fvp::DataProducerSceneIndexInterfaceImp::get().setSceneIndexDataFactory(dataProducerFactory); } diff --git a/lib/mayaHydra/mayaPlugin/renderOverride.cpp b/lib/mayaHydra/mayaPlugin/renderOverride.cpp index 3426a55944..de4ec9cd53 100644 --- a/lib/mayaHydra/mayaPlugin/renderOverride.cpp +++ b/lib/mayaHydra/mayaPlugin/renderOverride.cpp @@ -600,7 +600,7 @@ MStatus MtohRenderOverride::Render( //Create a HydraViewportInformation const Fvp::InformationInterface::ViewportInformation hydraViewportInformation(std::string(panelName.asChar()), cameraName); - manager.AddViewportInformation(hydraViewportInformation, _renderIndexProxy); + manager.AddViewportInformation(hydraViewportInformation, _renderIndexProxy, _lastFilteringSceneIndexBeforeCustomFiltering); } } @@ -880,28 +880,26 @@ void MtohRenderOverride::_CreateSceneIndicesChainAfterMergingSceneIndex() //This function is where happens the ordering of filtering scene indices that are after the merging scene index TF_AXIOM(_renderIndexProxy); - HdSceneIndexBaseRefPtr lastSceneIndexOfTheChain = _renderIndexProxy->GetMergingSceneIndex(); + _lastFilteringSceneIndexBeforeCustomFiltering = _renderIndexProxy->GetMergingSceneIndex(); _selection = std::make_shared(); - _selectionSceneIndex = Fvp::SelectionSceneIndex::New(lastSceneIndexOfTheChain, _selection); + _selectionSceneIndex = Fvp::SelectionSceneIndex::New(_lastFilteringSceneIndexBeforeCustomFiltering , _selection); _selectionSceneIndex->SetDisplayName("Flow Viewport Selection Scene Index"); - lastSceneIndexOfTheChain = _selectionSceneIndex; + _lastFilteringSceneIndexBeforeCustomFiltering = _selectionSceneIndex; if (!_sceneIndexRegistry) { _sceneIndexRegistry.reset(new MayaHydraSceneIndexRegistry(_renderIndexProxy)); } - auto wfSi = TfDynamic_cast(Fvp::WireframeSelectionHighlightSceneIndex::New(_selectionSceneIndex, _selection)); + auto wfSi = TfDynamic_cast(Fvp::WireframeSelectionHighlightSceneIndex::New(_lastFilteringSceneIndexBeforeCustomFiltering, _selection)); wfSi->SetDisplayName("Flow Viewport Wireframe Selection Highlight Scene Index"); // At time of writing, wireframe selection highlighting of Maya native data // is done by Maya at render item creation time, so avoid double wireframe // selection highlighting. wfSi->addExcludedSceneRoot(_ID); - lastSceneIndexOfTheChain = wfSi; + _lastFilteringSceneIndexBeforeCustomFiltering = wfSi; - _renderIndex->InsertSceneIndex(lastSceneIndexOfTheChain, SdfPath::AbsoluteRootPath()); - // Set the initial selection onto the selection scene index. _selectionSceneIndex->ReplaceSelection(*Ufe::GlobalSelection::get()); } diff --git a/lib/mayaHydra/mayaPlugin/renderOverride.h b/lib/mayaHydra/mayaPlugin/renderOverride.h index 5d30e7ce24..a4fd9ab119 100644 --- a/lib/mayaHydra/mayaPlugin/renderOverride.h +++ b/lib/mayaHydra/mayaPlugin/renderOverride.h @@ -221,6 +221,7 @@ class MtohRenderOverride : public MHWRender::MRenderOverride HdxTaskController* _taskController = nullptr; HdPluginRenderDelegateUniqueHandle _renderDelegate = nullptr; Fvp::RenderIndexProxyPtr _renderIndexProxy{nullptr}; + HdSceneIndexBaseRefPtr _lastFilteringSceneIndexBeforeCustomFiltering {nullptr}; HdRenderIndex* _renderIndex = nullptr; Fvp::SelectionTrackerSharedPtr _fvpSelectionTracker; Fvp::SelectionSceneIndexRefPtr _selectionSceneIndex; diff --git a/test/lib/mayaUsd/render/mayaToHydra/CMakeLists.txt b/test/lib/mayaUsd/render/mayaToHydra/CMakeLists.txt index de30349a08..94f297ff34 100644 --- a/test/lib/mayaUsd/render/mayaToHydra/CMakeLists.txt +++ b/test/lib/mayaUsd/render/mayaToHydra/CMakeLists.txt @@ -24,6 +24,7 @@ set(TEST_SCRIPT_FILES cpp/testFlowViewportAPIViewportInformation.py cpp/testFlowViewportAPIAddPrims.py cpp/testUsdStageLayerMuting.py + cpp/testFlowViewportAPIFilterPrims.py ) # Test use of mesh adapter code for mesh support, using environment variable. diff --git a/test/lib/mayaUsd/render/mayaToHydra/FlowViewportAPITest/filter_NodeCreated.png b/test/lib/mayaUsd/render/mayaToHydra/FlowViewportAPITest/filter_NodeCreated.png new file mode 100644 index 0000000000..e0a000f100 Binary files /dev/null and b/test/lib/mayaUsd/render/mayaToHydra/FlowViewportAPITest/filter_NodeCreated.png differ diff --git a/test/lib/mayaUsd/render/mayaToHydra/FlowViewportAPITest/filter_NodeDeleted.png b/test/lib/mayaUsd/render/mayaToHydra/FlowViewportAPITest/filter_NodeDeleted.png new file mode 100644 index 0000000000..07b6793a30 Binary files /dev/null and b/test/lib/mayaUsd/render/mayaToHydra/FlowViewportAPITest/filter_NodeDeleted.png differ diff --git a/test/lib/mayaUsd/render/mayaToHydra/FlowViewportAPITest/filter_NodeDeletedRedo.png b/test/lib/mayaUsd/render/mayaToHydra/FlowViewportAPITest/filter_NodeDeletedRedo.png new file mode 100644 index 0000000000..07b6793a30 Binary files /dev/null and b/test/lib/mayaUsd/render/mayaToHydra/FlowViewportAPITest/filter_NodeDeletedRedo.png differ diff --git a/test/lib/mayaUsd/render/mayaToHydra/FlowViewportAPITest/filter_NodeDeletedUndo.png b/test/lib/mayaUsd/render/mayaToHydra/FlowViewportAPITest/filter_NodeDeletedUndo.png new file mode 100644 index 0000000000..d5a428242c Binary files /dev/null and b/test/lib/mayaUsd/render/mayaToHydra/FlowViewportAPITest/filter_NodeDeletedUndo.png differ diff --git a/test/lib/mayaUsd/render/mayaToHydra/FlowViewportAPITest/filter_NodeHidden.png b/test/lib/mayaUsd/render/mayaToHydra/FlowViewportAPITest/filter_NodeHidden.png new file mode 100644 index 0000000000..07b6793a30 Binary files /dev/null and b/test/lib/mayaUsd/render/mayaToHydra/FlowViewportAPITest/filter_NodeHidden.png differ diff --git a/test/lib/mayaUsd/render/mayaToHydra/FlowViewportAPITest/filter_NodeMoved.png b/test/lib/mayaUsd/render/mayaToHydra/FlowViewportAPITest/filter_NodeMoved.png new file mode 100644 index 0000000000..0a6ed866bd Binary files /dev/null and b/test/lib/mayaUsd/render/mayaToHydra/FlowViewportAPITest/filter_NodeMoved.png differ diff --git a/test/lib/mayaUsd/render/mayaToHydra/FlowViewportAPITest/filter_NodeUnhidden.png b/test/lib/mayaUsd/render/mayaToHydra/FlowViewportAPITest/filter_NodeUnhidden.png new file mode 100644 index 0000000000..d5a428242c Binary files /dev/null and b/test/lib/mayaUsd/render/mayaToHydra/FlowViewportAPITest/filter_NodeUnhidden.png differ diff --git a/test/lib/mayaUsd/render/mayaToHydra/FlowViewportAPITest/filter_SphereFiltered.png b/test/lib/mayaUsd/render/mayaToHydra/FlowViewportAPITest/filter_SphereFiltered.png new file mode 100644 index 0000000000..d5a428242c Binary files /dev/null and b/test/lib/mayaUsd/render/mayaToHydra/FlowViewportAPITest/filter_SphereFiltered.png differ diff --git a/test/lib/mayaUsd/render/mayaToHydra/FlowViewportAPITest/filter_SphereFilteredAgain.png b/test/lib/mayaUsd/render/mayaToHydra/FlowViewportAPITest/filter_SphereFilteredAgain.png new file mode 100644 index 0000000000..d5a428242c Binary files /dev/null and b/test/lib/mayaUsd/render/mayaToHydra/FlowViewportAPITest/filter_SphereFilteredAgain.png differ diff --git a/test/lib/mayaUsd/render/mayaToHydra/FlowViewportAPITest/filter_SphereUnFiltered.png b/test/lib/mayaUsd/render/mayaToHydra/FlowViewportAPITest/filter_SphereUnFiltered.png new file mode 100644 index 0000000000..5a5e990f77 Binary files /dev/null and b/test/lib/mayaUsd/render/mayaToHydra/FlowViewportAPITest/filter_SphereUnFiltered.png differ diff --git a/test/lib/mayaUsd/render/mayaToHydra/FlowViewportAPITest/filter_VP2AndThenBackToStorm.png b/test/lib/mayaUsd/render/mayaToHydra/FlowViewportAPITest/filter_VP2AndThenBackToStorm.png new file mode 100644 index 0000000000..d5a428242c Binary files /dev/null and b/test/lib/mayaUsd/render/mayaToHydra/FlowViewportAPITest/filter_VP2AndThenBackToStorm.png differ diff --git a/test/lib/mayaUsd/render/mayaToHydra/FlowViewportAPITest/multipleViewports_VP2AndThenBackToStorm_modPan2.png b/test/lib/mayaUsd/render/mayaToHydra/FlowViewportAPITest/multipleViewports_VP2AndThenBackToStorm_modPan2.png index 73e33dae93..d3875b5574 100644 Binary files a/test/lib/mayaUsd/render/mayaToHydra/FlowViewportAPITest/multipleViewports_VP2AndThenBackToStorm_modPan2.png and b/test/lib/mayaUsd/render/mayaToHydra/FlowViewportAPITest/multipleViewports_VP2AndThenBackToStorm_modPan2.png differ diff --git a/test/lib/mayaUsd/render/mayaToHydra/FlowViewportAPITest/multipleViewports_VP2AndThenBackToStorm_modPan4.png b/test/lib/mayaUsd/render/mayaToHydra/FlowViewportAPITest/multipleViewports_VP2AndThenBackToStorm_modPan4.png index 485e6e19c0..c7c5a9c29e 100644 Binary files a/test/lib/mayaUsd/render/mayaToHydra/FlowViewportAPITest/multipleViewports_VP2AndThenBackToStorm_modPan4.png and b/test/lib/mayaUsd/render/mayaToHydra/FlowViewportAPITest/multipleViewports_VP2AndThenBackToStorm_modPan4.png differ diff --git a/test/lib/mayaUsd/render/mayaToHydra/FlowViewportAPITest/multipleViewports_VP2_modPan2.png b/test/lib/mayaUsd/render/mayaToHydra/FlowViewportAPITest/multipleViewports_VP2_modPan2.png index 4856fd5bab..6459f82aba 100644 Binary files a/test/lib/mayaUsd/render/mayaToHydra/FlowViewportAPITest/multipleViewports_VP2_modPan2.png and b/test/lib/mayaUsd/render/mayaToHydra/FlowViewportAPITest/multipleViewports_VP2_modPan2.png differ diff --git a/test/lib/mayaUsd/render/mayaToHydra/FlowViewportAPITest/multipleViewports_VP2_modPan4.png b/test/lib/mayaUsd/render/mayaToHydra/FlowViewportAPITest/multipleViewports_VP2_modPan4.png index ac1d96cef3..68d0036926 100644 Binary files a/test/lib/mayaUsd/render/mayaToHydra/FlowViewportAPITest/multipleViewports_VP2_modPan4.png and b/test/lib/mayaUsd/render/mayaToHydra/FlowViewportAPITest/multipleViewports_VP2_modPan4.png differ diff --git a/test/lib/mayaUsd/render/mayaToHydra/cpp/CMakeLists.txt b/test/lib/mayaUsd/render/mayaToHydra/cpp/CMakeLists.txt index a2d1b2eb9d..d2dc3448ef 100644 --- a/test/lib/mayaUsd/render/mayaToHydra/cpp/CMakeLists.txt +++ b/test/lib/mayaUsd/render/mayaToHydra/cpp/CMakeLists.txt @@ -25,6 +25,7 @@ target_sources(${TARGET_NAME} testFlowViewportAPIAddPrims.cpp testUsdStageLayerMuting.cpp testMeshAdapterTransform.cpp + testFlowViewportAPIFilterPrims.cpp ) # ----------------------------------------------------------------------------- diff --git a/test/lib/mayaUsd/render/mayaToHydra/cpp/testFlowViewportAPIAddPrims.cpp b/test/lib/mayaUsd/render/mayaToHydra/cpp/testFlowViewportAPIAddPrims.cpp index efeb48ba9d..7dd9536dc7 100644 --- a/test/lib/mayaUsd/render/mayaToHydra/cpp/testFlowViewportAPIAddPrims.cpp +++ b/test/lib/mayaUsd/render/mayaToHydra/cpp/testFlowViewportAPIAddPrims.cpp @@ -92,26 +92,14 @@ TEST(FlowViewportAPI, addPrimitives) //Setup inspector for the first viewport scene index const SceneIndicesVector& sceneIndices = GetTerminalSceneIndices(); - ASSERT_GT(sceneIndices.size(), static_cast(0)); + ASSERT_GT(sceneIndices.size(), 0u); SceneIndexInspector inspector(sceneIndices.front()); // Retrieve the first cube primitive from its Sdfpath and check its visibility - FindPrimPredicate findFirstCubePrimPredicate - = [&firstCubePath](const HdSceneIndexBasePtr& sceneIndex, const SdfPath& primPath) -> bool { - const std::string primPathString = primPath.GetAsString(); - HdSceneIndexPrim prim = sceneIndex->GetPrim(primPath); - if (primPathString.find(firstCubePath) != std::string::npos) { - //Check if it is visible or not - auto visibilityHandle = HdVisibilitySchema::GetFromParent(prim.dataSource).GetVisibility(); - if (visibilityHandle){ - return visibilityHandle->GetTypedValue(0.0f); //return true if it is visible, false otherwise - } - } - return false; - }; - + const PrimNameVisibilityPredicate findFirstCubePrimPredicate(firstCubePath); + PrimEntriesVector foundPrims = inspector.FindPrims(findFirstCubePrimPredicate, 1); - ASSERT_EQ(foundPrims.size(), static_cast(1)); //The cube should be found + ASSERT_EQ(foundPrims.size(), 1u); //The cube should be found //Hide the shape node MFnDependencyNode depNode(parentSphereShapeMOject, &stat); @@ -121,13 +109,13 @@ TEST(FlowViewportAPI, addPrimitives) visibilityPlug.setBool(false); foundPrims = inspector.FindPrims(findFirstCubePrimPredicate, 1); - ASSERT_EQ(foundPrims.size(), static_cast(0));//The cube should not be found + ASSERT_EQ(foundPrims.size(), 0u);//The cube should not be found //Unhide the shape node visibilityPlug.setBool(true); foundPrims = inspector.FindPrims(findFirstCubePrimPredicate, 1); - ASSERT_EQ(foundPrims.size(), static_cast(1));//The cube should be found + ASSERT_EQ(foundPrims.size(), 1u);//The cube should be found hydraViewportDataProducerSceneIndexExample.removeDataProducerSceneIndex(); } diff --git a/test/lib/mayaUsd/render/mayaToHydra/cpp/testFlowViewportAPIFilterPrims.cpp b/test/lib/mayaUsd/render/mayaToHydra/cpp/testFlowViewportAPIFilterPrims.cpp new file mode 100644 index 0000000000..cfd69f6d6b --- /dev/null +++ b/test/lib/mayaUsd/render/mayaToHydra/cpp/testFlowViewportAPIFilterPrims.cpp @@ -0,0 +1,119 @@ +// +// Copyright 2023 Autodesk, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +//Local headers +#include "testUtils.h" + +//maya hydra +#include +#include + +//Flow viewport headers +#include +#include + +//maya headers +#include +#include +#include +#include + +//Hydra headers +#include + +//Google tests +#include + +PXR_NAMESPACE_USING_DIRECTIVE + +TEST(FlowViewportAPI, filterPrimitives) +{ + /* The python script testFlowViewportAPIFilterPrims.py associated with that file has created 1 cube and 2 spheres with : + * #Create a maya sphere named parentSphere + cmds.polyCube(name="parentCube", w=2, h=2, d=2) + cmds.polySphere(name="smallSphere") + cmds.polySphere(name="bigSphere", subdivisionsAxis=200, subdivisionsHeight= 200) + */ + static const MString parentName("parentCube"); + static const MString parentShapeName("parentCubeShape"); + static const MString smallSphereShapeName("smallSphereShape"); + static const MString bigSphereShapeName("bigSphereShape"); + + //Get the maya nodes which have been created by the python script matching this cpp file. + const MString names[] = {parentName, parentShapeName, smallSphereShapeName, bigSphereShapeName}; + const MStringArray nameArs (names, 4); + MObjectArray objArray; + objArray.setLength(4); + MStatus stat = MayaHydra::GetObjectsFromNodeNames(nameArs, objArray); + ASSERT_EQ(stat, MS::kSuccess); + + MObject parentMOject = objArray[0]; + ASSERT_FALSE(parentMOject.isNull()); + MObject parentShapeMOject = objArray[1]; + ASSERT_FALSE(parentShapeMOject.isNull()); + MObject smallSphereShapeMOject = objArray[2]; + ASSERT_FALSE(smallSphereShapeMOject.isNull()); + MObject bigSphereShapeMOject = objArray[3]; + ASSERT_FALSE(bigSphereShapeMOject.isNull()); + + //FilteringSceneIndexClientExample is an helper class to apply a filtering scene index into the viewport which hides objects with more than 10 000 vertices + //This is the case for the object named "bigSphere", it has more than 10 000 vertices. + const std::shared_ptr hydraViewportFilteringSceneIndexExample = std::make_shared + ("TestFilteringSceneIndex", + Fvp::FilteringSceneIndexClient::Category::kSceneFiltering, + FvpViewportAPITokens->allRenderers, + &parentShapeMOject //Set the cube as the parent of this filtering scene index + ); + //Filtering scene index interface + Fvp::FilteringSceneIndexInterface& filteringSceneIndexInterface = Fvp::FilteringSceneIndexInterface::get(); + + //Register it + const bool bRes = filteringSceneIndexInterface.registerFilteringSceneIndexClient(hydraViewportFilteringSceneIndexExample); + ASSERT_TRUE(bRes); + + //Check that there are primitives in the viewport terminal scene index + const SceneIndicesVector& sceneIndices = GetTerminalSceneIndices(); + ASSERT_GT(sceneIndices.size(), 0u); + SceneIndexInspector inspector(sceneIndices.front()); + + // Define both predicates for the small sphere prim and bug sphere in the list of primitives and return their visibility + const PrimNameVisibilityPredicate smallSpherePredicate(smallSphereShapeName.asChar()); + const PrimNameVisibilityPredicate bigSpherePredicate(bigSphereShapeName.asChar()); + + PrimEntriesVector foundPrims = inspector.FindPrims(smallSpherePredicate, 1); + ASSERT_EQ(foundPrims.size(), 1u); //The small sphere should be found and visible + + foundPrims = inspector.FindPrims(bigSpherePredicate, 1); + ASSERT_EQ(foundPrims.size(), 0u); //The big sphere should be filtered (not visible) + + //Hide the cube shape node which is the parent node of the filtering scene index, this should disable the filtering and make the big sphere visible. + MFnDependencyNode depNode(parentShapeMOject, &stat); + ASSERT_EQ(stat, MS::kSuccess); + MPlug visibilityPlug = depNode.findPlug("visibility"); + ASSERT_FALSE(visibilityPlug.isNull()); + visibilityPlug.setBool(false); + + foundPrims = inspector.FindPrims(bigSpherePredicate, 1); + ASSERT_EQ(foundPrims.size(), 1u);//The big sphere should be visible, as the filtering is disabled since the cube which is its parent node is hidden. + + //Unhide the cube shape node + visibilityPlug.setBool(true); + + foundPrims = inspector.FindPrims(bigSpherePredicate, 1); + ASSERT_EQ(foundPrims.size(), 0u);//The big sphere should not be visible, as filtering is applied again + + filteringSceneIndexInterface.unregisterFilteringSceneIndexClient(hydraViewportFilteringSceneIndexExample); +} diff --git a/test/lib/mayaUsd/render/mayaToHydra/cpp/testFlowViewportAPIFilterPrims.py b/test/lib/mayaUsd/render/mayaToHydra/cpp/testFlowViewportAPIFilterPrims.py new file mode 100644 index 0000000000..3a4f9ce76c --- /dev/null +++ b/test/lib/mayaUsd/render/mayaToHydra/cpp/testFlowViewportAPIFilterPrims.py @@ -0,0 +1,41 @@ +# +# Copyright 2023 Autodesk, Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +import maya.cmds as cmds +import fixturesUtils +import mtohUtils +from testUtils import PluginLoaded + +class TestFlowViewportAPIFilterPrims(mtohUtils.MayaHydraBaseTestCase): + # MayaHydraBaseTestCase.setUpClass requirement. + _file = __file__ + + def setupParentChildScene(self): + self.setHdStormRenderer() + #Create a maya sphere named parentSphere + cmds.polyCube(name="parentCube", w=2, h=2, d=2) + cmds.polySphere(name="smallSphere") + #Create a big sphere which has more than 10 000 vertices + cmds.polySphere(name="bigSphere", subdivisionsAxis=200, subdivisionsHeight= 200) + cmds.refresh() + + def test_FilterPrimitives(self): + self.setupParentChildScene() + with PluginLoaded('mayaHydraCppTests'): + cmds.mayaHydraCppTest(f="FlowViewportAPI.filterPrimitives") + +if __name__ == '__main__': + fixturesUtils.runTests(globals()) diff --git a/test/lib/mayaUsd/render/mayaToHydra/cpp/testMayaSceneFlattening.cpp b/test/lib/mayaUsd/render/mayaToHydra/cpp/testMayaSceneFlattening.cpp index 27a4711c5e..7c66d63d35 100644 --- a/test/lib/mayaUsd/render/mayaToHydra/cpp/testMayaSceneFlattening.cpp +++ b/test/lib/mayaUsd/render/mayaToHydra/cpp/testMayaSceneFlattening.cpp @@ -32,7 +32,7 @@ TEST(MayaSceneFlattening, childHasFlattenedTransform) { // Setup inspector for the first scene index const SceneIndicesVector& sceneIndices = GetTerminalSceneIndices(); - ASSERT_GT(sceneIndices.size(), static_cast(0)); + ASSERT_GT(sceneIndices.size(), 0u); SceneIndexInspector inspector(sceneIndices.front()); // Retrieve the child cube prim @@ -47,7 +47,7 @@ TEST(MayaSceneFlattening, childHasFlattenedTransform) return parentIsCube; }; PrimEntriesVector foundPrims = inspector.FindPrims(findCubePrimPredicate, 1); - ASSERT_EQ(foundPrims.size(), static_cast(1)); + ASSERT_EQ(foundPrims.size(), 1u); HdSceneIndexPrim cubePrim = foundPrims.front().prim; // Extract the Hydra xform matrix from the cube prim diff --git a/test/lib/mayaUsd/render/mayaToHydra/cpp/testMayaUsdUfeItems.cpp b/test/lib/mayaUsd/render/mayaToHydra/cpp/testMayaUsdUfeItems.cpp index 9cef3808fe..1b6a673ca4 100644 --- a/test/lib/mayaUsd/render/mayaToHydra/cpp/testMayaUsdUfeItems.cpp +++ b/test/lib/mayaUsd/render/mayaToHydra/cpp/testMayaUsdUfeItems.cpp @@ -38,10 +38,10 @@ TEST(MayaUsdUfeItems, skipUsdUfeLights) { // Setup inspector for the first scene index const SceneIndicesVector& sceneIndices = GetTerminalSceneIndices(); - ASSERT_GT(sceneIndices.size(), static_cast(0)); + ASSERT_GT(sceneIndices.size(), 0u); SceneIndexInspector inspector(sceneIndices.front()); // Find UFE lights PrimEntriesVector ufeLights = inspector.FindPrims(&IsUfeLight, 1); - EXPECT_EQ(ufeLights.size(), static_cast(0)); + EXPECT_EQ(ufeLights.size(), 0u); } diff --git a/test/lib/mayaUsd/render/mayaToHydra/cpp/testMergingSceneIndex.cpp b/test/lib/mayaUsd/render/mayaToHydra/cpp/testMergingSceneIndex.cpp index cea06271bf..1278463104 100644 --- a/test/lib/mayaUsd/render/mayaToHydra/cpp/testMergingSceneIndex.cpp +++ b/test/lib/mayaUsd/render/mayaToHydra/cpp/testMergingSceneIndex.cpp @@ -33,7 +33,7 @@ TEST(FlowViewport, mergingSceneIndex) { // The Flow Viewport custom merging scene index is in the scene index tree. const auto& sceneIndices = GetTerminalSceneIndices(); - ASSERT_GT(sceneIndices.size(), static_cast(0)); + ASSERT_GT(sceneIndices.size(), 0u); auto isFvpMergingSceneIndex = SceneIndexDisplayNamePred( "Flow Viewport Merging Scene Index"); diff --git a/test/lib/mayaUsd/render/mayaToHydra/cpp/testMeshAdapterTransform.cpp b/test/lib/mayaUsd/render/mayaToHydra/cpp/testMeshAdapterTransform.cpp index 82ce986afe..0e9e1a30ab 100644 --- a/test/lib/mayaUsd/render/mayaToHydra/cpp/testMeshAdapterTransform.cpp +++ b/test/lib/mayaUsd/render/mayaToHydra/cpp/testMeshAdapterTransform.cpp @@ -32,7 +32,7 @@ TEST(MeshAdapterTransform, testDirtying) { // Setup notifications accumulator for the first terminal scene index const SceneIndicesVector& sceneIndices = GetTerminalSceneIndices(); - ASSERT_GT(sceneIndices.size(), static_cast(0)); + ASSERT_GT(sceneIndices.size(), 0u); SceneIndexNotificationsAccumulator notifsAccumulator(sceneIndices.front()); // The test cube should still be selected from the Python driver diff --git a/test/lib/mayaUsd/render/mayaToHydra/cpp/testSelectionSceneIndex.cpp b/test/lib/mayaUsd/render/mayaToHydra/cpp/testSelectionSceneIndex.cpp index 8c9748cfa9..e3836d232b 100644 --- a/test/lib/mayaUsd/render/mayaToHydra/cpp/testSelectionSceneIndex.cpp +++ b/test/lib/mayaUsd/render/mayaToHydra/cpp/testSelectionSceneIndex.cpp @@ -37,7 +37,7 @@ TEST(FlowViewport, selectionSceneIndex) { // The Flow Viewport selection scene index is in the scene index tree. const auto& sceneIndices = GetTerminalSceneIndices(); - ASSERT_GT(sceneIndices.size(), static_cast(0)); + ASSERT_GT(sceneIndices.size(), 0u); auto isFvpSelectionSceneIndex = SceneIndexDisplayNamePred( "Flow Viewport Selection Scene Index"); diff --git a/test/lib/mayaUsd/render/mayaToHydra/cpp/testUtils.h b/test/lib/mayaUsd/render/mayaToHydra/cpp/testUtils.h index 915359f806..3c255c02ba 100644 --- a/test/lib/mayaUsd/render/mayaToHydra/cpp/testUtils.h +++ b/test/lib/mayaUsd/render/mayaToHydra/cpp/testUtils.h @@ -19,6 +19,7 @@ #include #include +#include #include #include @@ -166,6 +167,43 @@ class PrimNamePredicate const std::string _primName; }; +/** +* @brief PrimNameVisibilityPredicate is a Predicate to find a name in a primitive SdfPath and check its visibility attribute. This class is to be used as a FindPrimPredicate. +* It returns True if both conditions : +* 1) The predicate's prim name is found in one of the prims from the scene index (it only needs to be inside a path, not matching it exactly), +* 2) If 1) is filled, we check if the visibility attribute is set to true. +* This Predicate returns true only if both conditions are validated. Or false if one these conditions is not filled. +*/ +class PrimNameVisibilityPredicate +{ +public: + PrimNameVisibilityPredicate(const std::string primName) : _primName(primName) {} + + /** + * @brief Predicate to find a name in a primitive SdfPath and check its visibility attribute. This class is to be used as a FindPrimPredicate. + * + * @param[in] sceneIndex : scene index to use for checking the prims . + * @param[in] primPath : The prim path to test. + * + * @return True if the argument prim path's name has the predicate's prim name inside, and if the visibility attribute is set to true, false otherwise. + */ + bool operator()(const HdSceneIndexBasePtr& sceneIndex, const SdfPath& primPath) { + const std::string primPathString = primPath.GetAsString(); + HdSceneIndexPrim prim = sceneIndex->GetPrim(primPath); + if (primPathString.find(_primName) != std::string::npos) { + //Check if it is visible or not + auto visibilityHandle = HdVisibilitySchema::GetFromParent(prim.dataSource).GetVisibility(); + if (visibilityHandle){ + return visibilityHandle->GetTypedValue(0.0f); //return true if it is visible, false otherwise + } + } + return false; + } + +private: + const std::string _primName; +}; + class SceneIndexDisplayNamePred { const std::string _name; public: diff --git a/test/lib/mayaUsd/render/mayaToHydra/cpp/testWireframeSelectionHighlightSceneIndex.cpp b/test/lib/mayaUsd/render/mayaToHydra/cpp/testWireframeSelectionHighlightSceneIndex.cpp index 3b3b553413..cb418d68ae 100644 --- a/test/lib/mayaUsd/render/mayaToHydra/cpp/testWireframeSelectionHighlightSceneIndex.cpp +++ b/test/lib/mayaUsd/render/mayaToHydra/cpp/testWireframeSelectionHighlightSceneIndex.cpp @@ -94,7 +94,7 @@ TEST(FlowViewport, wireframeSelectionHighlightSceneIndex) // The Flow Viewport wireframe selection highlight scene index is in the // scene index tree. const auto& si = GetTerminalSceneIndices(); - ASSERT_GT(si.size(), static_cast(0)); + ASSERT_GT(si.size(), 0u); auto isFvpWireframeSelectionHighlightSceneIndex = SceneIndexDisplayNamePred( "Flow Viewport Wireframe Selection Highlight Scene Index"); diff --git a/test/lib/mayaUsd/render/mayaToHydra/testFlowViewportAPI.py b/test/lib/mayaUsd/render/mayaToHydra/testFlowViewportAPI.py index f8f24092bc..9cb2c3f1d0 100644 --- a/test/lib/mayaUsd/render/mayaToHydra/testFlowViewportAPI.py +++ b/test/lib/mayaUsd/render/mayaToHydra/testFlowViewportAPI.py @@ -76,22 +76,19 @@ def test_AddingPrimitives(self): cmds.showHidden(transformNode) self.assertSnapshotClose("add_NodeUnhidden.png", None, None) - #Delete the shape node + #Delete the shape node, this should hide the added prims as well cmds.delete(flowViewportNodeName) - self.assertSnapshotClose("add_NodeDeleted.png", None, None) - #Enable undo again - cmds.undoInfo(stateWithoutFlush=True) - - #Undo the delete, the node should be visible again + + #Undo the delete, the node should be visible again so do the added prims cmds.undo() self.assertSnapshotClose("add_NodeDeletedUndo.png", None, None) - #Redo the delete + #Redo the delete, the added prims should be hidden cmds.redo() self.assertSnapshotClose("add_NodeDeletedRedo.png", None, None) - #Undo the delete again, the node should be visible again + #Undo the delete again, the added prims should be visible cmds.undo() self.assertSnapshotClose("add_NodeDeletedUndoAgain.png", None, None) @@ -111,6 +108,84 @@ def test_AddingPrimitives(self): #Finish by a File New command cmds.file(new=True, force=True) + #Test filtering primitives + def test_FilteringPrimitives(self): + self.setupScene() + with PluginLoaded('flowViewportAPIMayaLocator'): + + #Create a maya sphere + sphereNode, sphereShape = cmds.polySphere() + cmds.refresh() + + #Create a FlowViewportAPIMayaLocator node which adds a dataProducerSceneIndex and a Filtering scene index + flowViewportNodeName = cmds.createNode("FlowViewportAPIMayaLocator") + self.assertFalse(flowViewportNodeName == None) + #When the node above is created, its compute method is not called automatically, so work around to trigger a call to compute + cmds.setAttr(flowViewportNodeName + '.dummyInput', 3)#setting this will set dirty the dummyOutput attribute + cmds.getAttr(flowViewportNodeName + '.dummyOutput')#getting this value will trigger a call to compute + cmds.refresh() + #Original images are located for example in maya-hydra\test\lib\mayaUsd\render\mayaToHydra\FlowViewportAPITest + self.assertSnapshotClose("filter_NodeCreated.png", None, None) + + #Move the transform node, the added prims (cube grid) should move as well + # Get the transform node of the FlowViewportAPIMayaLocator + transformNode = cmds.listRelatives(flowViewportNodeName, parent=True)[0] + self.assertFalse(transformNode == None) + #Select the transform node + cmds.select(transformNode) + # Move the selected node + cmds.move(15, 0, 0) + cmds.refresh() + self.assertSnapshotClose("filter_NodeMoved.png", None, None) + + #Change sphere attributes to add more vertices/polygons, our filtering hides a prim when its number of vertices is greater than 10 000. + cmds.setAttr(sphereShape + '.subdivisionsAxis', 200) + cmds.setAttr(sphereShape + '.subdivisionsHeight', 200) + cmds.refresh() + self.assertSnapshotClose("filter_SphereFiltered.png", None, None) + + #Decreasing the number of vertices of this sphere under 10 000 should make it visible again (not filtered) + cmds.setAttr(sphereShape + '.subdivisionsAxis', 30) + cmds.refresh() + self.assertSnapshotClose("filter_SphereUnFiltered.png", None, None) + + #Increasing again the number of vertices above 10 000 should make it filtered again (invisible) + cmds.setAttr(sphereShape + '.subdivisionsAxis', 200) + cmds.refresh() + self.assertSnapshotClose("filter_SphereFilteredAgain.png", None, None) + + #Hide the transform node, this should hide the FlowViewportAPIMayaLocator shape node and disable the filtering as well. + cmds.hide(transformNode) + self.assertSnapshotClose("filter_NodeHidden.png", None, None) + + #Unhide the transform node, this should unhide the FlowViewportAPIMayaLocator node and enable the filtering as well. + cmds.showHidden(transformNode) + self.assertSnapshotClose("filter_NodeUnhidden.png", None, None) + + #Delete the shape node, this should disable filtering + cmds.delete(flowViewportNodeName) + self.assertSnapshotClose("filter_NodeDeleted.png", None, None) + + #Undo the delete, the node should be visible again and filtering be enabled + cmds.undo() + self.assertSnapshotClose("filter_NodeDeletedUndo.png", None, None) + + #Redo the delete, filtering should be disabled + cmds.redo() + self.assertSnapshotClose("filter_NodeDeletedRedo.png", None, None) + + #Undo the delete so filtering is enabled again + cmds.undo() + + #Switch to VP2 + self.setViewport2Renderer() + #Switch back to Storm + self.setHdStormRenderer() + self.assertSnapshotClose("filter_VP2AndThenBackToStorm.png", None, None) + + #Finish by a File New command + cmds.file(new=True, force=True) + #Test Cube grids parameters def test_CubeGrid(self): self.setupScene() @@ -324,6 +399,23 @@ def test_MultipleViewports(self): cmds.setFocus ('modelPanel2') self.assertSnapshotClose("multipleViewports_viewPanel2.png", None, None) + #Change sphere attributes to add more vertices/polygons, our filtering removes a prim when its number of vertices is greater than 10 000. + cmds.setAttr(sphereShape + '.subdivisionsAxis', 200) + cmds.setAttr(sphereShape + '.subdivisionsHeight', 200) + cmds.refresh() + cmds.setFocus ('modelPanel4') + self.assertSnapshotClose("multipleViewports_sphereFiltered_viewPanel4.png", None, None) + cmds.setFocus ('modelPanel2') + self.assertSnapshotClose("multipleViewports_sphereFiltered_viewPanel2.png", None, None) + + #Remove filtering by decreasing the number of vertices + cmds.setAttr(sphereShape + '.subdivisionsAxis', 30) + cmds.refresh() + cmds.setFocus ('modelPanel4') + self.assertSnapshotClose("multipleViewports_sphereUnfiltered_viewPanel4.png", None, None) + cmds.setFocus ('modelPanel2') + self.assertSnapshotClose("multipleViewports_sphereUnfiltered_viewPanel2.png", None, None) + #Switch to VP2 cmds.setFocus ('modelPanel4') self.setViewport2Renderer()