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);
        }
Exemple #4
0
        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();
        }