Forum Archive

Tip - Useful objects like Rect obj in scene module (others also)

Phuket2

I have never used the scene module before, but I was doing some drawing in a custom view , just overriding the draw method. But needed to do some simple Rect Calculations. Inset etc. not difficult, but muddys your code. Then I just come across the Rect object in scene. I just imported Rect. My tip being that even you don't use a module, can be worTh going through the docs to see what it contains. I understand the Rect object is a little heavy compared to just calculating coords, but in this case I only needed a few Rects.
Hope it helps someone

from scene import Rect
JonB

The ui module (in the beta) also has Rect, as well as Point, Vector2, etc.

Phuket2

@JonB, yes I see that now. But unless I am mistaken which is normal, you have to explicitly import Rect from ui.
from ui import Rect

ccc
import scene, ui
assert dir(scene.Point())   == dir(ui.Point())
assert dir(scene.Rect())    == dir(ui.Rect())
assert dir(scene.Vector2()) == dir(ui.Vector2())
print('Success!')
JonB

only if you want to refer to it as Rect instead of ui.Rect.

In either case, if you are using ui already, but not using scene, it is better to import from ui (which is basically free, and akin to writing Rect=ui.Rect, rather than importing a whole new module).

But this is a good reminder -- the docs in the ui module do not list all of the useful functions in Rect. Also Rect supports the in keyword, which is useful:

>>> ui.Rect(1,1,5,5) in ui.Rect(0,0,10,10)
True
>>> ui.Rect(1,1,15,15) in ui.Rect(0,0,10,10)
False
>>> ui.Point(1,1) in ui.Rect(0,0,10,10)
True
>>> ui.Point(-1,1) in ui.Rect(0,0,10,10)
False

Also, Rects can have negative height or width, for when it is convienent to specify some other corner other than the upper left. Although (perhaps a bug) inset does not work the way it would for a CGRect for negative widths -- you must apply the sign of width/height to the x/y inset inputs to get the desired behavior (so negative inset makes a Rect larger when the corresponding width/height is positive, but smaller when the corresponding attribute is negative)

JonB

@ccc
I think you meant to say

assert(ui.Rect is scene.Rect)

etc. These types are the same fundamental built in types, not only do they have the same method names.

JonB

Other random observation: ui.View.frames can have negative width (which then does get regularized after you set it)! So super useful for, say, right aligning a button

>>> v=ui.View(0,0,100,100)
>>> b=ui.Button(frame=(v.width,0,-30,30))
>>> b.frame
Rect(70.00, 0.00, 30.00, 30.00)

though for a button this only works if not setting the title( since Buttons autosize if title is used)

ccc

The in operator does make hit testing easier but not as easy as it could have been:

```python
touch in sprite_node # throws a TypeError -- I like this syntax!
touch.location in sprite_node # throws a TypeError
touch in sprite_node.frame # always returns False
touch.location in sprite_node.frame # a real hit test

...

import scene

class MyScene(scene.Scene):
def setup(self):
self.snake = scene.SpriteNode(parent=self, position=self.bounds.center(),
texture=scene.Texture('emj:Snake'))

def touch_ended(self, touch):
    # print(touch in self.snake)             # TypeError SpriteNode is not iterable
    # print(touch.location in self.snake)    # TypeError SpriteNode is not iterable
    print(touch in self.snake.frame,         # always False
        touch.location in self.snake.frame)  # a real hit test

if name == 'main':
scene.run(MyScene())

Olaf

As @ccc points out, Point, Rect and Vector2 are identical. The same applies to Size, but the other common names, Button and Touch, are different.

import inspect, scene, ui
common = set(dict(inspect.getmembers(scene, inspect.isclass)))
common &= set(dict(inspect.getmembers(ui, inspect.isclass)))
common = sorted(list(common))
for cls in common:
    print 'class', cls, 'in scene and ui are', 'identical' if getattr(scene, cls) is getattr(ui, cls) else 'different'

results in

class Button in scene and ui are different
class Point in scene and ui are identical
class Rect in scene and ui are identical
class Size in scene and ui are identical
class Touch in scene and ui are different
class Vector2 in scene and ui are identical