source: trunk/game/scripts/dialoguegui.py @ 300

Revision 290, 6.1 KB checked in by orlandov, 10 years ago (diff)

Add a new test to fix broken unit test introduced by or1andov--

Line 
1#!python
2
3#   This file is part of PARPG.
4
5#   PARPG is free software: you can redistribute it and/or modify
6#   it under the terms of the GNU General Public License as published by
7#   the Free Software Foundation, either version 3 of the License, or
8#   (at your option) any later version.
9
10#   PARPG is distributed in the hope that it will be useful,
11#   but WITHOUT ANY WARRANTY; without even the implied warranty of
12#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13#   GNU General Public License for more details.
14
15#   You should have received a copy of the GNU General Public License
16#   along with PARPG.  If not, see <http://www.gnu.org/licenses/>.
17
18import pychan
19import fife
20import pychan.widgets as widgets
21from scripts.dialogue import DialogueEngine
22
23class Player(object):
24    """A mock player object until we have a proper Player/Quest model"""
25    def __init__(self):
26        self.current_quests = set()
27        self.finished_quests = set()
28
29    def canAcceptQuest(self, quest):
30        return     quest not in self.finished_quests \
31               and quest not in self.current_quests
32
33    def hasSatisfiedQuest(self, quest):
34        return quest in self.current_quests
35
36    def startQuest(self, quest):
37        if quest in self.current_quests:
38            raise RuntimeError("Already have quest, %s" % quest)
39        self.current_quests.add(quest)
40
41    def completeQuest(self, quest):
42        self.finished_quests.add(quest)
43        self.current_quests.remove(quest)
44
45class DialogueGUI(object):
46    def __init__(self, npc):
47        dialogue_callbacks = {
48            'say': self.handleSay,
49            'responses': self.handleResponses,
50            'start_quest': self.startQuest,
51            'complete_quest': self.completeQuest,
52            'npc_avatar': self.handleAvatarImage,
53            'end': self.handleEnd
54        }
55
56        # For testing purposes we're just using a a dummy player object  here
57        # until we decide on a player/quest model.
58        # TODO
59        # link this up to the actual PC and NPC instances, so that state can
60        # be persistent.
61        pc = Player()
62        self.npc = npc
63        state = {
64            'pc': pc
65        }
66        self.dialogue_engine = DialogueEngine('dialogue/sample.yaml',
67                                              dialogue_callbacks, state)
68        self.dialogue_gui = pychan.loadXML("gui/dialogue.xml")
69
70    def startQuest(self, state, quest):
71        """Callback for starting a quest"""
72        print "You've picked up the '%s' quest!" % quest,
73        state['pc'].startQuest(quest)
74
75    def completeQuest(self, state, quest):
76        """Callback for starting a quest"""
77        print "You've finished the '%s' quest" % quest
78        state['pc'].completeQuest(quest)
79
80    def initiateDialogue(self):
81        """Callback for starting a quest"""
82        stats_label = self.dialogue_gui.findChild(name='stats_label')
83        stats_label.text = u'Name: Ronwell\nA grizzled villager'
84
85        events = {
86            'end_button': self.handleEnd
87        }
88        self.dialogue_gui.mapEvents(events)
89        self.dialogue_gui.show()
90        responses_list = self.dialogue_gui.findChild(name='choices_list')
91        responses = self.dialogue_engine.run()
92        self.setResponses(responses)
93
94    def handleSay(self, state, say):
95        """Callback for NPC speech"""
96        speech = self.dialogue_gui.findChild(name='speech')
97        # to append text to npc speech box, uncomment the following line
98        #speech.text = speech.text + "\n-----\n" + unicode(say)
99        speech.text = unicode(say)
100
101    def handleEntered(self, *args):
102        """Callback for when user hovers over response label"""
103        pass
104
105    def handleExited(self, *args):
106        """Callback for when user hovers out of response label"""
107        pass
108
109    def handleClicked(self, *args):
110        """Handle a response being clicked"""
111        response = int(args[0].name.replace('response', ''))
112        if not self.dialogue_engine.reply(response):
113            self.handleEnd()
114
115    def handleEnd(self):
116        """Handle the end of the conversation being reached. Either from the
117           GUI or from within the conversation itself."""
118        self.dialogue_engine = None
119        self.dialogue_gui.hide()
120        self.npc.behaviour.state = 1
121        self.npc.behaviour.idle()
122
123    def handleAvatarImage(self, state, image):
124        """Callback to handle when the dialogue engine wants to set the NPC image
125           @type image: str
126           @param image: filename of avatar image"""
127        avatar_image = self.dialogue_gui.findChild(name='npc_avatar')
128        avatar_image.image = image
129
130    def handleResponses(self, *args):
131        """Callback to handle when the dialogue engine wants to display a new
132           list of options"""
133        self.setResponses(args[1])
134
135    def setResponses(self, responses):
136        """Creates the list of clickable response labels and sets their
137           respective on-click callbacks
138           @type responses: [ [ "response text", section, condition ], ...]
139           @param responses: the list of response objects from the dialogue
140                             engine"""
141        choices_list = self.dialogue_gui.findChild(name='choices_list')
142        choices_list.removeAllChildren()
143        for i,r in enumerate(responses):
144            button = widgets.Label(
145                name="response%s"%(i,),
146                text=unicode(r[0]),
147                hexpand="1",
148                min_size=(100,16),
149                max_size=(490,48),
150                position_technique='center:center'
151            )
152            button.margins=(5,5)
153            button.background_color=fife.Color(0,0,0)
154            button.color=fife.Color(0,255,0)
155            button.border_size = 0
156            button.wrap_text = 1
157            button.capture(lambda button=button: self.handleEntered(button), event_name='mouseEntered')
158            button.capture(lambda button=button: self.handleExited(button), event_name='mouseExited')
159            button.capture(lambda button=button: self.handleClicked(button), event_name='mouseClicked')
160            choices_list.addChild(button)
161            self.dialogue_gui.adaptLayout(True)
162
163
Note: See TracBrowser for help on using the repository browser.