const Model::EntityList ReparentBrushesCommand::emptyParents() const { Model::EntitySet result; Model::BrushParentMap::const_iterator it, end; for (it = m_oldParents.begin(), end = m_oldParents.end(); it != end; ++it) { Model::Entity& entity = *it->second; if (!entity.worldspawn() && entity.brushes().empty()) result.insert(&entity); } return Utility::makeList(result); }
// find links in a "context" void EntityLinkDecorator::gatherLinks(Vec4f::List& vListLocal, Vec4f::List& vListContext, RenderContext& context, Model::Entity& curEnt, Model::EntitySet& visitedEntities) { Model::EntitySet::iterator vIt = visitedEntities.lower_bound(&curEnt); if (*vIt == &curEnt) return; visitedEntities.insert(vIt, &curEnt); if (!context.filter().entityVisible(curEnt)) return; Model::EntityList::const_iterator it, end; const Model::EntityList& targetList = curEnt.linkTargets(); for (it = targetList.begin(), end = targetList.end(); it != end; ++it) { Model::Entity& targetEnt = **it; if (!context.filter().entityVisible(targetEnt)) continue; if (curEnt.selected() || targetEnt.selected()) addArrowVerts(vListLocal, curEnt.center(), targetEnt.center()); else addArrowVerts(vListContext, curEnt.center(), targetEnt.center()); gatherLinks(vListLocal, vListContext, context, targetEnt, visitedEntities); } const Model::EntityList& sourceList = curEnt.linkSources(); for (it = sourceList.begin(), end = sourceList.end(); it != end; ++it) { Model::Entity& sourceEnt = **it; if (!context.filter().entityVisible(sourceEnt)) continue; gatherLinks(vListLocal, vListContext, context, sourceEnt, visitedEntities); } }
void EntityLinkDecorator::render(Vbo& vbo, RenderContext& context) { if (context.viewOptions().linkDisplayMode() == View::ViewOptions::LinkDisplayNone) return; const Model::EntityList& entities = map().entities(); if (entities.empty()) return; SetVboState activateVbo(vbo, Vbo::VboActive); if (m_doRebuild) { delete m_vertexArray; m_vertexArray = NULL; m_doRebuild = false; // for keeping track of which entities have already been visited by the link-gathering algorithm - should this be part of each entity instead ? Model::EntitySet visitedEntities; Vec4f::List vertsLocal; // links directly connected to a selected entity Vec4f::List vertsContext; // links not directly connected, but in the same context Vec4f::List vertsUnrelated; // links not related to the current selection Model::EntityList::const_iterator it, end; // first pass, outputs local or local+context links for (it = entities.begin(), end = entities.end(); it != end; ++it) { Model::Entity& entity = **it; if (entity.selected()) { if (context.viewOptions().linkDisplayMode() == View::ViewOptions::LinkDisplayLocal) { gatherLinksLocal(vertsLocal, context, entity); } else { gatherLinks(vertsLocal, vertsContext, context, entity, visitedEntities); } } } // second pass, only used in "display all" mode, outputs target links of entities the first pass didn't visit if (context.viewOptions().linkDisplayMode() == View::ViewOptions::LinkDisplayAll) { Model::EntitySet::const_iterator vIt; for (it = entities.begin(), end = entities.end(); it != end; ++it) { Model::Entity& entity = **it; vIt = visitedEntities.lower_bound( &entity ); if( *vIt != &entity ) gatherLinksUnrelated(vertsUnrelated, context, entity); } } unsigned int vertexCount = static_cast<unsigned int>(vertsLocal.size() + vertsContext.size() + vertsUnrelated.size()); if (vertexCount == 0) return; //FIXME : doesn't need to be a color4f at the moment m_vertexArray = new VertexArray(vbo, GL_LINES, vertexCount, Attribute::position3f(), Attribute::color4f(), 0); SetVboState mapVbo(vbo, Vbo::VboMapped); // draw order : unrelated -> context -> local // vertData.y sets the type of link for the shader ( 0 = unrelated, 0.5 = context, 1.0 = local ) Vec4f vertData(1.0f); vertData.y = 0.0f; for (int i = 0; i != vertsUnrelated.size(); ++i ) { vertData.x = vertsUnrelated[i].w; m_vertexArray->addAttribute(Vec3f(vertsUnrelated[i].x, vertsUnrelated[i].y, vertsUnrelated[i].z)); m_vertexArray->addAttribute(vertData); } vertData.y = 0.5f; for (int i = 0; i != vertsContext.size(); ++i) { vertData.x = vertsContext[i].w; m_vertexArray->addAttribute(Vec3f(vertsContext[i].x, vertsContext[i].y, vertsContext[i].z)); m_vertexArray->addAttribute(vertData); } vertData.y = 1.0f; for (int i = 0; i != vertsLocal.size(); ++i) { vertData.x = vertsLocal[i].w; m_vertexArray->addAttribute(Vec3f(vertsLocal[i].x, vertsLocal[i].y, vertsLocal[i].z)); m_vertexArray->addAttribute(vertData); } m_valid = true; } if (!m_valid || m_vertexArray == NULL) return; ActivateShader shader(context.shaderManager(), Shaders::EntityLinkShader ); shader.currentShader().setUniformVariable("CameraPosition", context.camera().position()); //shader.currentShader().setUniformVariable("Color", m_color); // unused at the moment, make color view-prefs for the different types of links ? shader.currentShader().setUniformVariable("Occluded", 1.0f); // render the "occluded" portion without depth-test glLineWidth(2.0f); glDepthMask(GL_FALSE); glDisable(GL_DEPTH_TEST); m_vertexArray->render(); shader.currentShader().setUniformVariable("Occluded", 0.0f); glEnable(GL_DEPTH_TEST); m_vertexArray->render(); glDepthMask(GL_TRUE); glLineWidth(1.0f); }
void NavBar::updateBreadcrump() { m_navPanel->DestroyChildren(); wxSizer* sizer = new wxBoxSizer(wxHORIZONTAL); if (m_documentViewHolder.valid()) { Controller::InputController& inputController = m_documentViewHolder.view().inputController(); Model::EditStateManager& editStateManager = m_documentViewHolder.document().editStateManager(); Model::EntitySet entities = Utility::makeSet(editStateManager.selectedEntities()); const Model::BrushList& brushes = editStateManager.selectedBrushes(); const Model::FaceList& faces = editStateManager.selectedFaces(); size_t totalEntityBrushCount = 0; Model::BrushList::const_iterator brushIt, brushEnd; for (brushIt = brushes.begin(), brushEnd = brushes.end(); brushIt != brushEnd; ++brushIt) { const Model::Brush& brush = **brushIt; Model::Entity* entity = brush.entity(); entities.insert(entity); } Model::EntitySet::const_iterator entityIt, entityEnd; for (entityIt = entities.begin(), entityEnd = entities.end(); entityIt != entityEnd; ++entityIt) { const Model::Entity& entity = **entityIt; totalEntityBrushCount += entity.brushes().size(); } if (entities.empty() && brushes.empty()) { if (faces.empty()) { sizer->Add(makeBreadcrump(wxT("no selection"), false), 0, wxALIGN_CENTRE_VERTICAL); } else { Model::FaceList::const_iterator faceIt = faces.begin(); Model::FaceList::const_iterator faceEnd = faces.end(); const Model::Face* face = *faceIt++; const String& firstTextureName = face->textureName(); bool sameTexturename = true; while (faceIt != faceEnd && sameTexturename) { face = *faceIt++; const String& textureName = face->textureName(); sameTexturename = (textureName == firstTextureName); } wxString faceString; faceString << faces.size() << " " << (faces.size() == 1 ? "face" : "faces"); if (sameTexturename) faceString << " (" << (firstTextureName.empty() ? "no texture set" : firstTextureName) << ")"; else faceString << " (multiple textures)"; sizer->Add(makeBreadcrump(faceString, false), 0, wxALIGN_CENTRE_VERTICAL); } } else { if (entities.size() == 1 && (*entities.begin())->worldspawn()) { const Model::Entity& entity = **entities.begin(); const String classname = entity.classname() != NULL ? *entity.classname() : Model::Entity::NoClassnameValue; sizer->Add(makeBreadcrump(classname, false), 0, wxALIGN_CENTRE_VERTICAL); } else { entityIt = entities.begin(); entityEnd = entities.end(); const Model::Entity* entity = *entityIt++; const String& firstClassname = entity->safeClassname(); bool sameClassname = true; while (entityIt != entityEnd && sameClassname) { entity = *entityIt++; const String& classname = entity->safeClassname(); sameClassname = (classname == firstClassname); } wxString entityString; entityString << entities.size() << " "; if (sameClassname) entityString << firstClassname << " "; entityString << (entities.size() == 1 ? "entity" : "entities"); sizer->Add(makeBreadcrump(entityString, false), 0, wxALIGN_CENTRE_VERTICAL); } if (!brushes.empty()) { sizer->AddSpacer(2); sizer->Add(makeBreadcrump(L"\u00BB", false), 0, wxALIGN_CENTRE_VERTICAL); sizer->AddSpacer(2); wxString brushString; brushString << brushes.size() << "/" << totalEntityBrushCount << (totalEntityBrushCount == 1 ? " brush" : " brushes"); sizer->Add(makeBreadcrump(brushString, false), 0, wxALIGN_CENTRE_VERTICAL); } if (inputController.clipToolActive()) { sizer->AddSpacer(2); sizer->Add(makeBreadcrump(L"\u00BB", false), 0, wxALIGN_CENTRE_VERTICAL); sizer->AddSpacer(2); wxString clipString = "clip tool ("; clipString << inputController.clipTool().numPoints() << "/3 points)"; sizer->Add(makeBreadcrump(clipString, false), 0, wxALIGN_CENTRE_VERTICAL); } else if (inputController.moveVerticesToolActive()) { sizer->AddSpacer(2); sizer->Add(makeBreadcrump(L"\u00BB", false), 0, wxALIGN_CENTRE_VERTICAL); sizer->AddSpacer(2); Controller::MoveVerticesTool& tool = inputController.moveVerticesTool(); wxString vertexString = "vertex tool ("; if (tool.selectedVertexCount() > 0) { vertexString << tool.selectedVertexCount() << "/" << tool.totalVertexCount() << " vertices"; } else if (tool.selectedEdgeCount() > 0) { vertexString << tool.selectedEdgeCount() << "/" << tool.totalEdgeCount() << " edges"; } else if (tool.selectedFaceCount() > 0) { vertexString << tool.selectedFaceCount() << "/" << tool.totalFaceCount() << " faces"; } else { vertexString << "no selection"; } vertexString << ")"; sizer->Add(makeBreadcrump(vertexString, false), 0, wxALIGN_CENTRE_VERTICAL); } } } m_navPanel->SetSizer(sizer); Layout(); }