示例#1
0
/******************************************************************************
* 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();
	}
}