void makeVisportal(const cmd::ArgumentList& args) { BrushPtrVector brushes = getSelectedBrushes(); if (brushes.size() <= 0) { gtkutil::errorDialog(_("No brushes selected."), GlobalMainFrame().getTopLevelWindow()); return; } // Create a scoped undocmd object UndoableCommand cmd("brushMakeVisportal"); for (std::size_t i = 0; i < brushes.size(); i++) { Brush& brush = brushes[i]->getBrush(); // don't allow empty brushes if (brush.getNumFaces() == 0) continue; // Set all faces to nodraw first brush.setShader(GlobalRegistry().get(RKEY_NODRAW_SHADER)); // Find the largest face (in terms of area) LargestFaceFinder finder; brush.forEachFace(finder); finder.getLargestFace().setShader(GlobalRegistry().get(RKEY_VISPORTAL_SHADER)); } }
void mergeSelectedBrushes(const cmd::ArgumentList& args) { // Get the current selection BrushPtrVector brushes = selection::algorithm::getSelectedBrushes(); if (brushes.empty()) { rMessage() << _("CSG Merge: No brushes selected.") << std::endl; wxutil::Messagebox::ShowError(_("CSG Merge: No brushes selected.")); return; } if (brushes.size() < 2) { rMessage() << "CSG Merge: At least two brushes have to be selected.\n"; wxutil::Messagebox::ShowError("CSG Merge: At least two brushes have to be selected."); return; } rMessage() << "CSG Merge: Merging " << brushes.size() << " brushes." << std::endl; UndoableCommand undo("mergeSelectedBrushes"); // Take the last selected node as reference for layers and parent scene::INodePtr merged = GlobalSelectionSystem().ultimateSelected(); scene::INodePtr parent = merged->getParent(); assert(parent != NULL); // Create a new BrushNode scene::INodePtr node = GlobalBrushCreator().createBrush(); // Insert the newly created brush into the (same) parent entity parent->addChildNode(node); // Move the new brush to the same layers as the merged one node->assignToLayers(merged->getLayers()); // Get the contained brush Brush* brush = Node_getBrush(node); // Attempt to merge the selected brushes into the new one if (!Brush_merge(*brush, brushes, true)) { rWarning() << "CSG Merge: Failed - result would not be convex." << std::endl; return; } ASSERT_MESSAGE(!brush->empty(), "brush left with no faces after merge"); // Remove the original brushes for (BrushPtrVector::iterator i = brushes.begin(); i != brushes.end(); ++i) { scene::removeNodeFromParent(*i); } // Select the new brush Node_setSelected(node, true); rMessage() << "CSG Merge: Succeeded." << std::endl; SceneChangeNotify(); }
void makeRoomForSelectedBrushes(const cmd::ArgumentList& args) { UndoableCommand undo("brushMakeRoom"); // Find all brushes BrushPtrVector brushes = selection::algorithm::getSelectedBrushes(); // Cycle through the brushes and hollow them // We assume that all these selected brushes are visible as well. for (std::size_t i = 0; i < brushes.size(); ++i) { hollowBrush(brushes[i], true); } SceneChangeNotify(); }
void subtractBrushesFromUnselected(const cmd::ArgumentList& args) { if (registry::getValue<bool>(RKEY_EMIT_CSG_SUBTRACT_WARNING)) { wxutil::Messagebox::Show(_("This Is Not Dromed Warning"), _("Note: be careful when using the CSG tool, as you might end up\n" "with an unnecessary number of tiny brushes and/or leaks.\n" "This popup will not be shown again."), ui::IDialog::MESSAGE_CONFIRM); // Disable this warning registry::setValue(RKEY_EMIT_CSG_SUBTRACT_WARNING, false); } // Collect all selected brushes BrushPtrVector brushes = selection::algorithm::getSelectedBrushes(); if (brushes.empty()) { rMessage() << _("CSG Subtract: No brushes selected.") << std::endl; wxutil::Messagebox::ShowError(_("CSG Subtract: No brushes selected.")); return; } rMessage() << "CSG Subtract: Subtracting " << brushes.size() << " brushes.\n"; UndoableCommand undo("brushSubtract"); // subtract selected from unselected std::size_t before = 0; std::size_t after = 0; // instantiate a scoped walker class { SubtractBrushesFromUnselected walker(brushes, before, after); GlobalSceneGraph().root()->traverse(walker); } rMessage() << "CSG Subtract: Result: " << after << " fragment" << (after == 1 ? "" : "s") << " from " << before << " brush" << (before == 1 ? "" : "es") << ".\n"; SceneChangeNotify(); }
// Try to create a CM from the selected entity void createCMFromSelection(const cmd::ArgumentList& args) { // Check the current selection state const SelectionInfo& info = GlobalSelectionSystem().getSelectionInfo(); if (info.totalCount == info.entityCount && info.totalCount == 1) { // Retrieve the node, instance and entity const scene::INodePtr& entityNode = GlobalSelectionSystem().ultimateSelected(); // Try to retrieve the group node scene::GroupNodePtr groupNode = Node_getGroupNode(entityNode); // Remove the entity origin from the brushes if (groupNode != NULL) { groupNode->removeOriginFromChildren(); // Deselect the node Node_setSelected(entityNode, false); // Select all the child nodes NodeSelector visitor; entityNode->traverse(visitor); BrushPtrVector brushes = algorithm::getSelectedBrushes(); // Create a new collisionmodel on the heap using a shared_ptr cmutil::CollisionModelPtr cm(new cmutil::CollisionModel()); // Add all the brushes to the collision model for (std::size_t i = 0; i < brushes.size(); i++) { cm->addBrush(brushes[i]->getBrush()); } ui::ModelSelectorResult modelAndSkin = ui::ModelSelector::chooseModel("", false, false); std::string basePath = GlobalGameManager().getModPath(); std::string modelPath = basePath + modelAndSkin.model; std::string newExtension = "." + GlobalRegistry().get(RKEY_CM_EXT); // Set the model string to correctly associate the clipmodel cm->setModel(modelAndSkin.model); try { // create the new autosave filename by changing the extension Path cmPath = boost::filesystem::change_extension( Path(modelPath, boost::filesystem::native), newExtension ); // Open the stream to the output file std::ofstream outfile(cmPath.string().c_str()); if (outfile.is_open()) { // Insert the CollisionModel into the stream outfile << *cm; // Close the file outfile.close(); globalOutputStream() << "CollisionModel saved to " << cmPath.string() << std::endl; } else { gtkutil::errorDialog( (boost::format("Couldn't save to file: %s") % cmPath.string()).str(), GlobalMainFrame().getTopLevelWindow()); } } catch (boost::filesystem::filesystem_error f) { globalErrorStream() << "CollisionModel: " << f.what() << std::endl; } // De-select the child brushes GlobalSelectionSystem().setSelectedAll(false); // Re-add the origin to the brushes groupNode->addOriginToChildren(); // Re-select the node Node_setSelected(entityNode, true); } } else { gtkutil::errorDialog( _(ERRSTR_WRONG_SELECTION.c_str()), GlobalMainFrame().getTopLevelWindow()); } }