source: remote_control/puzzlebox_brainstorms_client_interface.py @ 42

Last change on this file since 42 was 42, checked in by sc, 11 years ago
  • initial support for discrete control commands
  • Property svn:executable set to *
File size: 11.5 KB
RevLine 
[11]1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3#
4# Puzzlebox - Brainstorms - Client Interface
5#
6# Copyright Puzzlebox Productions, LLC (2010)
7#
[31]8# This code is released under the GNU Pulic License (GPL) version 2
9# For more information please refer to http://www.gnu.org/copyleft/gpl.html
[11]10#
[42]11# Last Update: 2010.05.03
[11]12#
13#####################################################################
14
15import os, sys
[12]16
17import pygame
18#import pygame.font
19import pygame.image
20import pygame.locals
21
[25]22from twisted.internet import reactor, protocol, defer
23
[11]24import puzzlebox_brainstorms_configuration as configuration
[26]25import puzzlebox_brainstorms_client as client
[18]26import puzzlebox_brainstorms_client_interface_component as component
[27]27import puzzlebox_brainstorms_client_interface_button as interface_button
[11]28#import puzzlebox_logger
29
30#####################################################################
31# Globals
32#####################################################################
33
34DEBUG = 1
35
[12]36FLIP = 1
37
[42]38DISCRETE_CONTROL_COMMANDS = configuration.DISCRETE_CONTROL_COMMANDS
39
[11]40SERVER_HOST = configuration.SERVER_HOST
41SERVER_PORT = configuration.SERVER_PORT
42
43DISPLAY_WINDOW_X_COORDINATE = configuration.DISPLAY_WINDOW_X_COORDINATE
44DISPLAY_WINDOW_Y_COORDINATE = configuration.DISPLAY_WINDOW_Y_COORDINATE
45DISPLAY_WINDOW_X_DIMENSION = configuration.DISPLAY_WINDOW_X_DIMENSION
46DISPLAY_WINDOW_Y_DIMENSION = configuration.DISPLAY_WINDOW_Y_DIMENSION
47
48WINDOW_BACKGROUND_COLOR = configuration.WINDOW_BACKGROUND_COLOR
49
[18]50IMAGE_DIRECTORY = configuration.IMAGE_DIRECTORY
51
52BUTTON_LAYOUT = configuration.BUTTON_LAYOUT
53
[11]54#####################################################################
55# Classes
56#####################################################################
57
[18]58class puzzlebox_brainstorms_client_interface( \
[25]59         component.puzzlebox_brainstorms_client_interface_component, \
[26]60         client.puzzlebox_brainstorms_client):
[11]61       
62        def __init__(self, log, \
63                     display_window_x_coordinate, \
64                     display_window_y_coordinate, \
65                     display_window_x_dimension, \
66                     display_window_y_dimension, \
67                     window_background_color, \
68                     DEBUG=DEBUG):
69       
70                self.log = log
[12]71                self.DEBUG = DEBUG
[11]72               
73                self.display_window_x_coordinate = display_window_x_coordinate
74                self.display_window_y_coordinate = display_window_y_coordinate
75                self.display_window_x_dimension = display_window_x_dimension
76                self.display_window_y_dimension = display_window_y_dimension
77                self.window_background_color = window_background_color
78               
[27]79                self.server_host = configuration.SERVER_HOST
80                self.server_port = configuration.SERVER_PORT
81                self.max_connection_attempts = configuration.MAX_CONNECTION_ATTEMPTS
82               
[11]83                if (os.name == "nt") or (os.name == "dos"):
84                        self.operating_system = "windows"
85                else:
86                        self.operating_system = os.name
87               
[18]88                self.pygame = pygame
[19]89                self.screen = None
[18]90                self.FLIP = FLIP
[42]91                self.DISCRETE_CONTROL_COMMANDS = DISCRETE_CONTROL_COMMANDS
[19]92                self.image_directory = IMAGE_DIRECTORY
[18]93               
[11]94                self.initialize_pygame()
95               
[19]96                self.pygame.FLIP = self.FLIP
[11]97               
[27]98                self.buttons = {}
99                self.match_key_index = {}
[11]100               
[18]101                self.initialize_buttons(BUTTON_LAYOUT)
102               
103                self.update_display()
[11]104       
105       
106        #####################################################################
107       
108        def initialize_pygame(self):
109               
[25]110                if (self.operating_system != "windows"):
111                        os.environ['SDL_VIDEO_WINDOW_POS'] = \
112                           "%i,%i" % (self.display_window_x_coordinate, \
[27]113                                      self.display_window_y_coordinate)
[11]114               
[18]115                self.pygame.init()
[11]116               
[18]117                if (self.FLIP):
[11]118                       
[19]119                        self.screen = self.pygame.display.set_mode((self.display_window_x_dimension, \
120                                                                    self.display_window_y_dimension), \
121                                                                   pygame.HWSURFACE|pygame.DOUBLEBUF)
[11]122               
123                else:
[18]124                       
[19]125                        self.screen = self.pygame.display.set_mode((self.display_window_x_dimension, \
126                                                                    self.display_window_y_dimension), \
127                                                                   pygame.HWSURFACE)
[11]128               
129               
130                if (self.DEBUG >= 2):
131                        print "Display Driver:",
132                        print pygame.display.get_driver()
[31]133                        print
134                        print "Display Info:"
[11]135                        print pygame.display.Info()
[31]136                        #print
137                        #print "Windows System Info:"
138                        #print pygame.display.get_wm_info()
139                        #print
[11]140                        #print "Get Flags:",
141                        #print pygame.display.screen.get_flags()
142               
143               
[19]144                #self.pygame.mouse.set_visible(0)
145                self.pygame.mouse.set_visible(1)
[11]146               
[18]147                self.pygame.display.set_caption('Puzzlebox Brainstorms - Client Interface')
[11]148               
149                # Set Background
150                self.background = pygame.Surface(self.screen.get_size())
151                #self.background.set_alpha(0)
[19]152                self.draw_background()
[11]153       
154       
155        ##################################################################
[18]156
[19]157        def draw_background(self):
158               
159                self.background.fill(self.window_background_color)
160               
161                self.screen.blit(self.background, (0,0))
162       
163       
164        #####################################################################
165       
[18]166        def initialize_buttons(self, button_layout):
167               
[27]168                self.buttons = {}
169                self.match_key_index = {}
[18]170               
[27]171                for each in button_layout.keys():
[18]172                       
[27]173                        button = button_layout[each]
174                       
175                        if ((button['button_image'] != None) and \
176                            (button['button_image'] != '.') and \
177                            (button['button_image'] != '..') and \
178                            (os.path.exists(os.path.join(self.image_directory, button['button_image'])))):
[18]179                               
[27]180                                button_image_path = \
181                                   os.path.join(self.image_directory, button['button_image'])
[18]182                       
183                        else:
184                                if self.DEBUG:
185                                        print "Error: Button image does not exist:"
[27]186                                        print "   %s" % os.path.join(self.image_directory, button['button_image'])
[18]187                                continue
188                       
189                       
[27]190                        if ((button['activated_image'] != None) and \
191                            (button['activated_image'] != '.') and \
192                            (button['activated_image'] != '..') and \
193                            (os.path.exists(os.path.join(self.image_directory, button['activated_image'])))):
[18]194                               
[27]195                                activated_image_path = \
196                                   os.path.join(self.image_directory, button['activated_image'])
[18]197                       
198                        else:
199                                if self.DEBUG:
200                                        print "Error: Activated button image does not exist:"
[27]201                                        print "   %s" % os.path.join(self.image_directory, button['activated_image'])
[18]202                                continue
203                       
204                       
[27]205                        for match in button['match_keys']:
206                                self.match_key_index[match] = button['command']
207                       
208                       
209                        new_button = \
210                           interface_button.puzzlebox_brainstorms_client_interface_button( \
[18]211                                   self.pygame, \
212                                   self.screen, \
[27]213                                   button_image_path, \
214                                   activated_image_path, \
215                                   button['image_x'], \
216                                   button['image_y'], \
217                                   button['command'], \
218                                   button['match_keys'], \
[18]219                                   self.DEBUG)
220                       
221                       
[27]222                        self.buttons[ button['command'] ] = new_button
[11]223       
[18]224       
225        ##################################################################
226       
[27]227        def update_button(self, command, activated):
[19]228               
[27]229                self.buttons[command].activated=activated
230                self.buttons[command].display()
231                self.update_display()
[19]232       
233       
234        ##################################################################
235       
[29]236        def process_mouse_click(self, position, mouse_button):
237               
238                if (mouse_button == 1):
239                        # first mouse button clicked
240                       
241                        postion_rect = self.pygame.Rect(position, (1,1) )
242                       
243                        for each in self.buttons.keys():
244                               
245                                if self.buttons[each].check_collision(postion_rect):
246                                       
247                                        command = self.buttons[each].command
248                                        self.update_button(command, activated=True)
249                                        self.send_command(command)
250       
251       
252        ##################################################################
253       
254        def process_mouse_release(self, position, mouse_button):
255               
256                if (mouse_button == 1):
257                        # first mouse button released
258                       
259                        postion_rect = self.pygame.Rect(position, (1,1) )
260                       
261                        for each in self.buttons.keys():
262                               
263                                if self.buttons[each].check_collision(postion_rect):
264                                       
265                                        command = self.buttons[each].command
266                                        self.update_button(command, activated=False)
267       
268       
269        ##################################################################
270       
271        def release_all_buttons(self):
272               
273                for each in self.buttons.keys():
274                               
275                                command = self.buttons[each].command
276                                self.update_button(command, activated=False)
277       
278       
279        ##################################################################
280       
[27]281        def check_events(self):
[11]282               
[26]283                for event in self.pygame.event.get():
[11]284                       
[26]285                        if (event.type is self.pygame.locals.QUIT):
286                                reactor.stop()
[11]287                       
[19]288                       
[26]289                        elif (event.type == self.pygame.locals.KEYDOWN):
[11]290                               
[26]291                                if 'key' in event.dict.keys():
[11]292                                       
[27]293                                        key_pressed = event.dict['key']
[26]294                                       
[27]295                                        if (key_pressed == self.pygame.K_ESCAPE):
296                                                reactor.stop()
[26]297                                       
298                                       
[27]299                                        elif (key_pressed in self.match_key_index.keys()):
300                                               
301                                                # keypress matches recognized key
302                                                command = self.match_key_index[key_pressed]
303                                                self.update_button(command, activated=True)
[28]304                                                self.send_command(command)
[27]305                       
306                       
307                        elif (event.type == self.pygame.locals.KEYUP):
308                               
309                                if 'key' in event.dict.keys():
[26]310                                       
[27]311                                        key_pressed = event.dict['key']
[26]312                                       
[27]313                                        if (key_pressed in self.match_key_index.keys()):
314                                               
315                                                # keypress matches recognized key
316                                                command = self.match_key_index[key_pressed]
317                                                self.update_button(command, activated=False)
[28]318                       
319                       
[29]320                        elif (event.type == self.pygame.locals.MOUSEBUTTONDOWN):
321                               
322                                position = event.pos
323                                mouse_button = event.button
324                               
325                                self.process_mouse_click(position, mouse_button)
326                       
327                       
328                        elif (event.type == self.pygame.locals.MOUSEBUTTONUP):
329                               
[30]330                                # We release all activated buttons when a mouse button is
331                                # released because its possible the user may have pressed
332                                # the mouse button down while hovering over one button on
333                                # the screen, then dragged the pointer while still holding
334                                # down the mouse button, finally releasing it over another
335                                # button on the screen.
336                               
[29]337                                mouse_button = event.button
338                               
339                                if (mouse_button == 1):
340                                        # First mouse button released
341                                        self.release_all_buttons()
342                       
343                       
[28]344                        else:
345                               
346                                if self.DEBUG > 2:
347                                        print "Unrecognized event:",
348                                        print event
[26]349               
350               
[27]351                # Sleep timer provides approximately 33.3 fps
352                reactor.callLater(0.03, self.check_events)
[11]353
354
355#####################################################################
[18]356# Functions
357#####################################################################
358
359#####################################################################
[11]360# Main
361#####################################################################
362
363if __name__ == '__main__':
364       
365        #log = puzzlebox_logger.puzzlebox_logger(logfile='mcc')
366        log = None
367       
368       
369        # Collect default settings and command line parameters
370        server_host = SERVER_HOST
371        server_port = SERVER_PORT
372        display_window_x_coordinate = DISPLAY_WINDOW_X_COORDINATE
373        display_window_y_coordinate = DISPLAY_WINDOW_Y_COORDINATE
374        display_window_x_dimension = DISPLAY_WINDOW_X_DIMENSION
375        display_window_y_dimension = DISPLAY_WINDOW_Y_DIMENSION
376        window_background_color = WINDOW_BACKGROUND_COLOR
377       
378       
379        for each in sys.argv:
380               
381                if each.startswith("--host="):
382                        server_host = each[ len("--host="): ]
383                if each.startswith("--port="):
384                        server_port = each[ len("--port="): ]
385       
386       
387        # Window Defaults
388        try:
389                display_window_x_coordinate = string.atoi(sys.argv[-4])
390                display_window_y_coordinate = string.atoi(sys.argv[-3])
391                display_window_x_dimension = string.atoi(sys.argv[-2])
392                display_window_y_dimension = string.atoi(sys.argv[-1])
393        except:
[31]394                if DEBUG > 1:
[11]395                        print "Using default display coordinates"
396       
397       
398        interface = puzzlebox_brainstorms_client_interface( \
399                                             log, \
400                                             display_window_x_coordinate, \
401                                             display_window_y_coordinate, \
402                                             display_window_x_dimension, \
403                                             display_window_y_dimension, \
404                                             window_background_color, \
405                                             DEBUG=DEBUG)
406       
[27]407        reactor.callWhenRunning(interface.check_events)
[25]408        reactor.run()
[11]409
Note: See TracBrowser for help on using the repository browser.