Package pyzzle :: Module Hotspot
[hide private]
[frames] | no frames]

Source Code for Module pyzzle.Hotspot

  1  """ 
  2  Sprites representing parts of a slide that the user can click. 
  3  """ 
  4  import pyzzle, media, Text, Slide 
  5  import pygame 
  6  import os 
  7  from pygame.rect import Rect 
  8  from pygame.sprite import Sprite 
  9  from pygame.font import * 
 10  from pygame.locals import * 
 11  import standard 
 12  from RelativeRect import RelativeRect 
 13  from DB import Table,Row 
14 15 -class Hotspot(Sprite):
16 """Pygame Sprites representing parts of a slide 17 that the user can click.""" 18 __metaclass__=Table 19 20 cursorDefault ='fwd.png' 21 """The value of the cursor attribute when no other is specified""" 22 23 @staticmethod
24 - def _load(cells):
25 row=Row(cells) 26 parent =Slide.Slide[row.parent] if row.parent else None 27 link =Slide.Slide[row.link] if row.link else None 28 hotspot=Hotspot(parent, link, 29 rectRel=RelativeRect((row.left, row.top, row.width, row.height)), 30 cursor=row.cursor, 31 text=row.text, 32 layer=row.layer, 33 id=row.id, 34 soundfile=row.sound, 35 delay=row.delay, 36 zip=row.zip) 37 if any((row.dragleft,row.dragtop, 38 row.dragwidth,row.dragheight)): 39 hotspot.drag=RelativeRect((row.dragleft,row.dragtop, 40 row.dragwidth,row.dragheight)) 41 if parent: 42 parent.add(hotspot) 43 if row.transition: 44 hotspot.onTransition=getattr(standard, row.transition) 45 return hotspot
46 - def _save(self):
47 cells= \ 48 {'id':self.id, 49 'parent':self.parent.id if self.parent else None, 50 'link' :self.link.id if self.link else None, 51 'cursor':self.cursor, 52 'sound' :self.soundfile, 53 'delay' :self.delay, 54 'layer' :self._layer, 55 'text' :self.text, 56 'zip' :self.zip} 57 if 'lambda' not in self.onTransition.__name__: 58 cells['transition']=self.onTransition.__name__ 59 if self._rect: 60 self.rectRel=RelativeRect(self._rect, self.parent.rect) 61 for attr in 'left','top','width','height': 62 cells[attr]=getattr(self.rectRel,attr) 63 if self.drag: 64 for attr in 'left','top','width','height': 65 cells['drag'+attr]=getattr(self.drag,attr) 66 return cells
67 - def __init__(self, parent, link, id=None, 68 rectRel=None, layer=0.0, 69 cursor='', delay=.1, zip=False, 70 soundfile=None, text=None, drag=None, 71 _template=False, 72 73 onClick=lambda self: Hotspot.transition(self), 74 onHighlight=lambda self:None, 75 onTransition=standard._noTransition):
76 """ 77 Creates a new Hotspot. 78 @param id: A unique identifier for the Hotspot. Used to refer to the Hotspot 79 in scripts and the database 80 @param parent: Panel in which the Hotspot resides. 81 Note: This will not add the slide to the panel. You still need to add it 82 using Slide.enter() or one of the transition functions 83 @param link: Slide the Hotspot will transition to when clicked 84 @type rectRel: RelativeRect 85 @param rectRel: The relative coordinates representing the area 86 that can be clicked. Coordinates are relative to the size of parent. 87 @param layer: The layer of the Hotspot. Larger numbers represent upper layers. 88 When the player clicks on an area of the Slide where two Sprites overlap, 89 the sprite with the topmost layer is the only one that's activated. 90 @param cursor: The name of the cursor file that is displayed 91 when no hotspots are highlighted. The default is defined by 92 Panel.cursorDefault. None displays no cursor. 93 @param delay: The time that should be taken to transition from parent to link 94 when the Hotspot is clicked. 95 @param zip: Whether this is a zip hotspot 96 (disabled unless zip mode is on and the link has been visited). 97 @param soundfile: The name of the sound file played when the user clicks 98 the hotspot. 99 @param text: Text that is displayed under the cursor when the user highlights 100 the Hotspot. 101 @type drag: RelativeRect 102 @param drag: The relative coordinates of the area the user 103 must drag to activate the hotspot. 104 @param onClick: The function that is called when the Hotspot is clicked. 105 If the drag parameter is specified, this function will not be 106 called until the user has dragged the Hotspot to the correct location. 107 @param onHighlight: The function that is called when the Hotspot is clicked. 108 @param onTransition: The transition function used to transition from 109 parent to link when the Hotspot is clicked. 110 """ 111 if id and not _template: Hotspot.rows[id]=self 112 Sprite.__init__(self) 113 self.id=id 114 self.parent=parent 115 self._link=link 116 self._setLink(link) 117 self.rectRel=rectRel 118 self._rect=None 119 self.cursor=Hotspot.cursorDefault if cursor == '' else cursor 120 self.delay=delay 121 self._layer=layer 122 self.soundfile=soundfile 123 self.drag=drag 124 self.used=False 125 self.text=text 126 self.zip=zip 127 128 self._template=_template 129 self._enabled=True 130 131 self.onClick=onClick 132 self.onHighlight=onHighlight 133 self.onTransition=onTransition
134
135 - def _getRect(self):
136 """The portion of the screen the user may click to 137 activate the Hotspot.""" 138 if self.rectRel: 139 self._rect=self.rectRel.absolute(self.parent.rect) 140 return self._rect
141 - def _setRect(self, rect): self._rect=rect
142 rect=property(_getRect, _setRect) 143 152 link=property(_getLink, _setLink) 153
154 - def _getEnabled(self):
155 if not self._enabled:return False 156 if not self.zip: return True 157 return pyzzle.zip and self.link and self.link.visited
158 - def _setEnabled(self,value):
159 self.enabled=value
160 enabled=property(_getEnabled,_setEnabled) 161
162 - def draw(self,screen):
163 """Draws the Hotspot's border, if the game is in design mode. """ 164 if pyzzle.design and pygame.key.get_mods() & KMOD_SHIFT: 165 if (self._link or not self._template): 166 pygame.draw.rect(screen, pyzzle.Text.Text.colorDefault, 167 self.rect, 2)
168 - def highlight(self):
169 """Called when the user hovers over the Hotspot. 170 Draws cursor and text to the screen, where present, 171 and calls onHighlight""" 172 if self.text or (self._link and pyzzle.design): 173 text=Text.Text(self._link.id if pyzzle.design else self.text) 174 text._getImage() 175 textrect=text.rect 176 textrect.topleft=pyzzle.cursor.rect.bottomright 177 textrect.clamp_ip(pyzzle.screen.get_rect()) 178 text.draw(pyzzle.screen) 179 self.onHighlight(self) 180 return self.cursor
181
182 - def click(self, design=False):
183 """Called when the user clicks the Hotspot. 184 Plays soundfile and calls onClick. 185 If drag is specified, the user must drag the cursor 186 to the drag area in order to call onClick. 187 @param design: Used only for design mode 188 """ 189 if design: 190 self.design() 191 return 192 if pyzzle.design and not self.link: 193 return 194 195 if self.soundfile: 196 media.sounds.load(self.soundfile).play() 197 198 activate=not self.drag 199 if self.drag: 200 rect=self.drag.absolute(self.parent.rect) 201 pos=pyzzle.drag() 202 activate=rect.collidepoint(pos) 203 204 if activate: 205 self.onClick(self) 206 self.used=True
207 - def transition(self):
208 """Commands the hotspot to transition the user to the link. 209 onClick must explicitly call this to transition the user. 210 This makes it very easy to script certain behavior, 211 such as for locks.""" 212 self.onTransition(self.parent, self._link, self.delay)
213 214
215 - def design(self, drag=True):
216 selected=pyzzle.dragRect(color=(255,0,255)) if drag else Rect(0,0,0,0) 217 if selected.width>10 and selected.height>10: 218 #add custom hotspot 219 hotspotname=pyzzle.promptText("Enter hotspot name: ", 220 self.parent.id+self.id if self.id else '') 221 if hotspotname and hotspotname not in Hotspot.rows: 222 cursorfile=pyzzle.promptText("Enter cursor file: ", Hotspot.cursorDefault) 223 if cursorfile: 224 hotspot=Hotspot(parent=self.parent, link=None, 225 cursor=cursorfile, id=hotspotname) 226 hotspot.onTransition=standard.transition 227 hotspot.rect=selected 228 self.parent.add(hotspot) 229 hotspot.design(drag=False) 230 elif pygame.key.get_mods() & KMOD_CTRL: 231 #delete/clear hotspot 232 if self._template: 233 self._link=None 234 else: 235 self.kill() 236 else: 237 #edit hotspot 238 slidename=pyzzle.promptText('Enter slide name:') 239 if slidename: 240 slide=None 241 if slidename in Slide.Slide.rows: 242 slide=Slide.Slide[slidename] 243 else: 244 slidefile=pyzzle.promptText('Enter slide file:', slidename+'.jpg') 245 if slidefile: 246 slide=Slide.Slide(slidename, slidefile, self.parent.stage) 247 slide._refs={} 248 for ref in 'forward', 'up', 'down', 'right', 'left': 249 slide._refs[ref]=None 250 slide._loadRefs() 251 slide.insert() 252 if slide: 253 self._link=slide 254 self.click()
255