Tag

Tags are basically sprites that can be positioned pixel-exact on the screen. As such they have an inherent two-dimensional quality while still not being entirely 2D. They are drawn into orthographic space and therefore have no perspective. A tag that is moved away from the camera does not get smaller. Also, camera movement does not affect any tags. They will always stay at the same spot on the screen while the world and the sprites behind them will transform.

Tags are also a convenient way of checking whether the mouse is over a specific graphical object. Each tag fires various mouse events that precisely reflect how the mouse is interacting with the content of the tag.

Relevant examples: tag.py , tag_all.py, tag_lines.py , tag_drag.py , ALL

In Context

from slut import *

class Atlantis(World):
    def onSetup(self):
        self.name = "Lines"
        self.width = 300
        self.height = 300
         
        Lines(self, 'tag0')
        self.tags['tag0'].moveTo(50, 30)


class Lines(Tag):
    def onDraw(self):
        for x in range(7):
            glBegin(GL_LINES)
            glVertex3f(0+(20*x), 0, 0)
            glVertex3f(0+(20*x), 50, 0)
            glEnd()

atlantis = Atlantis()
atlantis.run()

Tags may also be nested in other tags resulting in a 3D-modeler-typical scene graph (or DAG).

Tags are added to the scene by simply instancing them. Since the first argument is a reference to the world (or another tag) they know how to add themselves to the scene. In many cases it is customary not to manually assign the tag instance to a variable but to use the dictionary where the world keeps track of them: self.tags. This dictionary uses the tag's name as the key to the tag instance.

ATagClass(self, 'tag1')
theNewTag = self.tags['tag1']

On the other hand there are occasions in which it makes sense to use a separate variable to hold the reference to the new tag:

anewtag = ATagClass(self, 'tag1')
theNewTag = anewtag

Tag objects are usually instanced from a custom class (like Lines in the above example) that defines the characteristics (what it draws, how it reacts to the mouse) of that tag. The only requirement for that custom tag class is that it inherits from slut.tag.Tag. Just as shapes that are drawn directly in the world, shapes in a tag are redrawn multiple times a second via repeated calls to onDraw(). Once a tag has been added to the scene it can be moved, rotated and scaled as a whole.

Transformation methods come in two flavors--relative and absolute. Relative methods always operate on the tag by adding to the current position/scale while absolute methods take the passed values and make them the new position/scale. The passed arguments are units of the coordinate system where the tag was created. This is either the world or another tag. Arguments for rotations and orbits are always in degrees (with 360 being one rotation).

The origin (x=0, y=0) of the world is the upper left corner with the lower right corner being the width and height of the window.

tagobject.moveTo(80, 40)
tagobject.rotTo(180)
tagobject.scaleTo(2.0, 2.0)

The above code snippet moves the tag 80 pixels right and 40 pixels down from the upper left corner. Then it rotates the tag half a rotation around the y-axis (axis that is perpendicular to the picture plane) and finally scales the tag up by 200 percent.

Note: Orbits always occurs around the origin of the coordinate system where the tag was created. If the tag was not moved away from the origin, orbiting is equivalent to rotation.

Alternatively, transformation arguments can be specified with Tween and Thrust objects.

Initiated by Stephan Hechenberger
Thanks to CADRE's 103