| Displaying Tagged-ness Updated 02 Mar 2001 | Upper levels: - QuArK Information Base - 3. Advanced customization - 3.4. Plug-Ins - 3.4.1. Plugin Tutorial

3.4.1.5. Displaying Tagged-ness | [ Prev - Up - Next ]

Our plugin still has the weakness that the map doesn't display any information about what side is tagged. Now we'll see how to fix this.

Index

- - Drawing (02 Mar 2001)
- - Tracking the tagged face (14 Feb 2001)

Drawing | tiglari - 02 Mar 2001 | [ Top ]

There's a bit of a problem with this, because tagging.py is already drawing the tagged sides, tho a bit late; to see the effects of what we do we need to go into `plugins\tagging', and comment out the line that says:
    #quarkpy.qbaseeditor.BaseEditor.finishdrawing = tagfinishdrawing
or else
    #quarkpy.mapeditor.MapEditor.finishdrawing = tagfinishdrawing
(At time of writing, the former line is occurring; it might get revised to the latter). To ham up the difference between the standard one and the one we're building, we'll also have the new one draw the tagged face in blue. The technique is again to redefine something, this time a method of a class, `finishdrawing', of `mapeditor', in quarkpy.mapeditor. Finishdrawing operates late in the map-drawing procedure and adds various finishing touches. While writing the tutorial, I noticed that tagging.py was actually redefining fininishdrawing of BaseEditor in quarkpy.qbaseeditor; this is actually not fully correct (tho it's been working fine in QuArK for a long time), since qbaseeditor is supposed to be the base class for both map and model editors, and face-tagging is clearly relevant only to the former. Anyway here's the code for the new procedure:
    def tagfinishdrawing(editor, view, oldfinish=quarkpy.mapeditor.MapEditor.finishdrawing):
        "the new finishdrawing routine"

        oldfinish(editor, view)
        tagged = gettagged(editor)
        if tagged is None: return
        #
        # OK, so there is something tagged, so lets draw it.  A `view' is one
        #  of the map-displays on the screen, such as the top-down or side on
        #  one in the classic layout.
        #
        cv = view.canvas()
        #
        # We'll color them like Duplicators so we can see an effect
        #
        cv.pencolor = MapColor("Duplicator")
        #
        #  A face has a list of lists of vertexes.  A list of lists because
        #   each face might be used in several polyhedrons, in each polyhedron
        #   the vertexes are listed in a clockwise order as you move around
        #   the edge of the face's manifestation in the polyhedron.
        #
        for vtx in editor.tagging.tagged.vertices: # for a face-manifestation
            #
            # proj turns a 3D point in the map into a point in the display,
            # as determined by the properties of the view  (it's got three
            # coordinates but the functions of z vary).  We start with the
            # last vertex (index pozzie -1 in Python), and cycle through,
            # connecting the last to the first, and so on
            #
            p2 = view.proj(vtx[-1])
            for v in vtx:
                p1 = p2
                p2 = view.proj(v)
                cv.line(p1,p2)  # draw the line
    quarkpy.mapeditor.MapEditor.finishdrawing = tagfinishdrawing
Now when we tag a side, at first nothing happens, but then if we click in the map area, it gets drawn in blue, so at we can see that our new finishdrawing is doing something. What we want is to get the map redrawn right after we have tagged the face, and the way to do it is to add:
            editor.invalidateviews()
at the very end of the tagSideClick function, right after the tagging info is added to the editor. `invalidateviews' will cause the map views to be redrawn on the basis of the new info, and the blue will show up immediately.

Tracking the tagged face | tiglari - 14 Feb 2001 | [ Top ]

But there is still a problem. Tag a face, and then move it. The blue line will probably stay behind in its original position. And if you use the Glue to Tagged command, you'll see the glued side snapping to the original position of the the moved face, not the present position. These aren't really show-stopping bugs, but it's still goofy behavior. What's going on is that the editor's tagging.tagged attribute is storing the old face, while the effect of the movement was to subsitute a new one; QuArK doesn't do a very good job of keeping track of identity of map objects as we tend to construe it. What we want to do is check that the tagged object is still in the map, before doing things that depend on its being there. For this we first utility function `checktree', defined in quarkpy.maputils.py, which tests whether one object is inside another. What we want to do is, at some strategic point, make sure that the tagged face (the thing sitting in editor.tagging.tagged) is still sitting in the map structure (inside editor.Root). We can do this with a little function `checktagged', defined inside of tagfinishdrawing, right after we've gotten the tagged face, which we then check the value of before proceeding:
        ...
        tagged = gettagged(editor)
        if tagged is None: return
        def checktagged(tagged=tagged, editor=editor):
            if not checktree(editor.Root, tagged):
                cleartag(editor)
                return 0
            return 1
        if tagged is None or not checktagged():
            return
        ...
This function utilizes the extremely useful technique of `default arguments, in the definition of the function, the variables to the right of the equalities in the function's argument-list are evaluated in the context where the function is defined, and then used as the values of the variables on the left in subsequent calls. Here the usage of this technique is trivial, just making an `if' statement a bit shorter, but things can get more serious. It would also seem to be a good idea to get rid of the tagging attribute when it's useless; this is accomplished by the `cleartag' function that's invoked above and defined here:
    def cleartag(editor):
        try:
           del editor.tagging
        except (AttributeError):
           pass
Now as a pleasant side effect of all this, when we move the tagged side, the Glue item should become disabled on the menu. Finally, as an easy exercise, you should implement a `Clear tag" command. Sample final results in `maptagside3.py` .

GNU General Public License by The QuArK (Quake Army Knife) Community - http://www.planetquake.com/quark | [ Prev - Top - Next ]