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 surroundWithMonsterclip(const cmd::ArgumentList& args) { UndoableCommand command("addMonsterclip"); // create a ModelFinder and retrieve the modelList selection::algorithm::ModelFinder visitor; GlobalSelectionSystem().foreachSelected(visitor); // Retrieve the list with all the found models from the visitor selection::algorithm::ModelFinder::ModelList list = visitor.getList(); selection::algorithm::ModelFinder::ModelList::iterator iter; for (iter = list.begin(); iter != list.end(); ++iter) { // one of the models in the SelectionStack const scene::INodePtr& node = *iter; // retrieve the AABB AABB brushAABB(node->worldAABB()); // create the brush scene::INodePtr brushNode(GlobalBrushCreator().createBrush()); if (brushNode != NULL) { scene::addNodeToContainer(brushNode, GlobalMap().findOrInsertWorldspawn()); Brush* theBrush = Node_getBrush(brushNode); std::string clipShader = GlobalRegistry().get(RKEY_MONSTERCLIP_SHADER); Scene_BrushResize(*theBrush, brushAABB, clipShader); } } }
void AddFaceWithTexture(scene::Node& brush, vec3_t va, vec3_t vb, vec3_t vc, const char* texture, bool detail) { _QERFaceData faceData; FillDefaultTexture(&faceData, va, vb, vc, texture); if(detail) faceData.contents |= FACE_DETAIL; GlobalBrushCreator().Brush_addFace(brush, faceData); }
void Build_StairStep(vec3_t min, vec3_t max, const char* mainTexture, const char* riserTexture, int direction) { NodeSmartReference newBrush(GlobalBrushCreator().createBrush()); //----- Build Outer Bounds --------- vec3_t v1, v2, v3, v5, v6, v7; VectorCopy(min, v1); VectorCopy(min, v2); VectorCopy(min, v3); VectorCopy(max, v5); VectorCopy(max, v6); VectorCopy(max, v7); v2[0] = max[0]; v3[1] = max[1]; v6[0] = min[0]; v7[1] = min[1]; //---------------------------------- AddFaceWithTexture(newBrush, v6, v5, v7, mainTexture, false); // top gets current texture if(direction == MOVE_EAST) AddFaceWithTexture(newBrush, v1, v3, v6, riserTexture, false); else AddFaceWithTexture(newBrush, v1, v3, v6, "textures/common/caulk", false); // west facing side, etc... if(direction == MOVE_NORTH) AddFaceWithTexture(newBrush, v1, v7, v2, riserTexture, false); else AddFaceWithTexture(newBrush, v1, v7, v2, "textures/common/caulk", false); if(direction == MOVE_SOUTH) AddFaceWithTexture(newBrush, v3, v5, v6, riserTexture, false); else AddFaceWithTexture(newBrush, v3, v5, v6, "textures/common/caulk", false); if(direction == MOVE_WEST) AddFaceWithTexture(newBrush, v7, v5, v2, riserTexture, false); else AddFaceWithTexture(newBrush, v7, v5, v2, "textures/common/caulk", false); AddFaceWithTexture(newBrush, v1, v2, v3, "textures/common/caulk", false); // base is caulked Node_getTraversable(GlobalRadiant().getMapWorldEntity())->insert(newBrush); // finish brush }
void AddFaceWithTextureScaled(scene::Node& brush, vec3_t va, vec3_t vb, vec3_t vc, const char* texture, bool bVertScale, bool bHorScale, float minX, float minY, float maxX, float maxY) { qtexture_t* pqtTexInfo; // TTimo: there used to be a call to pfnHasShader here // this was not necessary. In Radiant everything is shader. // If a texture doesn't have a shader script, a default shader object is used. // The IShader object was leaking also // collect texture info: sizes, etc IShader* i = GlobalShaderSystem().getShaderForName(texture); pqtTexInfo = i->getTexture(); // shader width/height doesn't come out properly if(pqtTexInfo) { float scale[2] = {0.5f, 0.5f}; float shift[2] = {0, 0}; if(bHorScale) { float width = maxX - minX; scale[0] = width/pqtTexInfo->width; shift[0] = -(float)((int)maxX%(int)width)/scale[0]; } if(bVertScale) { float height = maxY - minY; scale[1] = height/pqtTexInfo->height; shift[1] = (float)((int)minY%(int)height)/scale[1]; } _QERFaceData addFace; FillDefaultTexture(&addFace, va, vb, vc, texture); addFace.m_texdef.scale[0] = scale[0]; addFace.m_texdef.scale[1] = scale[1]; addFace.m_texdef.shift[0] = shift[0]; addFace.m_texdef.shift[1] = shift[1]; GlobalBrushCreator().Brush_addFace(brush, addFace); } else { // shouldn't even get here, as default missing texture should be returned if // texture doesn't exist, but just in case AddFaceWithTexture(brush, va, vb, vc, texture, false); globalErrorStream() << "BobToolz::Invalid Texture Name-> " << texture; } // the IShader is not kept referenced, DecRef it i->DecRef(); }
scene::Node& createPrimitive( const char* name ){ if ( string_equal( name, "brush" ) ) { return GlobalBrushCreator().createBrush(); } else if ( string_equal( name, "patch" ) ) { return GlobalPatchCreator().createPatch(); } ASSERT_MESSAGE( 0, PARSE_ERROR << ": primitive type not supported: \"" << name << "\"\n" ); scene::Node* node = 0; return *node; }
void hollowBrush(const BrushNodePtr& sourceBrush, bool makeRoom) { // Hollow the brush using the current grid size sourceBrush->getBrush().forEachFace([&] (Face& face) { if (!face.contributes()) { return; } scene::INodePtr parent = sourceBrush->getParent(); scene::INodePtr newNode = GlobalBrushCreator().createBrush(); BrushNodePtr brushNode = std::dynamic_pointer_cast<BrushNode>(newNode); assert(brushNode); // Add the child to the same parent as the source brush parent->addChildNode(brushNode); // Move the child brushes to the same layer as their source brushNode->assignToLayers(sourceBrush->getLayers()); // Copy all faces from the source brush brushNode->getBrush().copy(sourceBrush->getBrush()); Node_setSelected(brushNode, true); FacePtr newFace = brushNode->getBrush().addFace(face); if (newFace != 0) { float offset = GlobalGrid().getGridSize(); newFace->flipWinding(); newFace->getPlane().offset(offset); newFace->planeChanged(); if (makeRoom) { // Retrieve the normal vector of the "source" face brushNode->getBrush().transform(Matrix4::getTranslation(face.getPlane().getPlane().normal() * offset)); brushNode->getBrush().freezeTransform(); } } brushNode->getBrush().removeEmptyFaces(); }); // Now unselect and remove the source brush from the scene scene::removeNodeFromParent(sourceBrush); }
// internal use only, to get a box without finishing construction scene::Node& Build_Get_BoundingCube_Selective(vec3_t min, vec3_t max, char* texture, bool* useFaces) { NodeSmartReference newBrush(GlobalBrushCreator().createBrush()); //----- Build Outer Bounds --------- vec3_t v1, v2, v3, v5, v6, v7; VectorCopy(min, v1); VectorCopy(min, v2); VectorCopy(min, v3); VectorCopy(max, v5); VectorCopy(max, v6); VectorCopy(max, v7); v2[0] = max[0]; v3[1] = max[1]; v6[0] = min[0]; v7[1] = min[1]; //---------------------------------- //----- Add Six Cube Faces --------- if(useFaces[0]) AddFaceWithTexture(newBrush, v1, v2, v3, texture, false); if(useFaces[1]) AddFaceWithTexture(newBrush, v1, v3, v6, texture, false); if(useFaces[2]) AddFaceWithTexture(newBrush, v1, v7, v2, texture, false); if(useFaces[3]) AddFaceWithTexture(newBrush, v5, v6, v3, texture, false); if(useFaces[4]) AddFaceWithTexture(newBrush, v5, v2, v7, texture, false); if(useFaces[5]) AddFaceWithTexture(newBrush, v5, v7, v6, texture, false); //---------------------------------- return newBrush; }
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); } }
void BuildCornerStairs(vec3_t vMin, vec3_t vMax, int nSteps, const char* mainTexture, const char* riserTex) { vec3_t* topPoints = new vec3_t[nSteps+1]; vec3_t* botPoints = new vec3_t[nSteps+1]; //bool bFacesUse[6] = {true, true, false, true, false, false}; vec3_t centre; VectorCopy(vMin, centre); centre[0] = vMax[0]; int height = (int)(vMax[2] - vMin[2]) / nSteps; vec3_t vTop, vBot; VectorCopy(vMax, vTop); VectorCopy(vMin, vBot); vTop[2] = vMin[2] + height; int i; for(i = 0; i <= nSteps; i++) { VectorCopy(centre, topPoints[i]); VectorCopy(centre, botPoints[i]); topPoints[i][2] = vMax[2]; botPoints[i][2] = vMin[2]; topPoints[i][0] -= 10 * sinf( Q_PI * i / ( 2 * nSteps ) ); topPoints[i][1] += 10 * cosf( Q_PI * i / ( 2 * nSteps ) ); botPoints[i][0] = topPoints[i][0]; botPoints[i][1] = topPoints[i][1]; } vec3_t tp[3]; for(int j = 0; j < 3; j++) VectorCopy(topPoints[j], tp[j]); for(i = 0; i < nSteps; i++) { NodeSmartReference brush(GlobalBrushCreator().createBrush()); vec3_t v1, v2, v3, v5, v6, v7; VectorCopy(vBot, v1); VectorCopy(vBot, v2); VectorCopy(vBot, v3); VectorCopy(vTop, v5); VectorCopy(vTop, v6); VectorCopy(vTop, v7); v2[0] = vTop[0]; v3[1] = vTop[1]; v6[0] = vBot[0]; v7[1] = vBot[1]; AddFaceWithTexture(brush, v1, v2, v3, "textures/common/caulk", false); AddFaceWithTexture(brush, v1, v3, v6, "textures/common/caulk", false); AddFaceWithTexture(brush, v5, v6, v3, "textures/common/caulk", false); for(int j = 0; j < 3; j++) tp[j][2] = vTop[2]; AddFaceWithTexture(brush, tp[2], tp[1], tp[0], mainTexture, false); AddFaceWithTexture(brush, centre, botPoints[i+1], topPoints[i+1], "textures/common/caulk", false); AddFaceWithTexture(brush, centre, topPoints[i], botPoints[i], riserTex, false); Node_getTraversable(GlobalRadiant().getMapWorldEntity())->insert(brush); vTop[2] += height; vBot[2] += height; } delete[] topPoints; delete[] botPoints; vMin[2] += height; vMax[2] += height; MakeBevel(vMin, vMax); }
void Build_StairStep_Wedge(int dir, vec3_t min, vec3_t max, const char* mainTexture, const char* riserTexture, bool detail) { NodeSmartReference newBrush(GlobalBrushCreator().createBrush()); //----- Build Outer Bounds --------- vec3_t v1, v2, v3, v5, v6, v7, v8; VectorCopy(min, v1); VectorCopy(min, v2); VectorCopy(min, v3); VectorCopy(max, v5); VectorCopy(max, v6); VectorCopy(max, v7); VectorCopy(max, v8); v2[0] = max[0]; v3[1] = max[1]; v6[0] = min[0]; v7[1] = min[1]; v8[2] = min[2]; //v8 needed this time, becoz of sloping faces (2-4-6-8) //---------------------------------- AddFaceWithTexture(newBrush, v6, v5, v7, mainTexture, detail); if(dir != MOVE_EAST) { if(dir == MOVE_WEST) AddFaceWithTexture(newBrush, v5, v2, v7, riserTexture, detail); else AddFaceWithTexture(newBrush, v5, v2, v7, "textures/common/caulk", detail); } if(dir != MOVE_WEST) { if(dir == MOVE_EAST) AddFaceWithTexture(newBrush, v1, v3, v6, riserTexture, detail); else AddFaceWithTexture(newBrush, v1, v3, v6, "textures/common/caulk", detail); } if(dir != MOVE_NORTH) { if(dir == MOVE_SOUTH) AddFaceWithTexture(newBrush, v3, v5, v6, riserTexture, detail); else AddFaceWithTexture(newBrush, v3, v5, v6, "textures/common/caulk", detail); } if(dir != MOVE_SOUTH) { if(dir == MOVE_NORTH) AddFaceWithTexture(newBrush, v1, v7, v2, riserTexture, detail); else AddFaceWithTexture(newBrush, v1, v7, v2, "textures/common/caulk", detail); } if(dir == MOVE_EAST) AddFaceWithTexture(newBrush, v1, v5, v3, "textures/common/caulk", detail); if(dir == MOVE_WEST) AddFaceWithTexture(newBrush, v2, v8, v6, "textures/common/caulk", detail); if(dir == MOVE_NORTH) AddFaceWithTexture(newBrush, v1, v5, v6, "textures/common/caulk", detail); if(dir == MOVE_SOUTH) AddFaceWithTexture(newBrush, v7, v8, v3, "textures/common/caulk", detail); Node_getTraversable(GlobalRadiant().getMapWorldEntity())->insert(newBrush); }
void Build_Wedge(int dir, vec3_t min, vec3_t max, bool bUp) { NodeSmartReference newBrush(GlobalBrushCreator().createBrush()); vec3_t v1, v2, v3, v5, v6, v7, v8; VectorCopy(min, v1); VectorCopy(min, v2); VectorCopy(min, v3); VectorCopy(max, v5); VectorCopy(max, v6); VectorCopy(max, v7); VectorCopy(max, v8); v2[0] = max[0]; v3[1] = max[1]; v6[0] = min[0]; v7[1] = min[1]; v8[2] = min[2]; if(bUp) { if(dir != MOVE_EAST) AddFaceWithTexture(newBrush, v1, v3, v6, "textures/common/caulk", false); if(dir != MOVE_WEST) AddFaceWithTexture(newBrush, v7, v5, v8, "textures/common/caulk", false); if(dir != MOVE_NORTH) AddFaceWithTexture(newBrush, v1, v7, v2, "textures/common/caulk", false); if(dir != MOVE_SOUTH) AddFaceWithTexture(newBrush, v3, v8, v6, "textures/common/caulk", false); AddFaceWithTexture(newBrush, v1, v2, v3, "textures/common/caulk", false); if(dir == MOVE_EAST) AddFaceWithTexture(newBrush, v1, v3, v5, "textures/common/caulk", false); if(dir == MOVE_WEST) AddFaceWithTexture(newBrush, v2, v6, v8, "textures/common/caulk", false); if(dir == MOVE_NORTH) AddFaceWithTexture(newBrush, v1, v6, v5, "textures/common/caulk", false); if(dir == MOVE_SOUTH) AddFaceWithTexture(newBrush, v7, v3, v8, "textures/common/caulk", false); } else { if(dir != MOVE_WEST) AddFaceWithTexture(newBrush, v7, v5, v8, "textures/common/caulk", false); if(dir != MOVE_EAST) AddFaceWithTexture(newBrush, v1, v3, v6, "textures/common/caulk", false); if(dir != MOVE_NORTH) AddFaceWithTexture(newBrush, v3, v8, v6, "textures/common/caulk", false); if(dir != MOVE_SOUTH) AddFaceWithTexture(newBrush, v1, v7, v2, "textures/common/caulk", false); AddFaceWithTexture(newBrush, v6, v5, v7, "textures/common/caulk", false); if(dir == MOVE_WEST) AddFaceWithTexture(newBrush, v1, v5, v3, "textures/common/caulk", false); if(dir == MOVE_EAST) AddFaceWithTexture(newBrush, v2, v8, v6, "textures/common/caulk", false); if(dir == MOVE_NORTH) AddFaceWithTexture(newBrush, v1, v5, v6, "textures/common/caulk", false); if(dir == MOVE_SOUTH) AddFaceWithTexture(newBrush, v7, v8, v3, "textures/common/caulk", false); } Node_getTraversable(GlobalRadiant().getMapWorldEntity())->insert(newBrush); }
void BrushByPlaneClipper::split(const BrushPtrVector& brushes) { Plane3 plane(_p0, _p1, _p2); if (!plane.isValid()) { return; } for (BrushPtrVector::const_iterator i = brushes.begin(); i != brushes.end(); ++i) { const BrushNodePtr& node = *i; // Don't clip invisible nodes if (!node->visible()) { continue; } Brush& brush = node->getBrush(); scene::INodePtr parent = node->getParent(); if (!parent) { continue; } // 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 fragmentNode = GlobalBrushCreator().createBrush(); assert(fragmentNode != NULL); // Put the fragment in the same layer as the brush it was clipped from // Do this before adding the fragment to the parent, since there is an // update algorithm setting the visibility of the fragment right there. scene::assignNodeToLayers(fragmentNode, node->getLayers()); // greebo: For copying the texture scale the new node needs to be inserted in the scene // otherwise the shaders cannot be captured and the scale is off // Insert the child into the designated parent scene::addNodeToContainer(fragmentNode, parent); // Select the child Node_setSelected(fragmentNode, true); Brush* fragment = Node_getBrush(fragmentNode); 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"); } 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 // Remove the node from the scene scene::removeNodeFromParent(node); } } }
/* // Example Primitive { brushDef { ( -1216 -464 232 ) ( -1088 -464 232 ) ( -1088 -80 120 ) ( ( 0.031250 0 14 ) ( -0.000009 0.031250 4.471550 ) ) common/caulk 134217728 4 0 ( -1088 -464 248 ) ( -1216 -464 248 ) ( -1216 -80 136 ) ( ( 0 -0.031373 -0.147059 ) ( 0.007812 0 0.049020 ) ) common/caulk 134217728 0 0 ( -1088 -560 120 ) ( -1088 -560 136 ) ( -1088 -80 136 ) ( ( 0.031250 0 16.500000 ) ( 0 0.031250 0.250000 ) ) common/caulk 134217728 4 0 ( -1088 -80 136 ) ( -1216 -80 136 ) ( -1216 -80 8 ) ( ( 0.031250 0 2 ) ( 0 0.031250 0.250000 ) ) common/caulk 134217728 4 0 ( -1216 -400 136 ) ( -1216 -400 120 ) ( -1216 -80 120 ) ( ( 0.031250 0 -16.500000 ) ( 0 0.031250 0.250000 ) ) common/caulk 134217728 4 0 ( -1088 -464 232 ) ( -1216 -464 232 ) ( -1216 -464 248 ) ( ( 0.031250 0 -2 ) ( 0 0.031250 0.250000 ) ) common/caulk 134217728 4 0 } } */ scene::INodePtr BrushDefParser::parse(parser::DefTokeniser& tok) const { // Create a new brush scene::INodePtr node = GlobalBrushCreator().createBrush(); // Cast the node, this must succeed IBrushNodePtr brushNode = boost::dynamic_pointer_cast<IBrushNode>(node); assert(brushNode != NULL); IBrush& brush = brushNode->getIBrush(); tok.assertNextToken("{"); // Parse face tokens until a closing brace is encountered while (1) { std::string token = tok.nextToken(); // Token should be either a "(" (start of face) or "}" (end of brush) if (token == "}") { break; // end of brush } else if (token == "(") // FACE { // Parse three 3D points to construct a plane Vector3 p1(string::to_float(tok.nextToken()), string::to_float(tok.nextToken()), string::to_float(tok.nextToken())); tok.assertNextToken(")"); tok.assertNextToken("("); Vector3 p2(string::to_float(tok.nextToken()), string::to_float(tok.nextToken()), string::to_float(tok.nextToken())); tok.assertNextToken(")"); tok.assertNextToken("("); Vector3 p3(string::to_float(tok.nextToken()), string::to_float(tok.nextToken()), string::to_float(tok.nextToken())); tok.assertNextToken(")"); // Construct the plane from the three points Plane3 plane(p1, p2, p3); // Parse TexDef Matrix4 texdef; tok.assertNextToken("("); tok.assertNextToken("("); texdef.xx() = string::to_float(tok.nextToken()); texdef.yx() = string::to_float(tok.nextToken()); texdef.tx() = string::to_float(tok.nextToken()); tok.assertNextToken(")"); tok.assertNextToken("("); texdef.xy() = string::to_float(tok.nextToken()); texdef.yy() = string::to_float(tok.nextToken()); texdef.ty() = string::to_float(tok.nextToken()); tok.assertNextToken(")"); tok.assertNextToken(")"); // Parse Shader, brushDef has an implicit "textures/" not written to the map std::string shader = "textures/" + tok.nextToken(); // Parse Contents Flags (and ignore them) tok.skipTokens(3); // Finally, add the new face to the brush /*IFace& face = */brush.addFace(plane, texdef, shader); } else { std::string text = (boost::format(_("BrushDefParser: invalid token '%s'")) % token).str(); throw parser::ParseException(text); } } // Final outer "}" tok.assertNextToken("}"); return node; }
void BuildDoorsX2(vec3_t min, vec3_t max, bool bSclMainHor, bool bSclMainVert, bool bSclTrimHor, bool bSclTrimVert, const char* mainTexture, const char* trimTexture, int direction) { int xy; if(direction == 0) xy = 0; else xy = 1; //----- Build Outer Bounds --------- vec3_t v1, v2, v3, v5, v6, v7, ve_1, ve_2, ve_3; VectorCopy(min, v1); VectorCopy(min, v2); VectorCopy(min, v3); VectorCopy(max, v5); VectorCopy(max, v6); VectorCopy(max, v7); v2[0] = max[0]; v3[1] = max[1]; v6[0] = min[0]; v7[1] = min[1]; float width = (max[xy] - min[xy])/2; if(direction == 0) { VectorCopy(v1, ve_1); VectorCopy(v3, ve_2); VectorCopy(v6, ve_3); } else { VectorCopy(v7, ve_1); VectorCopy(v1, ve_2); VectorCopy(v2, ve_3); } ve_1[xy] += width; ve_2[xy] += width; ve_3[xy] += width; //---------------------------------- NodeSmartReference newBrush1(GlobalBrushCreator().createBrush()); NodeSmartReference newBrush2(GlobalBrushCreator().createBrush()); AddFaceWithTexture(newBrush1, v1, v2, v3, "textures/common/caulk", false); AddFaceWithTexture(newBrush1, v5, v7, v6, "textures/common/caulk", false); AddFaceWithTexture(newBrush2, v1, v2, v3, "textures/common/caulk", false); AddFaceWithTexture(newBrush2, v5, v7, v6, "textures/common/caulk", false); if(direction == 0) { AddFaceWithTexture(newBrush1, v1, v3, v6, "textures/common/caulk", false); AddFaceWithTexture(newBrush2, v5, v2, v7, "textures/common/caulk", false); } else { AddFaceWithTexture(newBrush1, v1, v7, v2, "textures/common/caulk", false); AddFaceWithTexture(newBrush2, v5, v6, v3, "textures/common/caulk", false); } if(direction == 0) { AddFaceWithTextureScaled(newBrush1, v1, v7, v2, mainTexture, bSclMainVert, bSclMainHor, min[0], min[2], max[0], max[2]); AddFaceWithTextureScaled(newBrush1, v5, v6, v3, mainTexture, bSclMainVert, bSclMainHor, max[0], min[2], min[0], max[2]); AddFaceWithTextureScaled(newBrush2, v1, v7, v2, mainTexture, bSclMainVert, bSclMainHor, min[0], min[2], max[0], max[2]); AddFaceWithTextureScaled(newBrush2, v5, v6, v3, mainTexture, bSclMainVert, bSclMainHor, max[0], min[2], min[0], max[2]); // flip max/min to reverse tex dir AddFaceWithTextureScaled(newBrush1, ve_3, ve_2, ve_1, trimTexture, bSclTrimVert, bSclTrimHor, min[1], min[2], max[1], max[2]); AddFaceWithTextureScaled(newBrush2, ve_1, ve_2, ve_3, trimTexture, bSclTrimVert, bSclTrimHor, max[1], min[2], min[1], max[2]); } else { AddFaceWithTextureScaled(newBrush1, v1, v3, v6, mainTexture, bSclMainVert, bSclMainHor, min[1], min[2], max[1], max[2]); AddFaceWithTextureScaled(newBrush1, v5, v2, v7, mainTexture, bSclMainVert, bSclMainHor, max[1], min[2], min[1], max[2]); AddFaceWithTextureScaled(newBrush2, v1, v3, v6, mainTexture, bSclMainVert, bSclMainHor, min[1], min[2], max[1], max[2]); AddFaceWithTextureScaled(newBrush2, v5, v2, v7, mainTexture, bSclMainVert, bSclMainHor, max[1], min[2], min[1], max[2]); // flip max/min to reverse tex dir AddFaceWithTextureScaled(newBrush1, ve_1, ve_2, ve_3, trimTexture, bSclTrimVert, bSclTrimHor, min[0], min[2], max[0], max[2]); AddFaceWithTextureScaled(newBrush2, ve_3, ve_2, ve_1, trimTexture, bSclTrimVert, bSclTrimHor, max[0], min[2], min[0], max[2]); } //---------------------------------- EntityClass* doorClass = GlobalEntityClassManager().findOrInsert("func_door", true); NodeSmartReference pEDoor1(GlobalEntityCreator().createEntity(doorClass)); NodeSmartReference pEDoor2(GlobalEntityCreator().createEntity(doorClass)); if(direction == 0) { Node_getEntity(pEDoor1)->setKeyValue("angle", "180"); Node_getEntity(pEDoor2)->setKeyValue("angle", "360"); } else { Node_getEntity(pEDoor1)->setKeyValue("angle", "270"); Node_getEntity(pEDoor2)->setKeyValue("angle", "90"); } srand((unsigned)time(NULL)); char teamname[256]; sprintf(teamname, "t%i", rand()); Node_getEntity(pEDoor1)->setKeyValue("team", teamname); Node_getEntity(pEDoor2)->setKeyValue("team", teamname); Node_getTraversable(pEDoor1)->insert(newBrush1); Node_getTraversable(pEDoor2)->insert(newBrush2); Node_getTraversable(GlobalSceneGraph().root())->insert(pEDoor1); Node_getTraversable(GlobalSceneGraph().root())->insert(pEDoor2); // ResetCurrentTexture(); }
scene::INodePtr BrushDef3Parser::parse(parser::DefTokeniser& tok) const { // Create a new brush scene::INodePtr node = GlobalBrushCreator().createBrush(); // Cast the node, this must succeed IBrushNodePtr brushNode = boost::dynamic_pointer_cast<IBrushNode>(node); assert(brushNode != NULL); IBrush& brush = brushNode->getIBrush(); tok.assertNextToken("{"); // Parse face tokens until a closing brace is encountered while (1) { std::string token = tok.nextToken(); // Token should be either a "(" (start of face) or "}" (end of brush) if (token == "}") { break; // end of brush } else if (token == "(") // FACE { // Construct a plane and parse its values Plane3 plane; plane.normal().x() = string::to_float(tok.nextToken()); plane.normal().y() = string::to_float(tok.nextToken()); plane.normal().z() = string::to_float(tok.nextToken()); plane.dist() = -string::to_float(tok.nextToken()); // negate d tok.assertNextToken(")"); // Parse TexDef Matrix4 texdef; tok.assertNextToken("("); tok.assertNextToken("("); texdef.xx() = string::to_float(tok.nextToken()); texdef.yx() = string::to_float(tok.nextToken()); texdef.tx() = string::to_float(tok.nextToken()); tok.assertNextToken(")"); tok.assertNextToken("("); texdef.xy() = string::to_float(tok.nextToken()); texdef.yy() = string::to_float(tok.nextToken()); texdef.ty() = string::to_float(tok.nextToken()); tok.assertNextToken(")"); tok.assertNextToken(")"); // Parse Shader std::string shader = tok.nextToken(); // Parse Flags (usually each brush has all faces detail or all faces structural) IBrush::DetailFlag flag = static_cast<IBrush::DetailFlag>( string::convert<std::size_t>(tok.nextToken(), IBrush::Structural)); brush.setDetailFlag(flag); // Ignore the other two flags tok.skipTokens(2); // Finally, add the new face to the brush /*IFace& face = */brush.addFace(plane, texdef, shader); } else { std::string text = (boost::format(_("BrushDef3Parser: invalid token '%s'")) % token).str(); throw parser::ParseException(text); } } // Final outer "}" tok.assertNextToken("}"); return node; }
void post(const scene::INodePtr& node) { if (!node->visible()) { return; } Brush* brush = Node_getBrush(node); if (brush != NULL && !Node_isSelected(node)) { BrushNodePtr brushNode = std::dynamic_pointer_cast<BrushNode>(node); // Get the parent of this brush scene::INodePtr parent = node->getParent(); assert(parent != NULL); // parent should not be NULL BrushPtrVector buffer[2]; std::size_t swap = 0; BrushNodePtr original = std::dynamic_pointer_cast<BrushNode>(brushNode->clone()); //Brush* original = new Brush(*brush); buffer[swap].push_back(original); // Iterate over all selected brushes for (BrushPtrVector::const_iterator i(_brushlist.begin()); i != _brushlist.end(); ++i) { for (BrushPtrVector::iterator j(buffer[swap].begin()); j != buffer[swap].end(); ++j) { if (Brush_subtract(*j, (*i)->getBrush(), buffer[1 - swap])) { // greebo: Delete not necessary, nodes get deleted automatically by clear() below // delete (*j); } else { buffer[1 - swap].push_back(*j); } } buffer[swap].clear(); swap = 1 - swap; } BrushPtrVector& out = buffer[swap]; if (out.size() == 1 && out.back() == original) { // greebo: shared_ptr is taking care of this //delete original; } else { _before++; for (BrushPtrVector::const_iterator i = out.begin(); i != out.end(); ++i) { _after++; scene::INodePtr newBrush = GlobalBrushCreator().createBrush(); parent->addChildNode(newBrush); // Move the new Brush to the same layers as the source node newBrush->assignToLayers(node->getLayers()); (*i)->getBrush().removeEmptyFaces(); ASSERT_MESSAGE(!(*i)->getBrush().empty(), "brush left with no faces after subtract"); Node_getBrush(newBrush)->copy((*i)->getBrush()); } _deleteList.push_back(node); } } }