/****************************************************************************** * Applies a modifier by appending it to the end of the node's modification * pipeline. ******************************************************************************/ void ObjectNode::applyModifier(Modifier* modifier) { if(!dataProvider()) throw Exception("Cannot insert modifier into a modification pipeline without a data source."); PipelineObject* pipelineObj = dynamic_object_cast<PipelineObject>(dataProvider()); if(!pipelineObj) { OORef<PipelineObject> p = new PipelineObject(dataset()); p->setSourceObject(dataProvider()); setDataProvider(p); pipelineObj = p; } pipelineObj->insertModifier(modifier, pipelineObj->modifierApplications().size()); }
/****************************************************************************** * Inserts the given modifier into the modification pipeline of the * selected scene nodes. ******************************************************************************/ void ModificationListModel::applyModifier(Modifier* modifier) { // Get the selected stack entry. The new modifier is inserted just behind it. ModificationListItem* currentItem = selectedItem(); // On the next list update, the new modifier should be selected. _nextToSelectObject = modifier; if(currentItem) { if(dynamic_object_cast<Modifier>(currentItem->object())) { for(ModifierApplication* modApp : currentItem->modifierApplications()) { PipelineObject* pipelineObj = modApp->pipelineObject(); OVITO_CHECK_OBJECT_POINTER(pipelineObj); pipelineObj->insertModifier(modifier, pipelineObj->modifierApplications().indexOf(modApp) + 1); } return; } else if(dynamic_object_cast<PipelineObject>(currentItem->object())) { PipelineObject* pipelineObj = static_object_cast<PipelineObject>(currentItem->object()); OVITO_CHECK_OBJECT_POINTER(pipelineObj); pipelineObj->insertModifier(modifier, 0); return; } else if(dynamic_object_cast<DataObject>(currentItem->object())) { if(PipelineObject* pipelineObj = hiddenPipelineObject()) { pipelineObj->insertModifier(modifier, 0); return; } } } // Apply modifier to each selected node. for(ObjectNode* objNode : selectedNodes()) { objNode->applyModifier(modifier); } }
/****************************************************************************** * Completely rebuilds the modifier list. ******************************************************************************/ void ModificationListModel::refreshList() { _needListUpdate = false; // Determine the currently selected object and // select it again after the list has been rebuilt (and it is still there). // If _currentObject is already non-NULL then the caller // has specified an object to be selected. if(_nextToSelectObject == nullptr) { ModificationListItem* item = selectedItem(); if(item) _nextToSelectObject = item->object(); } RefTarget* defaultObjectToSelect = nullptr; // Collect all selected ObjectNodes. // Also check if all selected object nodes reference the same data object. _selectedNodes.clear(); DataObject* cmnObject = nullptr; if(_datasetContainer.currentSet()) { for(SceneNode* node : _datasetContainer.currentSet()->selection()->nodes()) { if(ObjectNode* objNode = dynamic_object_cast<ObjectNode>(node)) { _selectedNodes.push_back(objNode); if(cmnObject == nullptr) cmnObject = objNode->dataProvider(); else if(cmnObject != objNode->dataProvider()) { cmnObject = nullptr; break; // The scene nodes are not compatible. } } } } QList<OORef<ModificationListItem>> items; QList<OORef<ModificationListItem>> hiddenItems; if(cmnObject) { // Create list items for display objects. for(ObjectNode* objNode : _selectedNodes.targets()) { for(DisplayObject* displayObj : objNode->displayObjects()) items.push_back(new ModificationListItem(displayObj)); } if(!items.empty()) items.push_front(new ModificationListItem(nullptr, false, tr("Display"))); // Walk up the pipeline. do { OVITO_CHECK_OBJECT_POINTER(cmnObject); // Create entries for the modifier applications if this is a PipelineObject. PipelineObject* modObj = dynamic_object_cast<PipelineObject>(cmnObject); if(modObj) { if(!modObj->modifierApplications().empty()) items.push_back(new ModificationListItem(nullptr, false, tr("Modifications"))); hiddenItems.push_back(new ModificationListItem(modObj)); for(int i = modObj->modifierApplications().size(); i--; ) { ModifierApplication* app = modObj->modifierApplications()[i]; ModificationListItem* item = new ModificationListItem(app->modifier()); item->setModifierApplications({1, app}); items.push_back(item); // Create list items for the modifier's editable sub-objects. for(int j = 0; j < app->modifier()->editableSubObjectCount(); j++) { RefTarget* subobject = app->modifier()->editableSubObject(j); if(subobject != NULL && subobject->isSubObjectEditable()) { items.push_back(new ModificationListItem(subobject, true)); } } } cmnObject = modObj->sourceObject(); } else { items.push_back(new ModificationListItem(nullptr, false, tr("Input"))); // Create an entry for the data object. items.push_back(new ModificationListItem(cmnObject)); if(defaultObjectToSelect == nullptr) defaultObjectToSelect = cmnObject; // Create list items for the object's editable sub-objects. for(int i = 0; i < cmnObject->editableSubObjectCount(); i++) { RefTarget* subobject = cmnObject->editableSubObject(i); if(subobject != NULL && subobject->isSubObjectEditable()) { items.push_back(new ModificationListItem(subobject, true)); } } break; } } while(cmnObject != nullptr); } int selIndex = -1; int selDefaultIndex = -1; for(int i = 0; i < items.size(); i++) { if(_nextToSelectObject && _nextToSelectObject == items[i]->object()) selIndex = i; if(defaultObjectToSelect && defaultObjectToSelect == items[i]->object()) selDefaultIndex = i; } if(selIndex == -1) selIndex = selDefaultIndex; setItems(items, hiddenItems); _nextToSelectObject = nullptr; // Select the proper item in the list box. if(!items.empty()) { if(selIndex == -1) { for(int index = 0; index < items.size(); index++) { if(items[index]->object()) { selIndex = index; break; } } } _selectionModel->select(index(selIndex), QItemSelectionModel::SelectCurrent | QItemSelectionModel::Clear); } else { Q_EMIT selectedItemChanged(); } }