##################################################################### # -*- coding: iso-8859-1 -*- # # # # Frets on Fire # # Copyright (C) 2006 Sami Kyöstilä # # 2008 myfingershurt # # 2008 Blazingamer # # 2008 evilynux # # # # This program is free software; you can redistribute it and/or # # modify it under the terms of the GNU General Public License # # as published by the Free Software Foundation; either version 2 # # of the License, or (at your option) any later version. # # # # This program is distributed in the hope that it will be useful, # # but WITHOUT ANY WARRANTY; without even the implied warranty of # # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # # GNU General Public License for more details. # # # # You should have received a copy of the GNU General Public License # # along with this program; if not, write to the Free Software # # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # # MA 02110-1301, USA. # ##################################################################### import Config from OpenGL.GL import * import math import Log from Shader import shaders import Theme import os import random #MFH - needed for new stage background handling from Language import _ import Version # Provides dataPath class Stage(object): def __init__(self, guitarScene, configFileName): self.scene = guitarScene self.engine = guitarScene.engine self.config = Config.MyConfigParser() self.reset() self.wFull = None #MFH - needed for new stage background handling self.hFull = None # evilynux - imported myfingershurt stuff from GuitarScene self.mode = self.engine.config.get("game", "stage_mode") self.songStage = self.engine.config.get("game", "song_stage") self.animatedFolder = self.engine.config.get("game", "animated_stage_folder") # evilynux - imported myfingershurt stuff from GuitarScene w/ minor modifs #MFH TODO - alter logic to accomodate separated animation and slideshow # settings based on seleted animated stage folder animationMode = self.engine.config.get("game", "stage_animate") slideShowMode = self.engine.config.get("game", "rotate_stages") if self.animatedFolder == _("None"): self.rotationMode = 0 #MFH: if no animated stage folders are available, disable rotation. elif self.animatedFolder == "Normal": self.rotationMode = slideShowMode else: self.rotationMode = animationMode self.imgArr = [] #QQstarS:random self.imgArrScaleFactors = [] #MFH - for precalculated scale factors self.rotateDelay = self.engine.config.get("game", "stage_rotate_delay") #myfingershurt - user defined stage rotate delay self.animateDelay = self.engine.config.get("game", "stage_animate_delay") #myfingershurt - user defined stage rotate delay self.animation = False self.indexCount = 0 #QQstarS:random time counter self.arrNum = 0 #QQstarS:random the array num self.arrDir = 1 #forwards self.config.read(configFileName) # evilynux - Improved stage error handling self.themename = self.engine.data.themeLabel self.path = os.path.join("themes",self.themename,"stages") self.pathfull = self.engine.getPath(self.path) if not os.path.exists(self.pathfull): # evilynux Log.warn("Stage folder does not exist: %s" % self.pathfull) self.mode = 1 # Fallback to song-specific stage suffix = ".jpg" def load(self, libraryName, songName, practiceMode = False): # evilynux - Fixes a self.background not defined crash self.background = None #MFH - new background stage logic: if self.mode == 2: #blank / no stage self.songStage = 0 self.rotationMode = 0 elif practiceMode: #check for existing practice stage; always disable stage rotation here self.songStage = 0 self.rotationMode = 0 self.mode = 1 try: #separated practice stages for the instruments by k.i.d if self.scene.guitars[0].isDrum: background = "practicedrum" elif self.scene.guitars[0].isBassGuitar: background = "practicebass" else: background = "practice" try: self.engine.loadImgDrawing(self, "background", os.path.join("themes",self.themename,"stages",background + ".jpg")) except IOError: self.engine.loadImgDrawing(self, "background", os.path.join("themes",self.themename,"stages",background + ".png")) except IOError: #MFH - must first fall back on the old practice.png before forcing blank stage mode! try: try: self.engine.loadImgDrawing(self, "background", os.path.join("themes",self.themename,"stages","practice.jpg")) except IOError: self.engine.loadImgDrawing(self, "background", os.path.join("themes",self.themename,"stages","practice.png")) except IOError: Log.warn("No practice stage, fallbacking on a forced Blank stage mode") # evilynux self.mode = 2 #if no practice stage, just fall back on a forced Blank stage mode elif self.songStage == 1: #check for song-specific background test = True try: try: self.engine.loadImgDrawing(self, "background", os.path.join(libraryName, songName, "background.jpg")) except IOError: self.engine.loadImgDrawing(self, "background", os.path.join(libraryName, songName, "background.png")) except IOError: Log.notice("No song-specific stage found") # evilynux test = False if test: #does a song-specific background exist? self.rotationMode = 0 self.mode = 1 else: self.songStage = 0 #MFH - now, after the above logic, we can run the normal stage mode logic # only worrying about checking for Blank, song-specific and # practice stage modes if self.mode != 2 and self.songStage == 0 and not practiceMode: #still need to load stage(s) #myfingershurt: assign this first if self.mode == 1: #just use Default.png try: try: self.engine.loadImgDrawing(self, "background", os.path.join(self.path, "default.jpg")) except IOError: self.engine.loadImgDrawing(self, "background", os.path.join(self.path, "default.png")) except IOError: Log.warn("No default stage; falling back on a forced Blank stage mode") # evilynux self.mode = 2 #if no practice stage, just fall back on a forced Blank stage mode ##This checks how many Stage-background we have to select from if self.mode == 0 and self.rotationMode == 0: #MFH: just display a random stage files = [] fileIndex = 0 allfiles = os.listdir(self.pathfull) for name in allfiles: if os.path.splitext(name)[1].lower() == ".png" or os.path.splitext(name)[1].lower() == ".jpg" or os.path.splitext(name)[1].lower() == ".jpeg": if os.path.splitext(name)[0].lower() != "practice" and os.path.splitext(name)[0].lower() != "practicedrum" and os.path.splitext(name)[0].lower() != "practicebass": Log.debug("Valid background found, index (" + str(fileIndex) + "): " + name) files.append(name) fileIndex += 1 else: Log.debug("Practice background filtered: " + name) # evilynux - improved error handling, fallback to blank background if no background are found if fileIndex == 0: Log.warn("No valid stage found!") self.mode = 2; else: i = random.randint(0,len(files)-1) filename = files[i] ##End check number of Stage-backgrounds self.engine.loadImgDrawing(self, "background", os.path.join(self.path, filename)) elif self.rotationMode > 0 and self.mode != 2: files = [] fileIndex = 0 if self.animatedFolder == "Random": #Select one of the subfolders under stages\ to animate randomly numAniStageFolders = len(self.engine.stageFolders) if numAniStageFolders > 0: self.animatedFolder = random.choice(self.engine.stageFolders) else: self.animatedFolder = "Normal" elif self.animatedFolder == "None": self.mode = 2 if self.animatedFolder != "Normal" and self.mode != 2: #just use the base Stages folder for rotation self.path = os.path.join("themes",self.themename,"stages",self.animatedFolder) self.pathfull = self.engine.getPath(self.path) self.animation = True allfiles = os.listdir(self.pathfull) for name in allfiles: if os.path.splitext(name)[1].lower() == ".png" or os.path.splitext(name)[1].lower() == ".jpg" or os.path.splitext(name)[1].lower() == ".jpeg": if os.path.splitext(name)[0].lower() != "practice" and os.path.splitext(name)[0].lower() != "practicedrum" and os.path.splitext(name)[0].lower() != "practicebass": Log.debug("Valid background found, index (" + str(fileIndex) + "): " + name) files.append(name) fileIndex += 1 else: Log.debug("Practice background filtered: " + name) files.sort() if self.rotationMode > 0 and self.mode != 2: #alarian: blank stage option is not selected #myfingershurt: just populate the image array in order, they are pulled in whatever order requested: for j in range(len(files)): self.engine.loadImgDrawing(self, "backgroundA", os.path.join(self.path, files[j])) #MFH: also precalculate each image's scale factor and store in the array imgwidth = self.backgroundA.width1() wfactor = 640.000/imgwidth self.imgArr.append(getattr(self, "backgroundA", os.path.join(self.path, files[j]))) self.imgArrScaleFactors.append(wfactor) if self.rotationMode > 0 and len(self.imgArr) == 0: self.rotationMode = 0 if self.mode != 2 and self.background: #MFH - precalculating scale factor imgwidth = self.background.width1() self.backgroundScaleFactor = 640.000/imgwidth #stage rotation def rotate(self): if self.animation: whichDelay = self.animateDelay else: whichDelay = self.rotateDelay self.indexCount = self.indexCount + 1 if self.indexCount > whichDelay: #myfingershurt - adding user setting for stage rotate delay self.indexCount = 0 if self.rotationMode == 1: #QQstarS:random self.arrNum = random.randint(0,len(self.imgArr)-1) elif self.rotationMode == 2: #myfingershurt: in order display mode self.arrNum += 1 if self.arrNum > (len(self.imgArr)-1): self.arrNum = 0 elif self.rotationMode == 3: #myfingershurt: in order, back and forth display mode if self.arrDir == 1: #forwards self.arrNum += 1 if self.arrNum > (len(self.imgArr)-1): self.arrNum -= 2 self.arrDir = 0 else: self.arrNum -= 1 if self.arrNum < 0: self.arrNum += 2 self.arrDir = 1 def renderBackground(self): #myfingershurt: multiple rotation modes if self.mode != 2: if self.rotationMode == 0: self.engine.drawImage(self.background, scale = (self.backgroundScaleFactor,-self.backgroundScaleFactor), coord = (self.wFull/2,self.hFull/2)) #myfingershurt: else: #MFH - use precalculated scale factors instead self.engine.drawImage(self.imgArr[self.arrNum], scale = (self.imgArrScaleFactors[self.arrNum],-self.imgArrScaleFactors[self.arrNum]), coord = (self.wFull/2,self.hFull/2)) def updateDelays(self): self.rotateDelay = self.engine.config.get("game", "stage_rotate_delay") #myfingershurt - user defined stage rotate delay self.animateDelay = self.engine.config.get("game", "stage_animate_delay") #myfingershurt - user defined stage rotate delay def reset(self): self.lastBeatPos = None self.lastQuarterBeatPos = None self.lastMissPos = None self.lastPickPos = None self.beat = 0 self.quarterBeat = 0 self.pos = 0.0 self.playedNotes = [] self.averageNotes = [0.0] self.beatPeriod = 0.0 def triggerPick(self, pos, notes): if notes: self.lastPickPos = pos self.playedNotes = self.playedNotes[-3:] + [sum(notes) / float(len(notes))] self.averageNotes[-1] = sum(self.playedNotes) / float(len(self.playedNotes)) def triggerMiss(self, pos): self.lastMissPos = pos def triggerQuarterBeat(self, pos, quarterBeat): self.lastQuarterBeatPos = pos self.quarterBeat = quarterBeat def triggerBeat(self, pos, beat): self.lastBeatPos = pos self.beat = beat self.averageNotes = self.averageNotes[-4:] + self.averageNotes[-1:] def run(self, pos, period): self.pos = pos self.beatPeriod = period quarterBeat = int(4 * pos / period) if quarterBeat > self.quarterBeat: self.triggerQuarterBeat(pos, quarterBeat) beat = quarterBeat / 4 if beat > self.beat: self.triggerBeat(pos, beat) def render(self, visibility): if self.mode != 3: self.renderBackground() if shaders.enable("stage"): height = 0.0 for i in shaders.var["color"].keys(): shaders.modVar("color",shaders.var["color"][i],0.05,10.0) height += shaders.var["color"][i][3]/3.0 height=height**2 shaders.setVar("height",2*height) shaders.setVar("ambientGlow",height/1.5) shaders.setVar("glowStrength",60+height*80.0) glBegin(GL_TRIANGLE_STRIP) glVertex3f(-8.0, 1.0,7.0) glVertex3f(8.0, 1.0,7.0) glVertex3f(-8.0, 4.0,7.0) glVertex3f(8.0, 4.0,7.0) glEnd() shaders.disable() self.scene.renderGuitar()