示例#1
0
    def frameStarted(self, evt):
        OgreBites.ApplicationContext.frameStarted(self, evt)

        if not self.cam.getViewport().getOverlaysEnabled():
            return True

        self.time = evt.timeSinceLastFrame
        self.Player.actualiza(self.time)

        OgreBites.ApplicationContext.frameStarted(self, evt)

        OgreOverlay.ImGuiOverlay.NewFrame(evt)

        if OgreOverlay.BeginMainMenuBar():

            if OgreOverlay.BeginMenu("Help"):
                if OgreOverlay.MenuItem("About"):
                    self.show_about = True
                OgreOverlay.EndMenu()

            OgreOverlay.EndMainMenuBar()

        if self.show_about:
            self.draw_about()

        return True
示例#2
0
 def draw_about(self):
     flags = OgreOverlay.ImGuiWindowFlags_AlwaysAutoResize
     self.show_about = OgreOverlay.Begin("About OgreMeshViewer",
                                         self.show_about, flags)[1]
     OgreOverlay.Text("By Pavel Rojtberg")
     OgreOverlay.Text(
         "OgreMeshViewer is licensed under the MIT License, see LICENSE for more information."
     )
     OgreOverlay.Separator()
     OgreOverlay.BulletText("Ogre:  %s" % Ogre.__version__)
     OgreOverlay.BulletText("imgui: %s" % OgreOverlay.GetVersion())
     OgreOverlay.End()
    def draw_loading(self):
        win = self.app.getRenderWindow()
        ImGui.SetNextWindowPos(
            ImGui.ImVec2(win.getWidth() * 0.5,
                         win.getHeight() * 0.5), 0, ImGui.ImVec2(0.5, 0.5))

        flags = ImGui.ImGuiWindowFlags_NoTitleBar | ImGui.ImGuiWindowFlags_NoResize | ImGui.ImGuiWindowFlags_NoSavedSettings
        ImGui.Begin("Loading", True, flags)
        ImGui.Text(self.app.meshname)
        ImGui.Separator()
        ImGui.Text("Loading..            ")
        ImGui.End()
示例#4
0
 def draw_about(self):
     flags = OgreOverlay.ImGuiWindowFlags_AlwaysAutoResize
     self.show_about = OgreOverlay.Begin("About TiledMap", True, flags)[1]
     OgreOverlay.Text("By arky")
     OgreOverlay.Text(
         "TiledMap is licensed under the MIT License, see LICENSE for more information."
     )
     OgreOverlay.Separator()
     OgreOverlay.BulletText(f"Ogre: {Ogre.__version__}")
     OgreOverlay.BulletText(f"imgui: {OgreOverlay.GetVersion()}")
     OgreOverlay.End()
示例#5
0
    def setup(self):
        OgreBites.ApplicationContext.setup(self)
        self.addInputListener(self)

        self.restart = False
        imgui_overlay = OgreOverlay.ImGuiOverlay()
        OgreOverlay.GetIO().IniFilename = self.getFSLayer().getWritablePath(
            "imgui.ini")

        root = self.getRoot()
        scn_mgr = root.createSceneManager()
        scn_mgr.addRenderQueueListener(self.getOverlaySystem())
        self.scn_mgr = scn_mgr

        # set listener to deal with missing materials
        self.mat_creator = MaterialCreator()
        Ogre.MeshManager.getSingleton().setListener(self.mat_creator)

        # for picking
        self.ray_query = scn_mgr.createRayQuery(Ogre.Ray())

        #imgui_overlay.addFont("SdkTrays/Value", RGN_MESHVIEWER)
        imgui_overlay.show()
        OgreOverlay.OverlayManager.getSingleton().addOverlay(imgui_overlay)
        imgui_overlay.disown()  # owned by OverlayMgr now

        shadergen = OgreRTShader.ShaderGenerator.getSingleton()
        shadergen.addSceneManager(
            scn_mgr)  # must be done before we do anything with the scene

        scn_mgr.setAmbientLight(Ogre.ColourValue(.1, .1, .1))

        self.highlight_mat = Ogre.MaterialManager.getSingleton().create(
            "Highlight", RGN_MESHVIEWER)
        self.highlight_mat.getTechniques()[0].getPasses()[0].setEmissive(
            Ogre.ColourValue(1, 1, 0))

        self.entity = scn_mgr.createEntity(self.meshname)
        scn_mgr.getRootSceneNode().createChildSceneNode().attachObject(
            self.entity)

        diam = self.entity.getBoundingBox().getSize().length()

        axes_node = scn_mgr.getRootSceneNode().createChildSceneNode()
        axes_node.getDebugRenderable(
        )  # make sure Ogre/Debug/AxesMesh is created
        self.axes = scn_mgr.createEntity("Ogre/Debug/AxesMesh")
        axes_node.attachObject(self.axes)
        axes_node.setScale(Ogre.Vector3(diam / 4))
        self.axes.setVisible(False)
        self.axes.setQueryFlags(0)  # exclude from picking

        self.cam = scn_mgr.createCamera("myCam")
        self.cam.setNearClipDistance(diam * 0.01)
        self.cam.setAutoAspectRatio(True)
        camnode = scn_mgr.getRootSceneNode().createChildSceneNode()
        camnode.attachObject(self.cam)

        light = scn_mgr.createLight("MainLight")
        light.setType(Ogre.Light.LT_DIRECTIONAL)
        light.setSpecularColour(Ogre.ColourValue.White)
        camnode.attachObject(light)

        vp = self.getRenderWindow().addViewport(self.cam)
        vp.setBackgroundColour(Ogre.ColourValue(.3, .3, .3))

        self.camman = OgreBites.CameraMan(camnode)
        self.camman.setStyle(OgreBites.CS_ORBIT)
        self.camman.setYawPitchDist(Ogre.Radian(0), Ogre.Radian(0.3), diam)
        self.camman.setFixedYaw(False)

        self.imgui_input = OgreBites.ImGuiInputListener()
        self.input_dispatcher = OgreBites.InputListenerChain(
            [self.imgui_input, self.camman])
        self.addInputListener(self.input_dispatcher)
示例#6
0
def show_vertex_decl(decl):
    OgreOverlay.Columns(2)
    OgreOverlay.Text("Semantic")
    OgreOverlay.NextColumn()
    OgreOverlay.Text("Type")
    OgreOverlay.NextColumn()
    OgreOverlay.Separator()

    for e in decl.getElements():
        OgreOverlay.Text(VES2STR[e.getSemantic()])
        OgreOverlay.NextColumn()
        try:
            OgreOverlay.Text(VET2STR[e.getType()])
        except IndexError:
            OgreOverlay.Text("TODO")
        OgreOverlay.NextColumn()

    OgreOverlay.Columns(1)
示例#7
0
    def frameStarted(self, evt):
        OgreBites.ApplicationContext.frameStarted(self, evt)

        if not self.cam.getViewport().getOverlaysEnabled():
            return True

        OgreOverlay.ImGuiOverlay.NewFrame(evt)

        if OgreOverlay.BeginMainMenuBar():
            if OgreOverlay.BeginMenu("File"):
                if OgreOverlay.MenuItem("Select Renderer"):
                    self.getRoot().queueEndRendering()
                    self.restart = True
                if OgreOverlay.MenuItem("Save Screenshot", "P"):
                    self._save_screenshot()
                if OgreOverlay.MenuItem("Quit", "Esc"):
                    self.getRoot().queueEndRendering()
                OgreOverlay.EndMenu()
            if OgreOverlay.BeginMenu("View"):
                enode = self.entity.getParentSceneNode()
                if OgreOverlay.MenuItem("Show Axes", "A",
                                        self.axes.getVisible()):
                    self._toggle_axes()
                if OgreOverlay.MenuItem("Show Bounding Box", "B",
                                        enode.getShowBoundingBox()):
                    self._toggle_bbox()
                if self.entity.hasSkeleton() and OgreOverlay.MenuItem(
                        "Show Skeleton", None,
                        self.entity.getDisplaySkeleton()):
                    self.entity.setDisplaySkeleton(
                        not self.entity.getDisplaySkeleton())
                OgreOverlay.EndMenu()

            if OgreOverlay.BeginMenu("Help"):
                if OgreOverlay.MenuItem("Metrics", None, self.show_metrics):
                    self.show_metrics = not self.show_metrics
                if OgreOverlay.MenuItem("About"):
                    self.show_about = True
                OgreOverlay.EndMenu()

            OgreOverlay.EndMainMenuBar()

        if self.show_about:
            self.draw_about()

        if self.show_metrics:
            self.draw_metrics()

        # Mesh Info Sidebar
        mesh = Ogre.MeshManager.getSingleton().getByName(self.meshname)

        OgreOverlay.SetNextWindowPos(OgreOverlay.ImVec2(0, 30))
        flags = OgreOverlay.ImGuiWindowFlags_NoTitleBar \
              | OgreOverlay.ImGuiWindowFlags_NoMove
        OgreOverlay.Begin("MeshProps", None, flags)
        OgreOverlay.Text(self.meshname)

        highlight = -1

        if OgreOverlay.CollapsingHeader("Geometry"):
            if mesh.sharedVertexData:
                if OgreOverlay.TreeNode("Shared Vertices: {}".format(
                        mesh.sharedVertexData.vertexCount)):
                    show_vertex_decl(mesh.sharedVertexData.vertexDeclaration)
                    TreePop()
            else:
                OgreOverlay.Text("Shared Vertices: None")

            for i, sm in enumerate(mesh.getSubMeshes()):
                submesh_details = OgreOverlay.TreeNode("SubMesh #{}".format(i))
                if OgreOverlay.IsItemHovered():
                    highlight = i

                if submesh_details:
                    OgreOverlay.BulletText("Material: {}".format(
                        sm.getMaterialName()))
                    if sm.indexData:
                        bits = sm.indexData.indexBuffer.getIndexSize() * 8
                        OgreOverlay.BulletText("Indices: {} ({} bit)".format(
                            sm.indexData.indexCount, bits))
                    else:
                        OgreOverlay.BulletText("Indices: None")

                    if sm.vertexData:
                        if OgreOverlay.TreeNode("Vertices: {}".format(
                                sm.vertexData.vertexCount)):
                            show_vertex_decl(sm.vertexData.vertexDeclaration)
                            OgreOverlay.TreePop()
                    else:
                        OgreOverlay.BulletText("Vertices: shared")
                    OgreOverlay.TreePop()

        if self.highlighted > -1:
            self.entity.getSubEntities()[self.highlighted].setMaterialName(
                self.orig_mat)

        if highlight > -1:
            self.orig_mat = self.entity.getSubEntities(
            )[highlight].getMaterial().getName()
            self.entity.getSubEntities()[highlight].setMaterial(
                self.highlight_mat)
            self.highlighted = highlight

        animations = self.entity.getAllAnimationStates()
        if animations is not None and OgreOverlay.CollapsingHeader(
                "Animations"):
            controller_mgr = Ogre.ControllerManager.getSingleton()

            if self.entity.hasSkeleton():
                OgreOverlay.Text("Skeleton: {}".format(mesh.getSkeletonName()))
                # self.entity.setUpdateBoundingBoxFromSkeleton(True)
            if mesh.hasVertexAnimation():
                OgreOverlay.Text("Vertex Animations")

            for name, astate in animations.getAnimationStates().items():
                if OgreOverlay.TreeNode(name):
                    if astate.getEnabled():
                        if OgreOverlay.Button("Reset"):
                            astate.setEnabled(False)
                            astate.setTimePosition(0)
                            if name in self.active_controllers:
                                controller_mgr.destroyController(
                                    self.active_controllers[name])
                    elif OgreOverlay.Button("Play"):
                        astate.setEnabled(True)
                        self.active_controllers[
                            name] = controller_mgr.createFrameTimePassthroughController(
                                Ogre.AnimationStateControllerValue.create(
                                    astate, True))
                    changed = False
                    if astate.getLength() > 0:
                        OgreOverlay.SameLine()
                        changed, value = OgreOverlay.SliderFloat(
                            "", astate.getTimePosition(), 0,
                            astate.getLength(), "%.3fs")
                    if changed:
                        astate.setEnabled(True)
                        astate.setTimePosition(value)
                    OgreOverlay.TreePop()

        if OgreOverlay.CollapsingHeader("Bounds"):
            bounds = mesh.getBounds()
            s = bounds.getSize()
            OgreOverlay.BulletText("Size: {:.2f}, {:.2f}, {:.2f}".format(
                s[0], s[1], s[2]))
            c = bounds.getCenter()
            OgreOverlay.BulletText("Center: {:.2f}, {:.2f}, {:.2f}".format(
                c[0], c[1], c[2]))
            OgreOverlay.BulletText("Radius: {:.2f}".format(
                mesh.getBoundingSphereRadius()))

        OgreOverlay.End()

        # ShowDemoWindow()

        return True
示例#8
0
    def draw_metrics(self):
        win = self.getRenderWindow()
        stats = win.getStatistics()

        OgreOverlay.SetNextWindowPos(
            OgreOverlay.ImVec2(win.getWidth() - 10,
                               win.getHeight() - 10),
            OgreOverlay.ImGuiCond_Always, OgreOverlay.ImVec2(1, 1))
        OgreOverlay.SetNextWindowBgAlpha(0.3)
        flags = OgreOverlay.ImGuiWindowFlags_NoMove \
              | OgreOverlay.ImGuiWindowFlags_NoTitleBar \
              | OgreOverlay.ImGuiWindowFlags_NoResize \
              | OgreOverlay.ImGuiWindowFlags_AlwaysAutoResize \
              | OgreOverlay.ImGuiWindowFlags_NoSavedSettings \
              | OgreOverlay.ImGuiWindowFlags_NoFocusOnAppearing \
              | OgreOverlay.ImGuiWindowFlags_NoNav
        self.show_metrics = OgreOverlay.Begin("Metrics", self.show_metrics,
                                              flags)[1]
        OgreOverlay.Text("Metrics")
        OgreOverlay.Separator()
        OgreOverlay.Text("Average FPS: {:.2f}".format(stats.avgFPS))
        OgreOverlay.Text("Batches: {}".format(stats.batchCount))
        OgreOverlay.Text("Triangles: {}".format(stats.triangleCount))
        OgreOverlay.End()
示例#9
0
    def setup(self):
        # SETUP es la primera función a la que se llama
        # Primero llamamos a la base y ponemos el listener
        OgreBites.ApplicationContext.setup(self)
        #Ahora se llama a locate resources
        self.addInputListener(self)
        #imgui_overlay = ImGuiOverlay()

        self.restart = False

        imgui_overlay = OgreOverlay.ImGuiOverlay()
        OgreOverlay.GetIO().IniFilename = self.getFSLayer().getWritablePath(
            "imgui.ini")

        #Inicializamos ogre u hacemos un puntero a Root
        root = self.getRoot()

        #Creamos el scene manager
        scn_mgr = root.createSceneManager()
        scn_mgr.addRenderQueueListener(self.getOverlaySystem())
        self.scn_mgr = scn_mgr

        imgui_overlay.show()
        OgreOverlay.OverlayManager.getSingleton().addOverlay(imgui_overlay)
        imgui_overlay.disown()  # owned by OverlayMgr now

        # Creamos el Shader y definimos las sombras
        shadergen = OgreRTShader.ShaderGenerator.getSingleton()
        shadergen.addSceneManager(scn_mgr)
        scn_mgr.setShadowTechnique(Ogre.Ogre.SHADOWTYPE_TEXTURE_MODULATIVE)
        #scn_mgr.setShadowTechnique(Ogre.Ogre.SHADOWTYPE_TEXTURE_ADDITIVE)
        #scn_mgr.setShadowTechnique(Ogre.Ogre.SHADOWTYPE_STENCIL_MODULATIVE)
        scn_mgr.setShadowDirLightTextureOffset(1)
        scn_mgr.setShadowFarDistance(200)
        #para que los objetos emitan shadow sobre si mismos
        scn_mgr.setShadowTextureSelfShadow(True)

        #skybox and distance of the skybox
        #scn_mgr.setSkyBox(True,"Skyes/Night1",100)
        scn_mgr.setSkyDome(True, "Skyes/Night1", 50, 5)
        #scn_mgr.setSkyDome(True,"Examples/SpaceSkyPlane",5,8)

        #lets set a fog
        #Fadecolor=Ogre.ColourValue(0,0,0)
        #vp.setBackgroundColour(Fadecolor)
        #scn_mgr.setFog(Ogre.Ogre.FOG_LINEAR,Fadecolor,0,600,900)

        #Creamos el mapa
        #mapa=Ogretmxmap.tmxmap("Maps/cathedral.tmx")
        mapa = Ogretmxmap.tmxmap("resources/tiled/cathedral.tmx")
        mannode = scn_mgr.getRootSceneNode().createChildSceneNode()
        mannode.setPosition(0, 0, 0)
        mapa.createmap(scn_mgr)

        # Vamos a crear el nodo perteneciente al personaje
        Playernode = scn_mgr.getRootSceneNode().createChildSceneNode()
        #Playernode.setPosition(self.pos)
        self.Playernode = Playernode
        # Creo el player y lo fusiono con su nodo
        self.Player = Player.Player(Playernode)
        self.Player.mapa = mapa
        self.Player.setpos(10, 10, 0)

        # Creamos la camara y la posicionamos en el personaje
        camNode = Playernode.createChildSceneNode()
        camNode.setPosition(0, 1.5, 0)
        self.cam = scn_mgr.createCamera("MainCam")
        #camNode.setPosition(0, 0, 80)
        camNode.lookAt(Ogre.Vector3(300, 1.5, 0), Ogre.Node.TS_WORLD)
        self.cam.setNearClipDistance(.2)
        camNode.attachObject(self.cam)
        vp = self.getRenderWindow().addViewport(self.cam)
        vp.setBackgroundColour(Ogre.ColourValue(0, 0, 0))
        self.cam.setAspectRatio((vp.getActualWidth()) / (vp.getActualHeight()))

        self.camNode = camNode

        # Setup the scene
        #night light
        scn_mgr.setAmbientLight(Ogre.ColourValue(.1, .1, .1))

        dirlight = scn_mgr.createLight("MoonLight1")
        dirlight.setType(Ogre.Light.LT_DIRECTIONAL)
        dirlight.setDiffuseColour(Ogre.ColourValue(0, .1, .7))
        dirlight.setSpecularColour(Ogre.ColourValue(0, 0, .5))
        dirlight.setDirection(-0.5, -0.5, -0.3)

        #        spotlight=scn_mgr.createLight("MoonLight2")
        #        spotlight.setType(Ogre.Light.LT_SPOTLIGHT);
        #        spotlight.setDiffuseColour(Ogre.ColourValue(.02, .2, .9));
        #        spotlight.setSpecularColour(Ogre.ColourValue(0, 0, .5))
        #        spotlight.setSpotlightInnerAngle(Ogre.Radian(0.09))
        #        spotlight.setSpotlightOuterAngle(Ogre.Radian(3))
        #        spotlight.setSpotlightFalloff(.0)
        #        spotLightNode = Playernode.createChildSceneNode()
        #        spotLightNode.setPosition(Ogre.Vector3(3, 3, 3))
        #        spotlight.setDirection(0, -1, -0.7)
        #        spotLightNode.attachObject(spotlight)
        #spotlight.setCastShadows(True)

        pointLight = scn_mgr.createLight("PointLight")
        pointLight.setType(Ogre.Light.LT_POINT)
        pointLight.setDiffuseColour(1, 1, 1)
        pointLight.setSpecularColour(1, 1, 1)
        pointLightNode = Playernode.createChildSceneNode()
        pointLightNode.attachObject(pointLight)
        pointLightNode.setPosition(0, 1.5, 0)
        pointLight.setAttenuation(100, 1, 0.045, 0.0075)

        #Daylight, esta tecnica de sombreado queda mucho mejor
        #        scn_mgr.setShadowTechnique(Ogre.Ogre.SHADOWTYPE_TEXTURE_ADDITIVE)
        #        scn_mgr.setAmbientLight(Ogre.ColourValue(.2, .2, .2))
        #        light=scn_mgr.createLight("MainLight")
        #        light.setType(Ogre.Light.LT_DIRECTIONAL);
        #        light.setDiffuseColour(Ogre.ColourValue(.6, .6, 1));
        #        light.setSpecularColour(Ogre.ColourValue(.6, .6, 1))
        #        light.setDirection(1, -0.5, 0.5)

        #        lightNode = scn_mgr.getRootSceneNode().createChildSceneNode()
        #        lightNode.attachObject(light)
        #        lightNode.setPosition(0, 3, 0)

        self.mapa = mapa

        self.cam.getViewport().setOverlaysEnabled(True)
        #self.mtraymanager=OgreBites.TrayManager("Interface",self.getRenderWindow())
        #self.mtraymanager.createLabel(OgreBites.TL_TOP,"TInfo","",350)

        self.imgui_input = OgreBites.ImGuiInputListener()
        self.input_dispatcher = OgreBites.InputListenerChain(
            [self.imgui_input])
        self.addInputListener(self.input_dispatcher)
示例#10
0
    def draw(self):
        if not self.show:
            return

        ImGui.SetNextWindowSize(ImGui.ImVec2(500, 400),
                                ImGui.ImGuiCond_FirstUseEver)
        self.show = ImGui.Begin("Log", self.show)[1]

        ImGui.PushFont(self.font)
        for msg, lvl in self.items:
            if lvl == 4:
                ImGui.PushStyleColor(ImGui.ImGuiCol_Text,
                                     ImGui.ImVec4(1, 0.4, 0.4, 1))
            elif lvl == 3:
                ImGui.PushStyleColor(ImGui.ImGuiCol_Text,
                                     ImGui.ImVec4(1, 0.8, 0.4, 1))
            ImGui.TextWrapped(msg)
            if lvl > 2:
                ImGui.PopStyleColor()
        ImGui.PopFont()
        ImGui.End()
示例#11
0
def show_vertex_decl(decl):
    ImGui.Columns(2)
    ImGui.Text("Semantic")
    ImGui.NextColumn()
    ImGui.Text("Type")
    ImGui.NextColumn()
    ImGui.Separator()

    for e in decl.getElements():
        ImGui.Text(VES2STR[e.getSemantic()])
        ImGui.NextColumn()
        ImGui.Text(VET2STR[e.getType()])
        ImGui.NextColumn()
    ImGui.Columns(1)
示例#12
0
    def preRenderTargetUpdate(self, evt):
        if not self.app.cam.getViewport().getOverlaysEnabled():
            return

        Ogre.Overlay.ImGuiOverlay.NewFrame()

        entity = self.app.entity

        if entity is None:
            self.draw_loading()
            return

        if ImGui.BeginMainMenuBar():
            if ImGui.BeginMenu("File"):
                if ImGui.MenuItem("Select Renderer"):
                    self.app.getRoot().queueEndRendering()
                    self.app.restart = True
                if ImGui.MenuItem("Save Screenshot", "P"):
                    self.app._save_screenshot()
                if ImGui.MenuItem("Quit", "Esc"):
                    self.app.getRoot().queueEndRendering()
                ImGui.EndMenu()
            if ImGui.BeginMenu("View"):
                enode = entity.getParentSceneNode()
                if ImGui.MenuItem("Show Axes", "A", self.app.axes_visible):
                    self.app._toggle_axes()
                if ImGui.MenuItem("Show Bounding Box", "B",
                                  enode.getShowBoundingBox()):
                    self.app._toggle_bbox()
                if entity.hasSkeleton() and ImGui.MenuItem(
                        "Show Skeleton", None, entity.getDisplaySkeleton()):
                    entity.setDisplaySkeleton(not entity.getDisplaySkeleton())
                ImGui.EndMenu()

            if ImGui.BeginMenu("Help"):
                if ImGui.MenuItem("Metrics", None, self.show_metrics):
                    self.show_metrics = not self.show_metrics
                if ImGui.MenuItem("Log"):
                    self.logwin.show = True
                if ImGui.MenuItem("About"):
                    self.show_about = True
                ImGui.EndMenu()

            ImGui.EndMainMenuBar()

        if self.show_about:
            self.draw_about()

        if self.show_metrics:
            self.draw_metrics()

        # Mesh Info Sidebar
        mesh = entity.getMesh()

        ImGui.SetNextWindowSize(ImGui.ImVec2(300, 500),
                                ImGui.ImGuiCond_FirstUseEver)
        ImGui.SetNextWindowPos(ImGui.ImVec2(0, 30))
        flags = ImGui.ImGuiWindowFlags_NoTitleBar | ImGui.ImGuiWindowFlags_NoMove
        ImGui.Begin("MeshProps", None, flags)
        ImGui.Text(mesh.getName())

        highlight = -1

        if ImGui.CollapsingHeader("Geometry"):
            if mesh.sharedVertexData:
                if ImGui.TreeNode("Shared Vertices: {}".format(
                        mesh.sharedVertexData.vertexCount)):
                    show_vertex_decl(mesh.sharedVertexData.vertexDeclaration)
                    ImGui.TreePop()
            else:
                ImGui.Text("Shared Vertices: None")

            for i, sm in enumerate(mesh.getSubMeshes()):
                submesh_details = ImGui.TreeNode("SubMesh #{}".format(i))
                if ImGui.IsItemHovered():
                    highlight = i

                if submesh_details:
                    ImGui.BulletText("Material: {}".format(
                        sm.getMaterialName()))
                    op = ROP2STR[
                        sm.
                        operationType] if sm.operationType <= 6 else "Control Points"
                    ImGui.BulletText("Operation: {}".format(op))

                    if sm.indexData.indexCount:
                        bits = sm.indexData.indexBuffer.getIndexSize() * 8
                        ImGui.BulletText("Indices: {} ({} bit)".format(
                            sm.indexData.indexCount, bits))
                    else:
                        ImGui.BulletText("Indices: None")

                    if sm.vertexData:
                        if ImGui.TreeNode("Vertices: {}".format(
                                sm.vertexData.vertexCount)):
                            show_vertex_decl(sm.vertexData.vertexDeclaration)
                            ImGui.TreePop()
                    else:
                        ImGui.BulletText("Vertices: shared")
                    ImGui.TreePop()

        if self.highlighted > -1:
            entity.getSubEntities()[self.highlighted].setMaterialName(
                self.orig_mat)

        if highlight > -1:
            self.orig_mat = entity.getSubEntities()[highlight].getMaterial(
            ).getName()
            entity.getSubEntities()[highlight].setMaterial(
                self.app.highlight_mat)
            self.highlighted = highlight

        animations = entity.getAllAnimationStates()
        if animations is not None and ImGui.CollapsingHeader("Animations"):
            controller_mgr = Ogre.ControllerManager.getSingleton()

            if entity.hasSkeleton():
                ImGui.Text("Skeleton: {}".format(mesh.getSkeletonName()))
                # self.entity.setUpdateBoundingBoxFromSkeleton(True)
            if mesh.hasVertexAnimation():
                ImGui.Text("Vertex Animations")

            for name, astate in animations.getAnimationStates().items():
                if ImGui.TreeNode(name):
                    if astate.getEnabled():
                        if ImGui.Button("Reset"):
                            astate.setEnabled(False)
                            astate.setTimePosition(0)
                            if name in self.app.active_controllers:
                                controller_mgr.destroyController(
                                    self.app.active_controllers[name])
                    elif ImGui.Button("Play"):
                        astate.setEnabled(True)
                        self.app.active_controllers[
                            name] = controller_mgr.createFrameTimePassthroughController(
                                Ogre.AnimationStateControllerValue.create(
                                    astate, True))
                    changed = False
                    if astate.getLength() > 0:
                        ImGui.SameLine()
                        changed, value = ImGui.SliderFloat(
                            "", astate.getTimePosition(), 0,
                            astate.getLength(), "%.3fs")
                    if changed:
                        astate.setEnabled(True)
                        astate.setTimePosition(value)
                    ImGui.TreePop()

        lod_count = mesh.getNumLodLevels()
        if lod_count > 1 and ImGui.CollapsingHeader("LOD levels"):
            entity.setMeshLodBias(1)  # reset LOD override
            strategy = mesh.getLodStrategy().getName()
            curr_idx = entity.getCurrentLodIndex()
            ImGui.Text("Strategy: {}".format(strategy))
            for i in range(lod_count):
                txt = "Base Mesh" if i == 0 else "Level {}: {:.2f}".format(
                    i,
                    mesh.getLodLevel(i).userValue)
                ImGui.Bullet()
                ImGui.Selectable(txt, i == curr_idx)
                if ImGui.IsItemHovered():
                    # force this LOD level
                    entity.setMeshLodBias(1, i, i)

        if ImGui.CollapsingHeader("Bounds"):
            bounds = mesh.getBounds()
            s = bounds.getSize()
            ImGui.BulletText("Size: {:.2f}, {:.2f}, {:.2f}".format(
                s[0], s[1], s[2]))
            c = bounds.getCenter()
            ImGui.BulletText("Center: {:.2f}, {:.2f}, {:.2f}".format(
                c[0], c[1], c[2]))
            ImGui.BulletText("Radius: {:.2f}".format(
                mesh.getBoundingSphereRadius()))

        ImGui.End()

        self.logwin.draw()