Imported Upstream version 2008.1+svn1656
[opeanno-debian-packaging.git] / game / engine.py
blob2a584e15d6d9dc4787045f2d9dbeb889cd87234d
1 # ###################################################
2 # Copyright (C) 2008 The OpenAnno Team
3 # team@openanno.org
4 # This file is part of OpenAnno.
6 # OpenAnno is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the
18 # Free Software Foundation, Inc.,
19 # 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 # ###################################################
22 import fife
23 import fifelog
24 import pychan
25 import game.gui.style
26 import game.main
27 import new
28 import glob, random
29 from game.util.inventory_widget import Inventory, ImageFillStatusButton
31 class SQLiteAnimationLoader(fife.ResourceLoader):
32 """Loads animations from a SQLite database.
33 """
34 def __init__(self):
35 super(SQLiteAnimationLoader, self).__init__()
36 self.thisown = 0
38 def loadResource(self, location):
39 """
40 @param location: String with the location. See below for details:
41 Location format: <animation_id>:<command>:<params> (e.g.: "123:shift:left-16,bottom-8)
42 Available commands:
43 - shift:
44 Shift the image using the params left, right, center, middle for x shifting and
45 y-shifting with the params: top, bottom, center, middle.
46 A param looks like this: "param_x(+/-)value,param_y(+/-)value" (e.g.: left-16,bottom+8)
47 - cut:
48 #TODO: complete documentation
49 """
50 commands = location.getFilename().split(':')
51 id = commands.pop(0)
52 if ',' in id:
53 id, shift_x, shift_y = id.split(',')
54 else:
55 shift_x, shift_y = None, None
56 commands = zip(commands[0::2], commands[1::2])
57 print "Loading animation #%s..." % (id)
58 ani = fife.Animation()
59 frame_start, frame_end = 0.0, 0.0
60 for file,frame_end in game.main.db("SELECT file, frame_length from data.animation where animation_id = ?", id):
61 idx = game.main.fife.imagepool.addResourceFromFile(file)
62 img = game.main.fife.imagepool.getImage(idx)
63 for command, arg in commands:
64 if command == 'shift':
65 x, y = arg.split(',')
66 if x.startswith('left'):
67 x = int(x[4:]) + int(img.getWidth() / 2)
68 elif x.startswith('right'):
69 x = int(x[5:]) - int(img.getWidth() / 2)
70 elif x.startswith(('center', 'middle')):
71 x = int(x[6:])
72 else:
73 x = int(x)
75 if y.startswith('top'):
76 y = int(y[3:]) + int(img.getHeight() / 2)
77 elif y.startswith('bottom'):
78 y = int(y[6:]) - int(img.getHeight() / 2)
79 elif y.startswith(('center', 'middle')):
80 y = int(y[6:])
81 else:
82 y = int(y)
84 img.setXShift(x)
85 img.setYShift(y)
86 elif command == 'cut':
87 loc = fife.ImageLocation('asdf')
88 loc.setParentSource(img)
89 x, y, w, h = arg.split(',')
91 if x.startswith('left'):
92 x = int(x[4:])
93 elif x.startswith('right'):
94 x = int(x[5:]) + img.getWidth()
95 elif x.startswith(('center', 'middle')):
96 x = int(x[6:]) + int(img.getWidth() / 2)
97 else:
98 x = int(x)
100 if y.startswith('top'):
101 y = int(y[3:])
102 elif y.startswith('bottom'):
103 y = int(y[6:]) - img.getHeight()
104 elif y.startswith(('center', 'middle')):
105 y = int(y[6:]) + int(img.getHeight() / 2)
106 else:
107 y = int(y)
109 if w.startswith('left'):
110 w = int(w[4:]) - x
111 elif w.startswith('right'):
112 w = int(w[5:]) + img.getWidth() - x
113 elif w.startswith(('center', 'middle')):
114 w = int(w[6:]) + int(img.getWidth() / 2) - x
115 else:
116 w = int(w)
118 if h.startswith('top'):
119 h = int(h[3:]) - y
120 elif h.startswith('bottom'):
121 h = int(h[6:]) + img.getHeight() - y
122 elif h.startswith(('center', 'middle')):
123 h = int(h[6:]) + int(img.getHeight() / 2) - y
124 else:
125 h = int(h)
127 loc.setXShift(x)
128 loc.setYShift(y)
129 loc.setWidth(w)
130 loc.setHeight(h)
132 idx = game.main.fife.imagepool.addResourceFromLocation(loc)
133 img = game.main.fife.imagepool.getImage(idx)
134 ani.addFrame(fife.ResourcePtr(game.main.fife.imagepool,idx), max(1,int((float(frame_end) - frame_start)*1000)))
135 frame_start = float(frame_end)
136 ani.setActionFrame(0)
137 ani.thisown = 0
138 return ani
140 class Fife(object):
143 def __init__(self):
144 self.pump = []
146 self.engine = fife.Engine()
147 self.settings = self.engine.getSettings()
148 self.pychan = pychan
150 self._doQuit = False
151 self._doBreak = False
152 self._doReturn = None
153 self._gotInited = False
155 #init settings
156 game.main.settings.addCategorys('fife')
157 game.main.settings.fife.addChangeListener(self._setSetting)
158 game.main.settings.fife.addCategorys('defaultFont', 'sound', 'renderer', 'screen')
160 game.main.settings.fife.defaultFont.setDefaults(
161 path = 'content/gfx/fonts/Essays1743-Italic.ttf',
162 size = 18,
163 glyphs = " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,!?-+/():;%&`'*#=[]\""
166 game.main.settings.fife.sound.setDefaults(
167 initialVolume = self.settings.getMaxVolume()
170 game.main.settings.fife.renderer.setDefaults(
171 backend = 'OpenGL',
172 SDLRemoveFakeAlpha = False,
173 imageChunkingSize = 256
176 game.main.settings.fife.screen.setDefaults(
177 fullscreen = False,
178 width = 1024,
179 height = 768,
180 bpp = 0,
181 title = 'OpenAnno',
182 icon = 'content/gui/images/icon.png'
185 def _setSetting(self, settingObject, settingName, value):
187 @param settingObject:
188 @param settingName:
189 @param value:
191 setting = settingObject._name + settingName
192 if setting == 'fife.defaultFont.path':
193 self.settings.setDefaultFontPath(value)
194 elif setting == 'fife.defaultFont.size':
195 self.settings.setDefaultFontSize(value)
196 elif setting == 'fife.defaultFont.glyphs':
197 self.settings.setDefaultFontGlyphs(value)
198 elif setting == 'fife.screen.fullscreen':
199 self.settings.setFullScreen(1 if value else 0)
200 elif setting == 'fife.screen.width':
201 self.settings.setScreenWidth(value)
202 elif setting == 'fife.screen.height':
203 self.settings.setScreenHeight(value)
204 elif setting == 'fife.screen.bpp':
205 self.settings.setBitsPerPixel(1 if value else 0)
206 elif setting == 'fife.renderer.backend':
207 self.settings.setRenderBackend(value)
208 elif setting == 'fife.renderer.SDLRemoveFakeAlpha':
209 self.settings.setSDLRemoveFakeAlpha(value)
210 elif setting == 'fife.renderer.imageChunkingSize':
211 self.settings.setImageChunkingSize(value)
212 elif setting == 'fife.sound.initialVolume':
213 self.settings.setInitialVolume(value)
214 elif setting == 'fife.screen.title':
215 self.settings.setWindowTitle(value)
216 elif setting == 'fife.screen.icon':
217 self.settings.setWindowIcon(value)
219 def init(self):
222 logToPrompt, logToFile, debugPychan = True, True, False
223 if self._gotInited:
224 return
225 #start modules
226 self.log = fifelog.LogManager(self.engine, 1 if logToPrompt else 0, 1 if logToFile else 0)
227 #self.log.setVisibleModules('all')
229 self.engine.init()
231 #temporarily select a random music file to play. TODO: Replace with proper playlist
232 self.music = glob.glob('content/audio/music/*.ogg')
234 #init stuff
235 self.eventmanager = self.engine.getEventManager()
236 #self.eventmanager.setNonConsumableKeys([fife.Key.ESCAPE, fife.Key.F10])
237 self.guimanager = self.engine.getGuiManager()
238 self.console = self.guimanager.getConsole()
239 self.soundmanager = self.engine.getSoundManager()
240 self.soundmanager.init()
241 if game.main.settings.sound.enabled:
242 self.soundclippool = self.engine.getSoundClipPool()
243 self.bgsound = self.soundmanager.createEmitter()
244 self.bgsound.setGain(game.main.settings.sound.volume_music)
245 self.bgsound.setLooping(False)
246 self.effect_sound = self.soundmanager.createEmitter()
247 self.effect_sound.setGain(game.main.settings.sound.volume_effects)
248 self.effect_sound.setLooping(False)
249 self.music_rand_element = random.randint(0, len(self.music) - 1)
250 self.bgsound.setSoundClip(self.soundclippool.addResourceFromFile(self.music[self.music_rand_element]))
251 self.bgsound.play()
252 def check_music():
253 if hasattr(self, '_bgsound_old_byte_pos') and hasattr(self, '_bgsound_old_sample_pos'):
254 if self._bgsound_old_byte_pos == game.main.fife.bgsound.getCursor(fife.SD_BYTE_POS) and self._bgsound_old_sample_pos == game.main.fife.bgsound.getCursor(fife.SD_SAMPLE_POS):
255 self.music_rand_element = self.music_rand_element + 1 if self.music_rand_element + 1 < len(self.music) else 0
256 self.bgsound.reset()
257 self.bgsound.setSoundClip(self.soundclippool.addResourceFromFile(self.music[self.music_rand_element]))
258 self.bgsound.play()
259 self._bgsound_old_byte_pos, self._bgsound_old_sample_pos = game.main.fife.bgsound.getCursor(fife.SD_BYTE_POS), game.main.fife.bgsound.getCursor(fife.SD_SAMPLE_POS)
260 game.main.ext_scheduler.add_new_object(check_music, self, loops=-1)
261 self.imagepool = self.engine.getImagePool()
262 self.animationpool = self.engine.getAnimationPool()
263 self.animationloader = SQLiteAnimationLoader()
264 self.animationpool.addResourceLoader(self.animationloader)
266 #Set game cursor
267 self.cursor = self.engine.getCursor()
268 self.default_cursor_image = self.imagepool.addResourceFromFile('content/gui/images/misc/cursor.png')
269 self.cursor.set(fife.CURSOR_IMAGE, self.default_cursor_image)
271 #init pychan
272 self.pychan.init(self.engine, debugPychan)
273 self.pychan.setupModalExecution(self.loop, self.breakLoop)
274 for name, stylepart in game.gui.style.STYLES.items():
275 self.pychan.manager.addStyle(name, stylepart)
276 self.pychan.loadFonts("content/fonts/Essays1743-Italic.fontdef")
277 pychan.widgets.registerWidget(Inventory)
278 pychan.widgets.registerWidget(ImageFillStatusButton)
280 self._gotInited = True
282 def run(self):
285 self.init()
286 self.engine.initializePumping()
287 self.loop()
288 self.engine.finalizePumping()
290 def loop(self):
293 while not self._doQuit:
294 try:
295 self.engine.pump()
296 except fife.Exception, e:
297 print e.getMessage()
298 break
299 for f in self.pump:
301 if self._doBreak:
302 self._doBreak = False
303 return self._doReturn
305 def breakLoop(self, returnValue = None):
307 @param returnValue:
309 self._doReturn = returnValue
310 self._doBreak = True
312 def quit(self):
313 """ Quits the engine.
315 self._doQuit = True