コード例 #1
0
ファイル: story.py プロジェクト: seanh/PandaZUI
    def __init__(self):

        # Create two story maps, 'Story Cards' which the user picks story cards
        # from, and 'My Story Map' in which the user constructs her story.
        self.storyCards = StoryMap(storyCardClass=FocusableChoosableStoryCard, 
                                   title="Story Cards")
        self.storyCards.reparentTo(zcanvas.home)
        self.storyCards.setScale(0.02)
        self.storyCards.setPos(-.5,0,.8)
        self.storyCards.fill()
        self.storyCards.added_behaviour = 'disable'
        
        self.myStoryMap = StoryMap(storyCardClass=FocusableEditableStoryCard, 
                                   title="My Story")
        self.myStoryMap.reparentTo(zcanvas.home)
        self.myStoryMap.setScale(0.02)
        self.myStoryMap.setPos(-.5,0,-.1)
        self.myStoryMap.added_behaviour = 'remove'
        #self.myStoryMap.keep_sorted = True        
        #self.myStoryMap.np.showTightBounds()
        self.myStoryMap.auto_grow = True
               
        # Keyboard controls for saving, loading and exporting.
        #base.accept("f1",self.save)
        #base.accept("f2",self.load)
        #base.accept("f3",self.export)
        
        # Subscribe to some messages.
        self.acceptOnce('zoom done',zcanvas.message,["Right-click to zoom back out again."])
        self.accept('add',self.add)
        self.accept('remove',self.remove)

        # Frame along the bottom for Save, Load and Quit buttons.
        self.bottom_np = aspect2d.attachNewNode('bottom frame')
        height = 0.15
        self.bottom_np.setPos(-base.getAspectRatio(),0,-1-height)
        cm = CardMaker('bottom frame')
        cm.setFrame(0,2*base.getAspectRatio(),0,height)
        self.bottom_np.attachNewNode(cm.generate())
        self.bottom_np.setTransparency(TransparencyAttrib.MAlpha)
        self.bottom_np.setColor(.1,.1,.1,.7)
        self.bottom_hbox = HBoxList(margin=1)
        self.bottom_hbox.reparentTo(self.bottom_np)
        self.bottom_hbox.setPos(0,0,height-0.03)
        self.bottom_hbox.setScale(.1)    
        self.save_button = DirectButton(text="Save",command=self.save)
        b = Box()
        b.fill(self.save_button)
        self.bottom_hbox.append(b)
        self.load_button = DirectButton(text="Load",command=self.load)
        b = Box()
        b.fill(self.load_button)
        self.bottom_hbox.append(b)
        # Interval that slides the frame onto the screen.
        self.bottom_interval = LerpPosInterval(
                            self.bottom_np,
                            duration=1,
                            pos=Point3(-base.getAspectRatio(),0,-1),
                            startPos=Point3(-base.getAspectRatio(),0,-1-height),
                            other=None,
                            blendType='easeInOut',
                            bakeInStart=1,
                            fluid=0,
                            name=None)
        self.bottom_reverse_interval = LerpPosInterval(
                                 self.bottom_np,
                                 duration=1,
                                 pos=Point3(-base.getAspectRatio(),0,-1-height),
                                 startPos=Point3(-base.getAspectRatio(),0,-1),
                                 other=None,
                                 blendType='easeInOut',
                                 bakeInStart=1,
                                 fluid=0,
                                 name=None)
        self.bottom_frame_is_active = False

        # Frame along the right for story cards.
        self.right_np = aspect2d.attachNewNode('right frame')
        width = 0.14*base.getAspectRatio()
        self.right_np.setPos(base.getAspectRatio()+width,0,1)
        cm = CardMaker('right frame')
        cm.setFrame(-width,0,-2,0)
        self.right_np.attachNewNode(cm.generate())
        self.right_np.setTransparency(TransparencyAttrib.MAlpha)
        self.right_np.setColor(.1,.1,.1,.7)
        self.right_vbox = Stack()
        self.right_vbox.reparentTo(self.right_np)
        self.right_vbox.setPos(-width+0.035,0,-0.06)
        self.right_vbox.setScale(.02)
        # Interval that slides the frame onto the screen.
        self.right_interval = LerpPosInterval(
                               self.right_np,
                               duration=1,
                               pos=Point3(base.getAspectRatio(),0,1),
                               startPos=Point3(base.getAspectRatio()+width,0,1),
                               other=None,
                               blendType='easeInOut',
                               bakeInStart=1,
                               fluid=0,
                               name=None)
        self.right_reverse_interval = LerpPosInterval(
                                    self.right_np,
                                    duration=1,
                                    pos=Point3(base.getAspectRatio()+width,0,1),
                                    startPos=Point3(base.getAspectRatio(),0,1),
                                    other=None,
                                    blendType='easeInOut',
                                    bakeInStart=1,
                                    fluid=0,
                                    name=None)
        self.right_frame_is_active = False

        # Task that watches for the mouse going to the screen edges and slides
        # the frames onscreen when it does.
        self.prev_x = None
        self.prev_y = None
        taskMgr.add(self.task,'Mediator mouse watcher task')

        NodePathWrapper.__init__(self)
        FocusObserver.__init__(self)
コード例 #2
0
ファイル: boxlist_demo.py プロジェクト: PlumpMath/PandaZUI
    cm = CardMaker('cm')
    cm.setFrame(-.1, .1, -.1, .1)

    def __init__(self):

        ZNode.__init__(self, geomnode=DemoItem.cm.generate())
        Draggable.__init__(self)
        self.set_draggable(True)
        Highlightable.__init__(self)
        self.set_highlightable(True)
        # FIXME. zoomable is required to make highlightable work because of the
        # collision mask. It shouldn't be.
        self.set_zoomable(True)


hbox = HBoxList()
hbox.setPos(-.5, 0, .4)
hbox.reparentTo(zcanvas.home)
for i in range(5):
    b = Box(geomnode=DemoItem.cm.generate())
    hbox.append(b)
    i = DemoItem()
    b.fill(i)

vbox = VBoxList()
vbox.setPos(-.5, 0, .25)
vbox.reparentTo(zcanvas.home)
for i in range(5):
    b = Box(geomnode=DemoItem.cm.generate())
    vbox.append(b)
コード例 #3
0
ファイル: story.py プロジェクト: seanh/PandaZUI
class Mediator(Receiver,FocusObserver,NodePathWrapper):
    """The singleton mediatorobject mediates the interaction between the
    StoryMap objects, receiving notifications and calling methods on StoryMap
    objects.

    """
    def __init__(self):

        # Create two story maps, 'Story Cards' which the user picks story cards
        # from, and 'My Story Map' in which the user constructs her story.
        self.storyCards = StoryMap(storyCardClass=FocusableChoosableStoryCard, 
                                   title="Story Cards")
        self.storyCards.reparentTo(zcanvas.home)
        self.storyCards.setScale(0.02)
        self.storyCards.setPos(-.5,0,.8)
        self.storyCards.fill()
        self.storyCards.added_behaviour = 'disable'
        
        self.myStoryMap = StoryMap(storyCardClass=FocusableEditableStoryCard, 
                                   title="My Story")
        self.myStoryMap.reparentTo(zcanvas.home)
        self.myStoryMap.setScale(0.02)
        self.myStoryMap.setPos(-.5,0,-.1)
        self.myStoryMap.added_behaviour = 'remove'
        #self.myStoryMap.keep_sorted = True        
        #self.myStoryMap.np.showTightBounds()
        self.myStoryMap.auto_grow = True
               
        # Keyboard controls for saving, loading and exporting.
        #base.accept("f1",self.save)
        #base.accept("f2",self.load)
        #base.accept("f3",self.export)
        
        # Subscribe to some messages.
        self.acceptOnce('zoom done',zcanvas.message,["Right-click to zoom back out again."])
        self.accept('add',self.add)
        self.accept('remove',self.remove)

        # Frame along the bottom for Save, Load and Quit buttons.
        self.bottom_np = aspect2d.attachNewNode('bottom frame')
        height = 0.15
        self.bottom_np.setPos(-base.getAspectRatio(),0,-1-height)
        cm = CardMaker('bottom frame')
        cm.setFrame(0,2*base.getAspectRatio(),0,height)
        self.bottom_np.attachNewNode(cm.generate())
        self.bottom_np.setTransparency(TransparencyAttrib.MAlpha)
        self.bottom_np.setColor(.1,.1,.1,.7)
        self.bottom_hbox = HBoxList(margin=1)
        self.bottom_hbox.reparentTo(self.bottom_np)
        self.bottom_hbox.setPos(0,0,height-0.03)
        self.bottom_hbox.setScale(.1)    
        self.save_button = DirectButton(text="Save",command=self.save)
        b = Box()
        b.fill(self.save_button)
        self.bottom_hbox.append(b)
        self.load_button = DirectButton(text="Load",command=self.load)
        b = Box()
        b.fill(self.load_button)
        self.bottom_hbox.append(b)
        # Interval that slides the frame onto the screen.
        self.bottom_interval = LerpPosInterval(
                            self.bottom_np,
                            duration=1,
                            pos=Point3(-base.getAspectRatio(),0,-1),
                            startPos=Point3(-base.getAspectRatio(),0,-1-height),
                            other=None,
                            blendType='easeInOut',
                            bakeInStart=1,
                            fluid=0,
                            name=None)
        self.bottom_reverse_interval = LerpPosInterval(
                                 self.bottom_np,
                                 duration=1,
                                 pos=Point3(-base.getAspectRatio(),0,-1-height),
                                 startPos=Point3(-base.getAspectRatio(),0,-1),
                                 other=None,
                                 blendType='easeInOut',
                                 bakeInStart=1,
                                 fluid=0,
                                 name=None)
        self.bottom_frame_is_active = False

        # Frame along the right for story cards.
        self.right_np = aspect2d.attachNewNode('right frame')
        width = 0.14*base.getAspectRatio()
        self.right_np.setPos(base.getAspectRatio()+width,0,1)
        cm = CardMaker('right frame')
        cm.setFrame(-width,0,-2,0)
        self.right_np.attachNewNode(cm.generate())
        self.right_np.setTransparency(TransparencyAttrib.MAlpha)
        self.right_np.setColor(.1,.1,.1,.7)
        self.right_vbox = Stack()
        self.right_vbox.reparentTo(self.right_np)
        self.right_vbox.setPos(-width+0.035,0,-0.06)
        self.right_vbox.setScale(.02)
        # Interval that slides the frame onto the screen.
        self.right_interval = LerpPosInterval(
                               self.right_np,
                               duration=1,
                               pos=Point3(base.getAspectRatio(),0,1),
                               startPos=Point3(base.getAspectRatio()+width,0,1),
                               other=None,
                               blendType='easeInOut',
                               bakeInStart=1,
                               fluid=0,
                               name=None)
        self.right_reverse_interval = LerpPosInterval(
                                    self.right_np,
                                    duration=1,
                                    pos=Point3(base.getAspectRatio()+width,0,1),
                                    startPos=Point3(base.getAspectRatio(),0,1),
                                    other=None,
                                    blendType='easeInOut',
                                    bakeInStart=1,
                                    fluid=0,
                                    name=None)
        self.right_frame_is_active = False

        # Task that watches for the mouse going to the screen edges and slides
        # the frames onscreen when it does.
        self.prev_x = None
        self.prev_y = None
        taskMgr.add(self.task,'Mediator mouse watcher task')

        NodePathWrapper.__init__(self)
        FocusObserver.__init__(self)

    def enterNone(self):
        """Viewport focus has changed to None."""
        # Make the title of 'My Story Map' editable.
        self.myStoryMap.title['state'] = DGG.NORMAL
    def exitNone(self):
        """Undo any changes made by enterNone."""
        self.myStoryMap.title['state'] = DGG.DISABLED

    def task(self,task):
        if base.mouseWatcherNode.hasMouse():
            x=base.mouseWatcherNode.getMouseX()
            y=base.mouseWatcherNode.getMouseY()                        
            if y <= -0.87 and self.prev_y > -0.87:
                # The mouse has just moved into the bottom frame's area.
                self.activate_bottom_frame()
            elif y > -0.87 and self.prev_y <= -0.87:
                # The mouse has just moved out of the bottom frame's area.
                self.deactivate_bottom_frame()
            self.prev_y = y
            if x >= 0.8 and self.prev_x < 0.8:
                # The mouse has just moved into the right frame's area.
                self.activate_right_frame()
            elif x < 0.8 and self.prev_x >= 0.8:
                # The mouse has just moved out of the right frame's area.
                self.deactivate_right_frame()
            self.prev_x = x
        return task.cont

    def activate_bottom_frame(self):
        
        if not self.bottom_frame_is_active:
            self.bottom_interval.start()
            self.bottom_frame_is_active = True

    def deactivate_bottom_frame(self):

        if self.bottom_frame_is_active:
            self.bottom_reverse_interval.start()
            self.bottom_frame_is_active = False

    def activate_right_frame(self):        
        if not self.right_frame_is_active:
            self.right_interval.start()
            self.right_frame_is_active = True

    def deactivate_right_frame(self):
        if self.right_frame_is_active:
            self.right_reverse_interval.start()
            self.right_frame_is_active = False

    def add(self,card):
        # The Add button was pressed on one of the StoryCards in self.storyCards
        for box in self.right_vbox:
            if box.contents is None:
                box.fill(card)
                # self.activate_right_frame()
                return
        zcanvas.message('The stack is full!\nDrag another card from the stack first.')
        
    def remove(self,editableCard):
        # The Remove button was pressed on one of the StoryCards in
        # self.myStoryMap
        editableCard.getPythonTag('box').empty()
        for choosableCard in self.storyCards.items():
            if choosableCard.function == editableCard.function:
                choosableCard.enable()
                return

    # Implement the Originator interface of the memento design pattern. (For
    # saving and loading.)
    class Memento:
        """A passive class that stores the state of a Mediator object."""    
        def __init__(self, storycards, mystorymap, stack):
            # MediatorMemento just holds mementos for mediator's two StoryMap 
            # objects.
            self.storycards = storycards
            self.mystorymap = mystorymap    
            self.stack = stack
        def __str__(self):
            return self.mystorymap.__str__()
    
    def create_memento(self):
        """Return a memento object holding the current internal state of this
        object."""

        return Mediator.Memento(self.storyCards.create_memento(), 
                                self.myStoryMap.create_memento(),
                                self.right_vbox.create_memento())

    def restore_memento(self,memento):
        """Restore the internal state of this object to that held by the given
        memento."""

        self.storyCards.restore_memento(memento.storycards)
        self.myStoryMap.restore_memento(memento.mystorymap)
        self.right_vbox.restore_memento(memento.stack)

    # Implement the Caretaker interface of the memento design pattern. (For
    # saving and loading.)
    def save(self):
        """Save the current state of the application to file."""
        memento = self.create_memento()
        import datetime
        f = open(str(datetime.datetime.now()).replace(' ','_')+'.saved_story','w')
        cPickle.dump(memento,f)
        f.close()
        zcanvas.message("Saved!")

    def _load(self,args):
        self.load_list.removeNode()
        f = open(args,'r')
        memento = cPickle.load(f)
        f.close()
        self.restore_memento(memento)        
        taskMgr.doMethodLater(1, zcanvas.message, 'Welcome Message', extraArgs = ["Loaded!"])

    def load(self):
        """Restore the current state of the application from file."""
        dir = '.'
        ext = '.saved_story'
        saved_stories = [f for f in os.listdir(dir) if os.path.isfile(os.path.join(dir,f)) and f.endswith(ext)]
        saved_stories.sort()
        
        from direct.gui.DirectGui import DirectScrolledList,DirectButton
        labels = []
        for saved_story in saved_stories:
            filename,ext = os.path.splitext(saved_story)
            l = DirectButton(text=filename, scale=0.05, command=self._load, extraArgs=[saved_story])
            labels.append(l)                
        self.load_list = DirectScrolledList(
            decButton_pos= (0.35, 0, 0.53),
            decButton_text = "/\\",
            decButton_text_scale = 0.04,
            decButton_borderWidth = (0.005, 0.005),
        
            incButton_pos= (0.35, 0, -0.02),
            incButton_text = "\\/",
            incButton_text_scale = 0.04,
            incButton_borderWidth = (0.005, 0.005),
        
            #frameSize = (0.0, 0.7, -0.05, 0.59),
            #frameColor = (1,0,0,0.5),
            pos = self.load_button.getPos(aspect2d),
            items = labels,
            numItemsVisible = 4,
            forceHeight = 0.11,
            itemFrame_frameSize = (-0.3, 0.3, -0.37, 0.11),
            itemFrame_pos = (0.35, 0, 0.4),
            )
                                
    def export(self):
        """Export the current story to a text file."""
        memento = self.create_memento()
        try:
            f = open("story.txt", "w")
            try:
                f.write(memento.__str__())
            finally:
                f.close()
        except IOError:
            print 'IOError while exporting story!'    
コード例 #4
0
    def __init__(self,function):

        self.function = function
        
        ZNode.__init__(self,geomnode=card(), magnification=.8)        
        self.np.setColor(1,1,1,1)
                
        Draggable.__init__(self)
        Highlightable.__init__(self)

        # Uncomment to apply a texture to the card.
        #tex = loader.loadTexture('card.png')
        #self.np.setTexture(tex)

        # Now to add the DirectGUI widgets onto the card. A StoryCard has two
        # VBoxes containing DirectGUI objects, one that is shown when the card
        # is far from the viewport and displaying itself in low detail, and one
        # that is shown when the viewport is focused on the card and the card is
        # showing itself in high detail.
        self.lowDetailVBox = VBoxList()
        self.highDetailVBox = VBoxList()
        self.lowDetailVBox.reparentTo(self.np)
        self.highDetailVBox.reparentTo(self.np)

        # The title of the function of this card.
        font = 'storymaps/data/TypeWritersSubstitute-Black.ttf'

        title = DirectLabel(text=self.function.name,
                            text_font=loader.loadFont(font),
                            text_bg=(1,1,1,0),
                            frameColor=(1,1,1,1),
                            scale=.7,
                            suppressMouse=0)
        b = Box()
        b.fill(title)                            
        self.lowDetailVBox.append(b)

        title = DirectLabel(text=self.function.name,
                            text_font=loader.loadFont(font),
                            text_bg=(1,1,1,0),
                            frameColor=(1,1,1,1),
                            scale=.7,
                            suppressMouse=0)
        b = Box()
        b.fill(title)                            
        self.highDetailVBox.append(b)

        # The icon of the function of this card. Use Panda's mipmapping
        # to handle scaling the image efficiently.
        tex = loader.loadTexture(function.image)
        tex.setMagfilter(Texture.FTLinearMipmapLinear)
        tex.setMinfilter(Texture.FTLinearMipmapLinear)

        icon = DirectLabel(image=tex)
        icon.setScale(2.5)
        b = Box()
        b.fill(icon)                            
        self.lowDetailVBox.append(b)

        icon = DirectLabel(image=tex)
        b = Box()
        b.fill(icon)                                    
        self.highDetailVBox.append(b)

        # The longer description of the Propp function.
        self.entry  = DirectEntry(initialText=self.function.desc,
                                 text_font=loader.loadFont('storymaps/data/WritersFont.ttf'),
                                 scale=.4,
                                 width=13,
                                 numLines=7,
                                 suppressMouse=0,
                                 frameColor = (1,1,1,1))
        self.entry['state'] = DGG.DISABLED

        b = Box()
        b.setColor(1,1,1,0)
        b.fill(self.entry)                            
        self.highDetailVBox.append(b)

        self.lowDetailVBox.setPos(self.lowDetailVBox.np,-2.6,0,4)
        self.highDetailVBox.setPos(self.lowDetailVBox.getPos())

        self.highDetailVBox.hide()

        # A place for subclasses to put buttons.
        self.buttons = HBoxList()             
        self.buttons.reparentTo(self.np)   
        self.buttons.setScale(.6)
        self.buttons.setPos(-1.8,0,-1.6)
        self.buttons.hide()

        self.disabled = False
コード例 #5
0
class StoryCard(ZNode, Highlightable, Draggable):
    """A StoryCard consists of some card-shaped background geometry, and on top
    of that a vbox with a title (DirectLabel), icon (DirectLabel) and main text
    (DirectEntry).Along the bottom of the card is an hbox containing buttons
    that control the card.
    
    A StoryCard has various binary states that can be toggled:
    
    focusable/not-focusable:    whether the card can be focused (zoomed to) by
                                the viewport. Functionality from znode. (Or
                                Focusable mixin class?)
                                
                                card.set_zoomable(True|False)
    
    draggable/not-draggable:    whether the card can be dragged or not,
                                functionality from Draggable mixin class.
                                
                                card.set_draggable(True|False)
                                
    highlightable/not-highlightable:    whether the card responds to mouse-overs
                                        or not, functionality from highlightable
                                        mixin class.
                                        
                                card.set_highlightable(True|False)  
                                        
    high-detail/low-detail: whether the highdetail vbox and hbox are shown or
                            the low detail.
                            
                            card.set_detail("high"|"low")
                            
    editable/not-editable: whether the DirectEntry is active and focussed or
                           not.
                           
                            card.set_editable(True|False)

    show-buttons/don't-show-buttons: whether or not the row of DirectButton's
                                     along the bottom of the card is shown.
                                     
                            card.show_buttons(True|False)
                           
    All of these states must be controlled by user classes, e.g. a StoryCard
    subclass that is a FocusObserver, a StoryMap that owns the StoryCard, or
    some sort of global Controller class.
     
    """
    def __init__(self,function):

        self.function = function
        
        ZNode.__init__(self,geomnode=card(), magnification=.8)        
        self.np.setColor(1,1,1,1)
                
        Draggable.__init__(self)
        Highlightable.__init__(self)

        # Uncomment to apply a texture to the card.
        #tex = loader.loadTexture('card.png')
        #self.np.setTexture(tex)

        # Now to add the DirectGUI widgets onto the card. A StoryCard has two
        # VBoxes containing DirectGUI objects, one that is shown when the card
        # is far from the viewport and displaying itself in low detail, and one
        # that is shown when the viewport is focused on the card and the card is
        # showing itself in high detail.
        self.lowDetailVBox = VBoxList()
        self.highDetailVBox = VBoxList()
        self.lowDetailVBox.reparentTo(self.np)
        self.highDetailVBox.reparentTo(self.np)

        # The title of the function of this card.
        font = 'storymaps/data/TypeWritersSubstitute-Black.ttf'

        title = DirectLabel(text=self.function.name,
                            text_font=loader.loadFont(font),
                            text_bg=(1,1,1,0),
                            frameColor=(1,1,1,1),
                            scale=.7,
                            suppressMouse=0)
        b = Box()
        b.fill(title)                            
        self.lowDetailVBox.append(b)

        title = DirectLabel(text=self.function.name,
                            text_font=loader.loadFont(font),
                            text_bg=(1,1,1,0),
                            frameColor=(1,1,1,1),
                            scale=.7,
                            suppressMouse=0)
        b = Box()
        b.fill(title)                            
        self.highDetailVBox.append(b)

        # The icon of the function of this card. Use Panda's mipmapping
        # to handle scaling the image efficiently.
        tex = loader.loadTexture(function.image)
        tex.setMagfilter(Texture.FTLinearMipmapLinear)
        tex.setMinfilter(Texture.FTLinearMipmapLinear)

        icon = DirectLabel(image=tex)
        icon.setScale(2.5)
        b = Box()
        b.fill(icon)                            
        self.lowDetailVBox.append(b)

        icon = DirectLabel(image=tex)
        b = Box()
        b.fill(icon)                                    
        self.highDetailVBox.append(b)

        # The longer description of the Propp function.
        self.entry  = DirectEntry(initialText=self.function.desc,
                                 text_font=loader.loadFont('storymaps/data/WritersFont.ttf'),
                                 scale=.4,
                                 width=13,
                                 numLines=7,
                                 suppressMouse=0,
                                 frameColor = (1,1,1,1))
        self.entry['state'] = DGG.DISABLED

        b = Box()
        b.setColor(1,1,1,0)
        b.fill(self.entry)                            
        self.highDetailVBox.append(b)

        self.lowDetailVBox.setPos(self.lowDetailVBox.np,-2.6,0,4)
        self.highDetailVBox.setPos(self.lowDetailVBox.getPos())

        self.highDetailVBox.hide()

        # A place for subclasses to put buttons.
        self.buttons = HBoxList()             
        self.buttons.reparentTo(self.np)   
        self.buttons.setScale(.6)
        self.buttons.setPos(-1.8,0,-1.6)
        self.buttons.hide()

        self.disabled = False

    def set_detail(self,detail):        
        if detail == "high":
            self.lowDetailVBox.hide()
            self.highDetailVBox.show()            
        elif detail == "low":
            self.lowDetailVBox.show()
            self.highDetailVBox.hide()
        else:
            raise Exception('Argument to set_detail must be "high" or "low".')

    def set_editable(self,boolean):        
        if boolean:
            self.entry['state'] = DGG.NORMAL
            self.entry['focus'] = 1
        else:
            self.entry['state'] = DGG.DISABLED
            self.entry['focus'] = 0
        
    def show_buttons(self,boolean):    
        if boolean:
            self.buttons.show()
        else:
            self.buttons.hide()

    def disable(self):
        disabled_color = Point4(.5,.5,.5,1)
        self.np.setColor(disabled_color)
        for box in self.lowDetailVBox:
            box.contents.setColor(disabled_color)    
        for box in self.highDetailVBox:
            box.contents.setColor(disabled_color)
        for box in self.buttons:
            box.contents.setColor(disabled_color)
        self.set_highlightable(False)
        self.set_draggable(False)        
        self.disabled = True

    def enable(self):
        color = Point4(1,1,1,1)
        self.np.setColor(color)
        for box in self.lowDetailVBox:
            box.contents.setColor(color)    
        for box in self.highDetailVBox:
            box.contents.setColor(color)
        for box in self.buttons:
            box.contents.setColor(color)
        self.set_highlightable(True)
        self.set_draggable(True)
        self.disabled = False

       
    # Implement the Originator interface of the Memento pattern for saving and
    # restoring user content. 
    class Memento(Memento):
        def __init__(self,function,text,cls,disabled):
            self.function = function
            self.text = text
            self.cls = cls
            self.disabled = disabled
        def __str__(self):
            return '\n\n' + self.function.__str__() + '\n\n' + self.text
    def create_memento(self):
        return StoryCard.Memento(self.function,self.entry.get(),self.__class__,self.disabled)
    def restore_memento(self,memento):    
        self.entry.enterText(memento.text)
        if memento.disabled: self.disable()
コード例 #6
0
ファイル: story.py プロジェクト: PlumpMath/PandaZUI
    def __init__(self):

        # Create two story maps, 'Story Cards' which the user picks story cards
        # from, and 'My Story Map' in which the user constructs her story.
        self.storyCards = StoryMap(storyCardClass=FocusableChoosableStoryCard,
                                   title="Story Cards")
        self.storyCards.reparentTo(zcanvas.home)
        self.storyCards.setScale(0.02)
        self.storyCards.setPos(-.5, 0, .8)
        self.storyCards.fill()
        self.storyCards.added_behaviour = 'disable'

        self.myStoryMap = StoryMap(storyCardClass=FocusableEditableStoryCard,
                                   title="My Story")
        self.myStoryMap.reparentTo(zcanvas.home)
        self.myStoryMap.setScale(0.02)
        self.myStoryMap.setPos(-.5, 0, -.1)
        self.myStoryMap.added_behaviour = 'remove'
        #self.myStoryMap.keep_sorted = True
        #self.myStoryMap.np.showTightBounds()
        self.myStoryMap.auto_grow = True

        # Keyboard controls for saving, loading and exporting.
        #base.accept("f1",self.save)
        #base.accept("f2",self.load)
        #base.accept("f3",self.export)

        # Subscribe to some messages.
        self.acceptOnce('zoom done', zcanvas.message,
                        ["Right-click to zoom back out again."])
        self.accept('add', self.add)
        self.accept('remove', self.remove)

        # Frame along the bottom for Save, Load and Quit buttons.
        self.bottom_np = aspect2d.attachNewNode('bottom frame')
        height = 0.15
        self.bottom_np.setPos(-base.getAspectRatio(), 0, -1 - height)
        cm = CardMaker('bottom frame')
        cm.setFrame(0, 2 * base.getAspectRatio(), 0, height)
        self.bottom_np.attachNewNode(cm.generate())
        self.bottom_np.setTransparency(TransparencyAttrib.MAlpha)
        self.bottom_np.setColor(.1, .1, .1, .7)
        self.bottom_hbox = HBoxList(margin=1)
        self.bottom_hbox.reparentTo(self.bottom_np)
        self.bottom_hbox.setPos(0, 0, height - 0.03)
        self.bottom_hbox.setScale(.1)
        self.save_button = DirectButton(text="Save", command=self.save)
        b = Box()
        b.fill(self.save_button)
        self.bottom_hbox.append(b)
        self.load_button = DirectButton(text="Load", command=self.load)
        b = Box()
        b.fill(self.load_button)
        self.bottom_hbox.append(b)
        # Interval that slides the frame onto the screen.
        self.bottom_interval = LerpPosInterval(
            self.bottom_np,
            duration=1,
            pos=Point3(-base.getAspectRatio(), 0, -1),
            startPos=Point3(-base.getAspectRatio(), 0, -1 - height),
            other=None,
            blendType='easeInOut',
            bakeInStart=1,
            fluid=0,
            name=None)
        self.bottom_reverse_interval = LerpPosInterval(
            self.bottom_np,
            duration=1,
            pos=Point3(-base.getAspectRatio(), 0, -1 - height),
            startPos=Point3(-base.getAspectRatio(), 0, -1),
            other=None,
            blendType='easeInOut',
            bakeInStart=1,
            fluid=0,
            name=None)
        self.bottom_frame_is_active = False

        # Frame along the right for story cards.
        self.right_np = aspect2d.attachNewNode('right frame')
        width = 0.14 * base.getAspectRatio()
        self.right_np.setPos(base.getAspectRatio() + width, 0, 1)
        cm = CardMaker('right frame')
        cm.setFrame(-width, 0, -2, 0)
        self.right_np.attachNewNode(cm.generate())
        self.right_np.setTransparency(TransparencyAttrib.MAlpha)
        self.right_np.setColor(.1, .1, .1, .7)
        self.right_vbox = Stack()
        self.right_vbox.reparentTo(self.right_np)
        self.right_vbox.setPos(-width + 0.035, 0, -0.06)
        self.right_vbox.setScale(.02)
        # Interval that slides the frame onto the screen.
        self.right_interval = LerpPosInterval(
            self.right_np,
            duration=1,
            pos=Point3(base.getAspectRatio(), 0, 1),
            startPos=Point3(base.getAspectRatio() + width, 0, 1),
            other=None,
            blendType='easeInOut',
            bakeInStart=1,
            fluid=0,
            name=None)
        self.right_reverse_interval = LerpPosInterval(
            self.right_np,
            duration=1,
            pos=Point3(base.getAspectRatio() + width, 0, 1),
            startPos=Point3(base.getAspectRatio(), 0, 1),
            other=None,
            blendType='easeInOut',
            bakeInStart=1,
            fluid=0,
            name=None)
        self.right_frame_is_active = False

        # Task that watches for the mouse going to the screen edges and slides
        # the frames onscreen when it does.
        self.prev_x = None
        self.prev_y = None
        taskMgr.add(self.task, 'Mediator mouse watcher task')

        NodePathWrapper.__init__(self)
        FocusObserver.__init__(self)
コード例 #7
0
ファイル: story.py プロジェクト: PlumpMath/PandaZUI
class Mediator(Receiver, FocusObserver, NodePathWrapper):
    """The singleton mediatorobject mediates the interaction between the
    StoryMap objects, receiving notifications and calling methods on StoryMap
    objects.

    """
    def __init__(self):

        # Create two story maps, 'Story Cards' which the user picks story cards
        # from, and 'My Story Map' in which the user constructs her story.
        self.storyCards = StoryMap(storyCardClass=FocusableChoosableStoryCard,
                                   title="Story Cards")
        self.storyCards.reparentTo(zcanvas.home)
        self.storyCards.setScale(0.02)
        self.storyCards.setPos(-.5, 0, .8)
        self.storyCards.fill()
        self.storyCards.added_behaviour = 'disable'

        self.myStoryMap = StoryMap(storyCardClass=FocusableEditableStoryCard,
                                   title="My Story")
        self.myStoryMap.reparentTo(zcanvas.home)
        self.myStoryMap.setScale(0.02)
        self.myStoryMap.setPos(-.5, 0, -.1)
        self.myStoryMap.added_behaviour = 'remove'
        #self.myStoryMap.keep_sorted = True
        #self.myStoryMap.np.showTightBounds()
        self.myStoryMap.auto_grow = True

        # Keyboard controls for saving, loading and exporting.
        #base.accept("f1",self.save)
        #base.accept("f2",self.load)
        #base.accept("f3",self.export)

        # Subscribe to some messages.
        self.acceptOnce('zoom done', zcanvas.message,
                        ["Right-click to zoom back out again."])
        self.accept('add', self.add)
        self.accept('remove', self.remove)

        # Frame along the bottom for Save, Load and Quit buttons.
        self.bottom_np = aspect2d.attachNewNode('bottom frame')
        height = 0.15
        self.bottom_np.setPos(-base.getAspectRatio(), 0, -1 - height)
        cm = CardMaker('bottom frame')
        cm.setFrame(0, 2 * base.getAspectRatio(), 0, height)
        self.bottom_np.attachNewNode(cm.generate())
        self.bottom_np.setTransparency(TransparencyAttrib.MAlpha)
        self.bottom_np.setColor(.1, .1, .1, .7)
        self.bottom_hbox = HBoxList(margin=1)
        self.bottom_hbox.reparentTo(self.bottom_np)
        self.bottom_hbox.setPos(0, 0, height - 0.03)
        self.bottom_hbox.setScale(.1)
        self.save_button = DirectButton(text="Save", command=self.save)
        b = Box()
        b.fill(self.save_button)
        self.bottom_hbox.append(b)
        self.load_button = DirectButton(text="Load", command=self.load)
        b = Box()
        b.fill(self.load_button)
        self.bottom_hbox.append(b)
        # Interval that slides the frame onto the screen.
        self.bottom_interval = LerpPosInterval(
            self.bottom_np,
            duration=1,
            pos=Point3(-base.getAspectRatio(), 0, -1),
            startPos=Point3(-base.getAspectRatio(), 0, -1 - height),
            other=None,
            blendType='easeInOut',
            bakeInStart=1,
            fluid=0,
            name=None)
        self.bottom_reverse_interval = LerpPosInterval(
            self.bottom_np,
            duration=1,
            pos=Point3(-base.getAspectRatio(), 0, -1 - height),
            startPos=Point3(-base.getAspectRatio(), 0, -1),
            other=None,
            blendType='easeInOut',
            bakeInStart=1,
            fluid=0,
            name=None)
        self.bottom_frame_is_active = False

        # Frame along the right for story cards.
        self.right_np = aspect2d.attachNewNode('right frame')
        width = 0.14 * base.getAspectRatio()
        self.right_np.setPos(base.getAspectRatio() + width, 0, 1)
        cm = CardMaker('right frame')
        cm.setFrame(-width, 0, -2, 0)
        self.right_np.attachNewNode(cm.generate())
        self.right_np.setTransparency(TransparencyAttrib.MAlpha)
        self.right_np.setColor(.1, .1, .1, .7)
        self.right_vbox = Stack()
        self.right_vbox.reparentTo(self.right_np)
        self.right_vbox.setPos(-width + 0.035, 0, -0.06)
        self.right_vbox.setScale(.02)
        # Interval that slides the frame onto the screen.
        self.right_interval = LerpPosInterval(
            self.right_np,
            duration=1,
            pos=Point3(base.getAspectRatio(), 0, 1),
            startPos=Point3(base.getAspectRatio() + width, 0, 1),
            other=None,
            blendType='easeInOut',
            bakeInStart=1,
            fluid=0,
            name=None)
        self.right_reverse_interval = LerpPosInterval(
            self.right_np,
            duration=1,
            pos=Point3(base.getAspectRatio() + width, 0, 1),
            startPos=Point3(base.getAspectRatio(), 0, 1),
            other=None,
            blendType='easeInOut',
            bakeInStart=1,
            fluid=0,
            name=None)
        self.right_frame_is_active = False

        # Task that watches for the mouse going to the screen edges and slides
        # the frames onscreen when it does.
        self.prev_x = None
        self.prev_y = None
        taskMgr.add(self.task, 'Mediator mouse watcher task')

        NodePathWrapper.__init__(self)
        FocusObserver.__init__(self)

    def enterNone(self):
        """Viewport focus has changed to None."""
        # Make the title of 'My Story Map' editable.
        self.myStoryMap.title['state'] = DGG.NORMAL

    def exitNone(self):
        """Undo any changes made by enterNone."""
        self.myStoryMap.title['state'] = DGG.DISABLED

    def task(self, task):
        if base.mouseWatcherNode.hasMouse():
            x = base.mouseWatcherNode.getMouseX()
            y = base.mouseWatcherNode.getMouseY()
            if y <= -0.87 and self.prev_y > -0.87:
                # The mouse has just moved into the bottom frame's area.
                self.activate_bottom_frame()
            elif y > -0.87 and self.prev_y <= -0.87:
                # The mouse has just moved out of the bottom frame's area.
                self.deactivate_bottom_frame()
            self.prev_y = y
            if x >= 0.8 and self.prev_x < 0.8:
                # The mouse has just moved into the right frame's area.
                self.activate_right_frame()
            elif x < 0.8 and self.prev_x >= 0.8:
                # The mouse has just moved out of the right frame's area.
                self.deactivate_right_frame()
            self.prev_x = x
        return task.cont

    def activate_bottom_frame(self):

        if not self.bottom_frame_is_active:
            self.bottom_interval.start()
            self.bottom_frame_is_active = True

    def deactivate_bottom_frame(self):

        if self.bottom_frame_is_active:
            self.bottom_reverse_interval.start()
            self.bottom_frame_is_active = False

    def activate_right_frame(self):
        if not self.right_frame_is_active:
            self.right_interval.start()
            self.right_frame_is_active = True

    def deactivate_right_frame(self):
        if self.right_frame_is_active:
            self.right_reverse_interval.start()
            self.right_frame_is_active = False

    def add(self, card):
        # The Add button was pressed on one of the StoryCards in self.storyCards
        for box in self.right_vbox:
            if box.contents is None:
                box.fill(card)
                # self.activate_right_frame()
                return
        zcanvas.message(
            'The stack is full!\nDrag another card from the stack first.')

    def remove(self, editableCard):
        # The Remove button was pressed on one of the StoryCards in
        # self.myStoryMap
        editableCard.getPythonTag('box').empty()
        for choosableCard in self.storyCards.items():
            if choosableCard.function == editableCard.function:
                choosableCard.enable()
                return

    # Implement the Originator interface of the memento design pattern. (For
    # saving and loading.)
    class Memento:
        """A passive class that stores the state of a Mediator object."""
        def __init__(self, storycards, mystorymap, stack):
            # MediatorMemento just holds mementos for mediator's two StoryMap
            # objects.
            self.storycards = storycards
            self.mystorymap = mystorymap
            self.stack = stack

        def __str__(self):
            return self.mystorymap.__str__()

    def create_memento(self):
        """Return a memento object holding the current internal state of this
        object."""

        return Mediator.Memento(self.storyCards.create_memento(),
                                self.myStoryMap.create_memento(),
                                self.right_vbox.create_memento())

    def restore_memento(self, memento):
        """Restore the internal state of this object to that held by the given
        memento."""

        self.storyCards.restore_memento(memento.storycards)
        self.myStoryMap.restore_memento(memento.mystorymap)
        self.right_vbox.restore_memento(memento.stack)

    # Implement the Caretaker interface of the memento design pattern. (For
    # saving and loading.)
    def save(self):
        """Save the current state of the application to file."""
        memento = self.create_memento()
        import datetime
        f = open(
            str(datetime.datetime.now()).replace(' ', '_') + '.saved_story',
            'w')
        cPickle.dump(memento, f)
        f.close()
        zcanvas.message("Saved!")

    def _load(self, args):
        self.load_list.removeNode()
        f = open(args, 'r')
        memento = cPickle.load(f)
        f.close()
        self.restore_memento(memento)
        taskMgr.doMethodLater(1,
                              zcanvas.message,
                              'Welcome Message',
                              extraArgs=["Loaded!"])

    def load(self):
        """Restore the current state of the application from file."""
        dir = '.'
        ext = '.saved_story'
        saved_stories = [
            f for f in os.listdir(dir)
            if os.path.isfile(os.path.join(dir, f)) and f.endswith(ext)
        ]
        saved_stories.sort()

        from direct.gui.DirectGui import DirectScrolledList, DirectButton
        labels = []
        for saved_story in saved_stories:
            filename, ext = os.path.splitext(saved_story)
            l = DirectButton(text=filename,
                             scale=0.05,
                             command=self._load,
                             extraArgs=[saved_story])
            labels.append(l)
        self.load_list = DirectScrolledList(
            decButton_pos=(0.35, 0, 0.53),
            decButton_text="/\\",
            decButton_text_scale=0.04,
            decButton_borderWidth=(0.005, 0.005),
            incButton_pos=(0.35, 0, -0.02),
            incButton_text="\\/",
            incButton_text_scale=0.04,
            incButton_borderWidth=(0.005, 0.005),

            #frameSize = (0.0, 0.7, -0.05, 0.59),
            #frameColor = (1,0,0,0.5),
            pos=self.load_button.getPos(aspect2d),
            items=labels,
            numItemsVisible=4,
            forceHeight=0.11,
            itemFrame_frameSize=(-0.3, 0.3, -0.37, 0.11),
            itemFrame_pos=(0.35, 0, 0.4),
        )

    def export(self):
        """Export the current story to a text file."""
        memento = self.create_memento()
        try:
            f = open("story.txt", "w")
            try:
                f.write(memento.__str__())
            finally:
                f.close()
        except IOError:
            print 'IOError while exporting story!'
コード例 #8
0
ファイル: boxlist_demo.py プロジェクト: seanh/PandaZUI
    cm = CardMaker('cm')
    cm.setFrame(-.1,.1,-.1,.1)

    def __init__(self):
    
        ZNode.__init__(self,geomnode = DemoItem.cm.generate())
        Draggable.__init__(self)
        self.set_draggable(True)
        Highlightable.__init__(self)
        self.set_highlightable(True)
        # FIXME. zoomable is required to make highlightable work because of the
        # collision mask. It shouldn't be.
        self.set_zoomable(True)

hbox = HBoxList()
hbox.setPos(-.5,0,.4)
hbox.reparentTo(zcanvas.home)
for i in range(5):
    b = Box(geomnode=DemoItem.cm.generate())    
    hbox.append(b)
    i = DemoItem()
    b.fill(i)

vbox = VBoxList()
vbox.setPos(-.5,0,.25)
vbox.reparentTo(zcanvas.home)
for i in range(5):
    b = Box(geomnode=DemoItem.cm.generate())    
    vbox.append(b)