diff --git a/scripting.py b/scripting.py index d1a1dbe..d18f614 100644 --- a/scripting.py +++ b/scripting.py @@ -489,6 +489,49 @@ class SyntPrint(SyntDesc): def Eval(self, env): env.GlobalMsg(self.expr.Eval(env)) +class SyntDialogBlock(SyntBlock): + def StypeForChild(self, syntChild): + return StypeDialogElement() + + def Eval(self, env): + rgmi = [] + for synt in self.rgsynt: + rgmiChild = synt.Eval(env) + if rgmiChild != None: + rgmi += rgmiChild + else: + rgmi.append(None) + return rgmi + +class SyntDialogIf(SyntIf): + desc = [["If"], " ", RtypeFlag(), " is ", (StypeFlagTest(), SyntIsFlagSet), ", then:", SyntDialogBlock, "or else:", SyntDialogBlock] + +class SyntDialogText(SyntDesc): + desc = [["Text"], ": \"", SyntText, "\""] + text = SyntDesc.DefProp(0) + def StButtonText(self, env): + return self.text.Eval(env) + def Eval(self, env): + return [MiDgText(Partial(self.StButtonText, env))] + +class SyntDialogOption(SyntDesc): + desc = [["Option"], " \"", SyntText, "\" is selected:", SyntBlock] + text = SyntDesc.DefProp(0) + exprOnSelect = SyntDesc.DefProp(1) + def Eval(self, env): + return [MiButton(self.text.Eval(env), Partial(env.OnDialogOptionSelected, self.exprOnSelect))] + +class StypeDialogElement(StypeEnum): + rgclsSynt = [SyntDialogText, SyntDialogOption, SyntDialogIf] + +@RegStmt +class SyntDialog(SyntDesc): + desc = [["Show dialog"], ":", SyntDialogBlock] + dialog = SyntDesc.DefProp(0) + def Eval(self, env): + rgmi = self.dialog.Eval(env) + env.ShowDialog(MiMenu([None] + rgmi + [None])) + class Fail(TPrs): """ Failure object. Our scripting language has no exceptions; instead, if a failure object is involved in a calculation, diff --git a/world.py b/world.py index 8395c74..4b911d4 100644 --- a/world.py +++ b/world.py @@ -17,7 +17,7 @@ import ansi_cython as ansi from tpers import TPrs, Partial from scripting import Vm from basetoken import AutoJoiner, AutoKiller, MsgScroller, Mi, MiButton, MiTypein, MiMenu, OvPopup -from basetoken import LeaveJoinToken, Selor +from basetoken import LeaveJoinToken, Selor, OvMenu from util import RgstWrapped from engine import Game, Token, TokenClient, Event from datetime import datetime @@ -212,9 +212,6 @@ class Joiner(LeaveJoinToken): self.msgScroller.evPost.fire(client.cld.user + " has left! :(") self.game.Chat().Add(ChlSys(client, "has left")) -## TODO: -## - fix lobby numbering (clients either editing or playing a game) - class Player(TokenClient): def InitPersistent(self, owner, client): TokenClient.InitPersistent(self, owner, client, "drawable", "player") @@ -224,6 +221,8 @@ class Player(TokenClient): miQuit = MiButton("Leave Game", self.client.leaveGame) self.mi = MiMenu([None, MiChat(self.client, 13, chat), MiTypein(Partial(chat.SendMsg, self.client)), None, miQuit, None]) self.ovPopup = OvPopup(self, self.client, self.mi) + self.ovDialog = None + self.evDialogDismiss = Event(self.game) def die(self): self.vm.RemovePlayer(self.rbot) @@ -264,8 +263,27 @@ class Player(TokenClient): def GlobalMsg(self, stMsg): self.game.rgtoken("msgscroller")[0].evPost.fire(stMsg) -# idea: synchronous event pair to implement "show message" w/ blocking + def OnDialogOptionSelected(self, synt): + self.evDialogDismiss.fire(synt) + return True + def DismissDialog(self): + if self.ovDialog: + self.ovDialog.die() + self.ovDialog = None + + def ShowDialog(self, mi): + self.DismissDialog() + self.ovDialog = OvMenu(self, self.client, mi, OvMenu.MIDDLE) + while self.ovDialog: + ev, val = Event.select(self, self.evDialogDismiss, self.EvKey()) + if ev == self.evDialogDismiss: + self.DismissDialog() + val.Eval(self) + break + elif val == ansi.K_TAB: + self.DismissDialog() + class GameWorld(Game): def InitPersistent(self, board): Game.InitPersistent(self)