diff --git a/direct/src/showbase/Transitions.py b/direct/src/showbase/Transitions.py index b47a2fb586..73ed9fab3a 100644 --- a/direct/src/showbase/Transitions.py +++ b/direct/src/showbase/Transitions.py @@ -2,6 +2,7 @@ from pandac.PandaModules import * from direct.gui.DirectGui import * from direct.task import Task +from direct.interval.IntervalGlobal import * class Transitions: @@ -11,88 +12,90 @@ class Transitions: FadeModelName = "models/misc/fade" def __init__(self, loader): + self.ival = None self.iris = None self.fade = None - self.fadeColor = Vec3(0) + self.letterbox = None + self.alphaOff = Vec4(0,0,0,0) + self.alphaOn = Vec4(0,0,0,1) self.irisTaskName = "irisTask" self.fadeTaskName = "fadeTask" + self.letterboxTaskName = "letterboxTask" + + ################################################## + # Fade + ################################################## - def __fadeInLerpDone(self, task): - # This is a helper function to the fadeIn sequence - self.fade.reparentTo(hidden) - return Task.done - - def fadeIn(self, t=0.5, block=0): + def loadFade(self): + if self.fade == None: + # We create a DirectFrame for the fade polygon, instead of + # simply loading the polygon model and using it directly, + # so that it will also obscure mouse events for objects + # positioned behind it. + fadeModel = loader.loadModel(self.FadeModelName) + self.fade = DirectFrame( + parent = hidden, + guiId = 'fade', + relief = None, + image = fadeModel, + image_scale = 3.0, + state = NORMAL, + ) + fadeModel.removeNode() + + def fadeIn(self, t=0.5, finishIval=None): """ Play a fade in transition over t seconds. Places a polygon on the aspect2d plane then lerps the color from black to transparent. When the color lerp is finished, it - parents the fade polygon to hidden. If block is set, return the - sequence instead of spawning it. + parents the fade polygon to hidden. """ self.noTransitions() - self.loadFade() - self.fade.reparentTo(aspect2d, FADE_SORT_INDEX) - if (t == 0): # Fade in immediately with no lerp - self.fade.reparentTo(hidden) + self.fade.detachNode() else: # Create a sequence that lerps the color out, then # parents the fade to hidden - r = self.fadeColor[0] - g = self.fadeColor[1] - b = self.fadeColor[2] - task = Task.sequence( - self.fade.lerpColor(r,g,b,1, - r,g,b,0, - t), - Task.Task(self.__fadeInLerpDone)) - # Spawn the sequence - if not block: - taskMgr.add(task, self.fadeTaskName) - else: - return task + self.fade.reparentTo(aspect2d, FADE_SORT_INDEX) + self.ival = Sequence(LerpColorInterval(self.fade, t, + color = self.alphaOff, + startColor = self.alphaOn), + Func(self.fade.detachNode), + name = self.fadeTaskName, + ) + if finishIval: + self.ival.append(finishIval) + self.ival.start() - def fadeInTask(self, task, time=0.5): - """ - As a sequence: Fade in, execute the given task - """ - seq = Task.sequence(self.fadeIn(time, block=1), task) - taskMgr.add(seq, 'fadeInTaskSeq') - - def fadeOut(self, t=0.5, block=0): + def fadeOut(self, t=0.5, finishIval=None): """ Play a fade out transition over t seconds. Places a polygon on the aspect2d plane then lerps the color from transparent to full black. When the color lerp is finished, it leaves the fade polygon covering the aspect2d plane until you - fadeIn or call noFade. If block is set to 1, performs blocking + fadeIn or call noFade. lerp """ self.noTransitions() - self.loadFade() self.fade.reparentTo(aspect2d, FADE_SORT_INDEX) - - r = self.fadeColor[0] - g = self.fadeColor[1] - b = self.fadeColor[2] if (t == 0): # Fade out immediately with no lerp - self.fade.setColor(r,g,b,1) + self.fade.setColor(self.alphaOn) else: - # Spawn a lerp of the color from no alpha to full alpha - if not block: - self.fade.lerpColor(r,g,b,0, - r,g,b,1, - t, task=self.fadeTaskName) - else: - return self.fade.lerpColor(r,g,b,0, - r,g,b,1, - t) + # Create a sequence that lerps the color out, then + # parents the fade to hidden + self.ival = Sequence(LerpColorInterval(self.fade, t, + color = self.alphaOn, + startColor = self.alphaOff), + name = self.fadeTaskName, + ) + if finishIval: + self.ival.append(finishIval) + self.ival.start() def fadeScreen(self, alpha=0.5): """ @@ -103,10 +106,9 @@ class Transitions: self.noTransitions() self.loadFade() self.fade.reparentTo(aspect2d, FADE_SORT_INDEX) - - self.fade.setColor(self.fadeColor[0], - self.fadeColor[1], - self.fadeColor[2], + self.fade.setColor(self.alphaOn[0], + self.alphaOn[1], + self.alphaOn[2], alpha) def fadeScreenColor(self, color): @@ -120,83 +122,55 @@ class Transitions: self.fade.reparentTo(aspect2d, FADE_SORT_INDEX) self.fade.setColor(color) - def fadeOutTask(self, task, time=0.3, noFade=1): - """ - As a sequence: Fade out, execute the given task, then do a noFade - if requested - """ - if noFade: - def noFadeTask(task): - task.noFade() - return Task.done - nft = Task.Task(noFadeTask) - nft.noFade = self.noFade - seq = Task.sequence(self.fadeOut(time, block=1), task, nft) - else: - seq = Task.sequence(self.fadeOut(time, block=1), task) - - # do it - taskMgr.add(seq, 'fadeOutTaskSeq') - def noFade(self): """ Removes any current fade tasks and parents the fade polygon away """ - taskMgr.remove(self.fadeTaskName) - if self.fade != None: - self.fade.reparentTo(hidden) + if self.ival: + self.ival.pause() + self.ival = None + if self.fade: + self.fade.detachNode() def setFadeColor(self, r, g, b): - self.fadeColor.set(r,g,b) - - def __irisInLerpDone(self, task): - # This is a helper function to the fadeIn sequence - self.iris.reparentTo(hidden) - return Task.done + self.alphaOn.set(r,g,b,1) + self.alphaOff.set(r,g,b,0) - def irisIn(self, t=0.5, block=0): + + ################################################## + # Iris + ################################################## + + def loadIris(self): + if self.iris == None: + self.iris = loader.loadModel(self.IrisModelName) + self.iris.setPos(0,0,0) + + def irisIn(self, t=0.5, finishIval=None): """ Play an iris in transition over t seconds. Places a polygon on the aspect2d plane then lerps the scale of the iris polygon up so it looks like we iris in. When the scale lerp is finished, it parents the iris polygon to hidden. - If block is true, does not execute lerp, but returns the sequence. """ self.noTransitions() - self.loadIris() if (t == 0): - self.iris.reparentTo(hidden) + self.iris.detachNode() else: self.iris.reparentTo(aspect2d, FADE_SORT_INDEX) - self.iris.setScale(0.015) - # Create a sequence that scales the iris up, - # then parents the fade to hidden - task = Task.sequence( - self.iris.lerpScale(0.18, 0.18, 0.18, - t, blendType="noBlend"), - Task.Task(self.__irisInLerpDone)) - # Spawn the sequence - if not block: - taskMgr.add(task, self.irisTaskName) - else: - return task + + self.ival = Sequence(LerpScaleInterval(self.iris, t, + scale = 0.18, + startScale = 0.01), + Func(self.iris.detachNode), + name = self.irisTaskName, + ) + if finishIval: + self.ival.append(finishIval) + self.ival.start() - def irisInTask(self, task, time=0.5): - """ - As a sequence: iris in, execute the given task - """ - seq = Task.sequence(self.irisIn(time, block=1), task) - taskMgr.add(seq, 'irisInTaskSeq') - - def irisOutLerpDone(self, task): - # This is a helper function to the fadeIn sequence - self.iris.reparentTo(hidden) - # Use the fade to cover up the hole that the iris would leave - self.fadeOut(0) - return Task.done - - def irisOut(self, t=0.5, block=0): + def irisOut(self, t=0.5, finishIval=None): """ Play an iris out transition over t seconds. Places a polygon on the aspect2d plane then lerps the scale @@ -205,56 +179,38 @@ class Transitions: aspect2d plane until you irisIn or call noIris. """ self.noTransitions() - self.loadIris() self.loadFade() # we need this to cover up the hole. if (t == 0): - self.iris.reparentTo(hidden) + self.iris.detachNode() + self.fadeOut(0) else: self.iris.reparentTo(aspect2d, FADE_SORT_INDEX) - self.iris.setScale(0.18) - # Create a sequence that scales the iris up, - # then parents the fade to hidden - task = Task.sequence( - self.iris.lerpScale(0.015, 0.015, 0.015, - t, blendType="noBlend"), - Task.Task(self.irisOutLerpDone)) - # Spawn the sequence - if not block: - taskMgr.add(task, self.irisTaskName) - else: - return task - def irisOutTask(self, task, time=0.5, noIris=1): - """ - As a sequence: iris out, execute the given task, then do a noIris - if requested - """ - if noIris: - def noIrisTask(task): - task.noIris() - return Task.done - nit = Task.Task(noIrisTask) - nit.noIris = self.noIris - seq = Task.sequence(self.irisOut(time, block=1), task, nit) - else: - seq = Task.sequence(self.irisOut(time, block=1), task) - - # do it - taskMgr.add(seq, 'irisOutTaskSeq') + self.ival = Sequence(LerpScaleInterval(self.iris, t, + scale = 0.01, + startScale = 0.18), + Func(self.iris.detachNode), + # Use the fade to cover up the hole that the iris would leave + Func(self.fadeOut, 0), + name = self.irisTaskName, + ) + if finishIval: + self.ival.append(finishIval) + self.ival.start() def noIris(self): """ Removes any current iris tasks and parents the iris polygon away """ - taskMgr.remove(self.irisTaskName) + if self.ival: + self.ival.pause() + self.ival = None if self.iris != None: - self.iris.reparentTo(hidden) - + self.iris.detachNode() # Actually we need to remove the fade too, # because the iris effect uses it. self.noFade() - def noTransitions(self): """ @@ -262,29 +218,102 @@ class Transitions: """ self.noFade() self.noIris() + self.noLetterbox() - def loadIris(self): - if self.iris == None: - self.iris = loader.loadModel(self.IrisModelName) - self.iris.setPos(0,0,0) - - def loadFade(self): - if self.fade == None: + ################################################## + # Letterbox + ################################################## + def loadLetterbox(self): + if self.letterbox == None: # We create a DirectFrame for the fade polygon, instead of # simply loading the polygon model and using it directly, # so that it will also obscure mouse events for objects # positioned behind it. - fadeModel = loader.loadModel(self.FadeModelName) - - self.fade = DirectFrame( - parent = hidden, - guiId = 'fade', - relief = None, - image = fadeModel, - image_scale = 3.0, + self.letterbox = NodePath("letterbox") + # Allow fade in and out of the bars + self.letterbox.setTransparency(1) + self.letterboxTop = DirectFrame( + parent = self.letterbox, + guiId = 'letterboxTop', + relief = FLAT, state = NORMAL, + frameColor = (0,0,0,1), + borderWidth = (0,0), + frameSize = (-1, 1, 0, 0.2), + pos = (0,0,0.8), + ) + self.letterboxBottom = DirectFrame( + parent = self.letterbox, + guiId = 'letterboxBottom', + relief = FLAT, + state = NORMAL, + frameColor = (0,0,0,1), + borderWidth = (0,0), + frameSize = (-1, 1, 0, 0.2), + pos = (0,0,-1), ) - fadeModel.removeNode() + def noLetterbox(self): + """ + Removes any current letterbox tasks and parents the letterbox polygon away + """ + if self.ival: + self.ival.pause() + self.ival = None + if self.letterbox != None: + self.letterbox.detachNode() + def letterboxOn(self, t=0.25, finishIval=None): + """ + Move black bars in over t seconds. + """ + self.noTransitions() + self.loadLetterbox() + if (t == 0): + self.letterbox.reparentTo(render2d, FADE_SORT_INDEX) + self.letterboxBottom.setPos(0,0,-1) + self.letterboxTop.setPos(0,0,0.8) + else: + self.letterbox.reparentTo(render2d, FADE_SORT_INDEX) + self.ival = Sequence(Parallel(LerpPosInterval(self.letterboxBottom, t, + pos = Vec3(0,0,-1), + startPos = Vec3(0,0,-1.2)), + LerpPosInterval(self.letterboxTop, t, + pos = Vec3(0,0,0.8), + startPos = Vec3(0,0,1)), + LerpColorInterval(self.letterbox, t, + color = self.alphaOn, + startColor = self.alphaOff), + ), + name = self.letterboxTaskName, + ) + if finishIval: + self.ival.append(finishIval) + self.ival.start() + + def letterboxOff(self, t=0.25, finishIval=None): + """ + Move black bars away over t seconds. + """ + self.noTransitions() + self.loadLetterbox() + if (t == 0): + self.letterbox.detachNode() + else: + self.letterbox.reparentTo(render2d, FADE_SORT_INDEX) + self.ival = Sequence(Parallel(LerpPosInterval(self.letterboxBottom, t, + pos = Vec3(0,0,-1.2), + startPos = Vec3(0,0,-1)), + LerpPosInterval(self.letterboxTop, t, + pos = Vec3(0,0,1), + startPos = Vec3(0,0,0.8)), + LerpColorInterval(self.letterbox, t, + color = self.alphaOff, + startColor = self.alphaOn), + ), + name = self.letterboxTaskName, + ) + if finishIval: + self.ival.append(finishIval) + self.ival.start()