void RotateSelected::visit(const scene::INodePtr& node) const { ITransformNodePtr transformNode = Node_getTransformNode(node); if (transformNode) { // Upcast the instance onto a Transformable ITransformablePtr transformable = Node_getTransformable(node); if (transformable) { // The object is not scaled or translated explicitly // A translation might occur due to the rotation around a pivot point transformable->setType(TRANSFORM_PRIMITIVE); transformable->setScale(c_scale_identity); transformable->setTranslation(c_translation_identity); // Pass the rotation quaternion and the world pivot, // unless we're rotating each object around their own center transformable->setRotation(_rotation, _freeObjectRotation ? transformable->getUntransformedOrigin() : _worldPivot, node->localToWorld()); } } }
void ModelExporter::processLight(const scene::INodePtr& node) { // Export lights as small polyhedron static const double EXTENTS = 8.0; std::vector<model::ModelPolygon> polys; Vertex3f up(0, 0, EXTENTS); Vertex3f down(0, 0, -EXTENTS); Vertex3f north(0, EXTENTS, 0); Vertex3f south(0, -EXTENTS, 0); Vertex3f east(EXTENTS, 0, 0); Vertex3f west(-EXTENTS, 0, 0); // Upper semi-diamond polys.push_back(createPolyCCW(up, south, east)); polys.push_back(createPolyCCW(up, east, north)); polys.push_back(createPolyCCW(up, north, west)); polys.push_back(createPolyCCW(up, west, south)); // Lower semi-diamond polys.push_back(createPolyCCW(down, south, west)); polys.push_back(createPolyCCW(down, west, north)); polys.push_back(createPolyCCW(down, north, east)); polys.push_back(createPolyCCW(down, east, south)); Matrix4 exportTransform = node->localToWorld().getPremultipliedBy(_centerTransform); _exporter->addPolygons("lights/default", polys, exportTransform); }
bool MapImporter::addPrimitiveToEntity(const scene::INodePtr& primitive, const scene::INodePtr& entity) { _nodes.insert(NodeMap::value_type( NodeIndexPair(_entityCount, _primitiveCount), primitive)); _primitiveCount++; if (_dialog && _dialogEventLimiter.readyForEvent()) { _dialog->setTextAndFraction( _dlgEntityText + "Primitive " + string::to_string(_primitiveCount), getProgressFraction() ); } if (Node_getEntity(entity)->isContainer()) { entity->addChildNode(primitive); return true; } else { return false; } }
void ScaleSelected::visit(const scene::INodePtr& node) const { ITransformNodePtr transformNode = Node_getTransformNode(node); if(transformNode != 0) { ITransformablePtr transform = Node_getTransformable(node); if(transform != 0) { transform->setType(TRANSFORM_PRIMITIVE); transform->setScale(c_scale_identity); transform->setTranslation(c_translation_identity); transform->setType(TRANSFORM_PRIMITIVE); transform->setScale(m_scale); { EditablePtr editable = Node_getEditable(node); const Matrix4& localPivot = editable != 0 ? editable->getLocalPivot() : Matrix4::getIdentity(); Vector3 parent_translation; translation_for_pivoted_scale( parent_translation, m_scale, m_world_pivot, node->localToWorld().getMultipliedBy(localPivot), transformNode->localToParent().getMultipliedBy(localPivot) ); transform->setTranslation(parent_translation); } } } }
void GraphTreeModel::updateSelectionStatus(const scene::INodePtr& node, const NotifySelectionUpdateFunc& notifySelectionChanged) { NodeMap::const_iterator found = _nodemap.find(scene::INodeWeakPtr(node)); GraphTreeNodePtr foundNode; if (found == _nodemap.end()) { // The node is not in our map, it might have been previously hidden if (node->visible()) { foundNode = insert(node); } } else { foundNode = found->second; } if (foundNode) { notifySelectionChanged(foundNode->getIter(), Node_isSelected(node)); } }
void visit(const scene::INodePtr& node) const { BrushNodePtr brush = std::dynamic_pointer_cast<BrushNode>(node); if (brush != NULL && node->visible()) { brush->setClipPlane(_plane); } }
void InfoFileExporter::visit(const scene::INodePtr& node) { // Don't export the layer settings for models and particles, as they are not there // at map load/parse time - these shouldn't even be passed in here assert(node && !Node_isModel(node) && !particles::isParticleNode(node)); // Open a Node block _stream << "\t\t" << InfoFile::NODE << " { "; scene::LayerList layers = node->getLayers(); // Write a space-separated list of node IDs for (scene::LayerList::const_iterator i = layers.begin(); i != layers.end(); ++i) { _stream << *i << " "; } // Close the Node block _stream << "}"; // Write additional node info, for easier debugging of layer issues _stream << " // " << getNodeInfo(node); _stream << std::endl; _layerInfoCount++; }
virtual bool pre(const scene::INodePtr& node) { NamespacedPtr namespaced = Node_getNamespaced(node); if (!namespaced) { return true; } INamespace* foreignNamespace = namespaced->getNamespace(); // Do not reconnect to same namespace, this causes invalid name changes if (foreignNamespace == _nspace) { rWarning() << "ConnectNamespacedWalker: node '" << node->name() << "' is already attached to namespace at " << _nspace << std::endl; return true; } else if (foreignNamespace) { // The node is already connected to a different namespace, disconnect namespaced->disconnectNameObservers(); namespaced->detachNames(); namespaced->setNamespace(NULL); } // Set the namespace reference and add all "names" namespaced->setNamespace(_nspace); namespaced->attachNames(); return true; }
void Namespace::ensureNoConflicts(const scene::INodePtr& root) { // Instantiate a new, temporary namespace for the nodes below root Namespace foreignNamespace; // Move all nodes below (and including) root into this temporary namespace foreignNamespace.connect(root); // Collect all namespaced items from the foreign root GatherNamespacedWalker walker; root->traverse(walker); rDebug() << "Namespace::ensureNoConflicts(): imported set of " << walker.result.size() << " namespaced nodes" << std::endl; // Build a union set containing all imported names and all existing names. // We need to know all existing names to ensure that newly created names are // unique in *both* namespaces UniqueNameSet allNames = _uniqueNames; allNames.merge(foreignNamespace._uniqueNames); // Process each object in the to-be-imported tree of nodes, ensuring that it // has a unique name for (const NamespacedPtr& n : walker.result) { // If the imported node conflicts with a name in THIS namespace, then it // needs to be given a new name which is unique in BOTH namespaces. if (_uniqueNames.nameExists(n->getName())) { // Name exists in the target namespace, get a new name std::string uniqueName = allNames.insertUnique(n->getName()); rMessage() << "Namespace::ensureNoConflicts(): '" << n->getName() << "' already exists in this namespace. Rename it to '" << uniqueName << "'\n"; // Change the name of the imported node, this should trigger all // observers in the foreign namespace n->changeName(uniqueName); } else { // Name does not exist yet, insert it into the local combined // namespace (but not our destination namespace, this will be // populated in the subsequent call to connect()). allNames.insert(n->getName()); } } // at this point, all names in the foreign namespace have been converted to // something unique in this namespace. The calling code can now move the // nodes into this namespace without name conflicts // Disconnect the root from the foreign namespace again, it will be destroyed now foreignNamespace.disconnect(root); }
bool pre(const scene::INodePtr& node) { SelectablePtr selectable = Node_getSelectable(node); // If a visible selectable was found and the path depth is appropriate, add it if (selectable != NULL && node->visible()) { _targetList.push_back(node); } return true; }
void post(const scene::INodePtr& node) { if (node->isRoot()) { return; } if (Node_isSelected(node)) { // Clone the current node scene::INodePtr clone = map::Node_Clone(node); // Add the cloned node and its parent to the list _cloned.insert(Map::value_type(clone, node->getParent())); // Insert this node in the root _cloneRoot->addChildNode(clone); } }
void PlaneSelectableSelectPlanes::visit(const scene::INodePtr& node) const { // Skip hidden nodes if (!node->visible()) { return; } PlaneSelectablePtr planeSelectable = Node_getPlaneSelectable(node); if (planeSelectable != NULL) { planeSelectable->selectPlanes(_selector, _test, _selectedPlaneCallback); } }
void ScaleComponentSelected::visit(const scene::INodePtr& node) const { ITransformablePtr transform = Node_getTransformable(node); if(transform != 0) { Vector3 parent_translation; translation_for_pivoted_scale(parent_translation, m_scale, m_world_pivot, node->localToWorld(), Node_getTransformNode(node)->localToParent()); transform->setType(TRANSFORM_COMPONENT); transform->setScale(m_scale); transform->setTranslation(parent_translation); } }
bool addPrimitiveToEntity(const scene::INodePtr& primitive, const scene::INodePtr& entity) { if (Node_getEntity(entity)->isContainer()) { entity->addChildNode(primitive); return true; } else { return false; } }
void visit(const scene::INodePtr& node) const { ASSERT_MESSAGE(_count <= _max, "Invalid _count in CollectSelectedBrushesBounds"); // stop if the array is already full if (_count == _max) { return; } if (Node_isSelected(node) && Node_isBrush(node)) { _bounds[_count] = node->worldAABB(); ++_count; } }
void post(const scene::INodePtr& node) { // greebo: We've traversed this subtree, now check if we had selected children if (!node->isRoot() && !_stack.empty() && _stack.top() == false && !Node_isSelected(node)) { // No selected child nodes, hide this node hideSubgraph(node, _hide); } // Go upwards again, one level _stack.pop(); }
bool pre(const scene::INodePtr& node) { if (!node->visible()) return false; // don't traverse hidden nodes if (Node_isBrush(node)) // this node is a floor { const AABB& aabb = node->worldAABB(); float floorHeight = aabb.origin.z() + aabb.extents.z(); if (floorHeight > _current && floorHeight < _bestUp) { _bestUp = floorHeight; } if (floorHeight < _current && floorHeight > _bestDown) { _bestDown = floorHeight; } return false; } return true; }
bool pre(const scene::INodePtr& node) { if (node->visible()) { Brush* brush = Node_getBrush(node); if (brush != NULL && brush->hasShader(_name)) { Node_setSelected(node, true); return false; // don't traverse brushes } // not a suitable brush, traverse further return true; } else { return false; // don't traverse invisible nodes } }
bool pre(const scene::INodePtr& node) { // Don't clone root items if (node->isRoot()) { return true; } if (Node_isSelected(node)) { // Don't traverse children of cloned nodes return false; } return true; }
bool pre(const scene::INodePtr& node) { // Ignore hidden nodes if (!node->visible()) return false; Entity* entity = Node_getEntity(node); // Check if we have a selectable SelectablePtr selectable = Node_getSelectable(node); if (selectable != NULL) { switch (_mode) { case SelectionSystem::eEntity: if (entity != NULL && entity->getKeyValue("classname") != "worldspawn") { _selectable = selectable; } break; case SelectionSystem::ePrimitive: _selectable = selectable; break; case SelectionSystem::eComponent: // Check if we have a componentselectiontestable instance ComponentSelectionTestablePtr compSelTestable = Node_getComponentSelectionTestable(node); // Only add it to the list if the instance has components and is already selected if (compSelTestable != NULL && selectable->isSelected()) { _selectable = selectable; } break; } } // Do we have a groupnode? If yes, don't traverse the children if (entity != NULL && node_is_group(node) && entity->getKeyValue("classname") != "worldspawn") { // Don't traverse the children of this groupnode return false; } return true; }
bool EntitySelectByClassnameWalker::pre(const scene::INodePtr& node) { // don't traverse invisible nodes if (!node->visible()) return false; Entity* entity = Node_getEntity(node); if (entity != NULL) { if (entityMatches(entity)) { // Got a matching entity Node_setSelected(node, true); } // Don't traverse entities return false; } // Not an entity, traverse return true; }
void ModelExporter::processBrush(const scene::INodePtr& node) { IBrush* brush = Node_getIBrush(node); if (brush == nullptr) return; Matrix4 exportTransform = node->localToWorld().getPremultipliedBy(_centerTransform); for (std::size_t b = 0; b < brush->getNumFaces(); ++b) { const IFace& face = brush->getFace(b); const std::string& materialName = face.getShader(); if (!isExportableMaterial(materialName)) continue; const IWinding& winding = face.getWinding(); std::vector<model::ModelPolygon> polys; if (winding.size() < 3) { rWarning() << "Skipping face with less than 3 winding verts" << std::endl; continue; } // Create triangles for this winding for (std::size_t i = 1; i < winding.size() - 1; ++i) { model::ModelPolygon poly; poly.a = convertWindingVertex(winding[i + 1]); poly.b = convertWindingVertex(winding[i]); poly.c = convertWindingVertex(winding[0]); polys.push_back(poly); } _exporter->addPolygons(materialName, polys, exportTransform); } }
// The visitor function bool pre(const scene::INodePtr& node) { // Check if the node is filtered if (node->visible()) { SelectionTestablePtr selectionTestable = Node_getSelectionTestable(node); if (selectionTestable != NULL) { bool occluded; OccludeSelector selector(_bestIntersection, occluded); selectionTestable->testSelect(selector, _selectionTest); if (occluded) { _node = node; } } } else { return false; // don't traverse filtered nodes } return true; }
void GraphTreeModel::updateSelectionStatus(const Glib::RefPtr<Gtk::TreeSelection>& selection, const scene::INodePtr& node) { NodeMap::const_iterator found = _nodemap.find(scene::INodeWeakPtr(node)); GraphTreeNodePtr foundNode; if (found == _nodemap.end()) { // The node is not in our map, it might have been previously hidden if (node->visible()) { foundNode = insert(node); } } else { foundNode = found->second; } if (foundNode) { if (Node_isSelected(node)) { // Select the row in the TreeView selection->select(foundNode->getIter()); // Scroll to the row Gtk::TreeView* tv = selection->get_tree_view(); Gtk::TreeModel::Path selectedPath(foundNode->getIter()); tv->expand_to_path(selectedPath); tv->scroll_to_row(selectedPath, 0.3f); } else { selection->unselect(foundNode->getIter()); } } }
bool pre(const scene::INodePtr& node) { // Check the selection status bool isSelected = Node_isSelected(node); // greebo: Don't check root nodes for selected state if (!node->isRoot() && isSelected) { // We have a selected instance, "remember" this by setting the parent // stack element to TRUE if (!_stack.empty()) { _stack.top() = true; } } // We are going one level deeper, add a new stack element for this subtree _stack.push(false); // Try to go deeper, but don't do this for deselected instances return !isSelected; }
void ModelExporter::processPatch(const scene::INodePtr& node) { IPatch* patch = Node_getIPatch(node); if (patch == nullptr) return; const std::string& materialName = patch->getShader(); if (!isExportableMaterial(materialName)) return; PatchMesh mesh = patch->getTesselatedPatchMesh(); std::vector<model::ModelPolygon> polys; for (std::size_t h = 0; h < mesh.height - 1; ++h) { for (std::size_t w = 0; w < mesh.width - 1; ++w) { model::ModelPolygon poly; poly.a = convertPatchVertex(mesh.vertices[w + (h*mesh.width)]); poly.b = convertPatchVertex(mesh.vertices[w + 1 + (h*mesh.width)]); poly.c = convertPatchVertex(mesh.vertices[w + mesh.width + (h*mesh.width)]); polys.push_back(poly); poly.a = convertPatchVertex(mesh.vertices[w + 1 + (h*mesh.width)]); poly.b = convertPatchVertex(mesh.vertices[w + 1 + mesh.width + (h*mesh.width)]); poly.c = convertPatchVertex(mesh.vertices[w + mesh.width + (h*mesh.width)]); polys.push_back(poly); } } Matrix4 exportTransform = node->localToWorld().getPremultipliedBy(_centerTransform); _exporter->addPolygons(materialName, polys, exportTransform); }
inline bool Node_hasChildren(scene::INodePtr node) { return node->hasChildNodes(); }
void createCaps(Patch& patch, const scene::INodePtr& parent, EPatchCap type, const std::string& shader) { if ((type == eCapEndCap || type == eCapIEndCap) && patch.getWidth() != 5) { rError() << "cannot create end-cap - patch width != 5" << std::endl; gtkutil::MessageBox::ShowError(_("Cannot create end-cap, patch must have a width of 5."), GlobalMainFrame().getTopLevelWindow()); return; } if ((type == eCapBevel || type == eCapIBevel) && patch.getWidth() != 3) { gtkutil::MessageBox::ShowError(_("Cannot create bevel-cap, patch must have a width of 3."), GlobalMainFrame().getTopLevelWindow()); rError() << "cannot create bevel-cap - patch width != 3" << std::endl; return; } if (type == eCapCylinder && patch.getWidth() != 9) { gtkutil::MessageBox::ShowError(_("Cannot create cylinder-cap, patch must have a width of 9."), GlobalMainFrame().getTopLevelWindow()); rError() << "cannot create cylinder-cap - patch width != 9" << std::endl; return; } assert(parent != NULL); { scene::INodePtr cap(GlobalPatchCreator(DEF2).createPatch()); parent->addChildNode(cap); Patch* capPatch = Node_getPatch(cap); assert(capPatch != NULL); patch.MakeCap(capPatch, type, ROW, true); capPatch->setShader(shader); // greebo: Avoid creating "degenerate" patches (all vertices merged in one 3D point) if (!capPatch->isDegenerate()) { Node_setSelected(cap, true); } else { parent->removeChildNode(cap); rWarning() << "Prevented insertion of degenerate patch." << std::endl; } } { scene::INodePtr cap(GlobalPatchCreator(DEF2).createPatch()); parent->addChildNode(cap); Patch* capPatch = Node_getPatch(cap); assert(capPatch != NULL); patch.MakeCap(capPatch, type, ROW, false); capPatch->setShader(shader); // greebo: Avoid creating "degenerate" patches (all vertices merged in one 3D point) if (!capPatch->isDegenerate()) { Node_setSelected(cap, true); } else { parent->removeChildNode(cap); rWarning() << "Prevented insertion of degenerate patch." << std::endl; } } }
bool addEntity(const scene::INodePtr& entityNode) { _root->addChildNode(entityNode); return true; }
void BrushByPlaneClipper::visit(const scene::INodePtr& node) const { // Don't clip invisible nodes if (!node->visible()) { return; } // Try to cast the instance onto a brush Brush* brush = Node_getBrush(node); // Return if not brush if (brush == NULL) { return; } Plane3 plane(_p0, _p1, _p2); if (!plane.isValid()) { return; } // greebo: Analyse the brush to find out which shader is the most used one getMostUsedTexturing(brush); BrushSplitType split = Brush_classifyPlane(*brush, _split == eFront ? -plane : plane); if (split.counts[ePlaneBack] && split.counts[ePlaneFront]) { // the plane intersects this brush if (_split == eFrontAndBack) { scene::INodePtr brushNode = GlobalBrushCreator().createBrush(); assert(brushNode != NULL); Brush* fragment = Node_getBrush(brushNode); assert(fragment != NULL); fragment->copy(*brush); FacePtr newFace = fragment->addPlane(_p0, _p1, _p2, _mostUsedShader, _mostUsedProjection); if (newFace != NULL && _split != eFront) { newFace->flipWinding(); } fragment->removeEmptyFaces(); ASSERT_MESSAGE(!fragment->empty(), "brush left with no faces after split"); // Mark this brush for insertion _insertList.insert(InsertMap::value_type(brushNode, node->getParent())); } FacePtr newFace = brush->addPlane(_p0, _p1, _p2, _mostUsedShader, _mostUsedProjection); if (newFace != NULL && _split == eFront) { newFace->flipWinding(); } brush->removeEmptyFaces(); ASSERT_MESSAGE(!brush->empty(), "brush left with no faces after split"); } // the plane does not intersect this brush else if (_split != eFrontAndBack && split.counts[ePlaneBack] != 0) { // the brush is "behind" the plane _deleteList.insert(node); } }