add sprite / animation support

add support for returning to the spot where you left off in the lobby
move meta information out of drawing name and off to the side
This commit is contained in:
Jeremy Penner 2011-10-05 17:50:18 -04:00
parent 70529b610f
commit 19fe12a12a

View file

@ -19,8 +19,6 @@ class Layer(TPrs):
def SetName(self, st): def SetName(self, st):
self.stName = st self.stName = st
def Draw(self, ascr):
ascr.PutAscr(self.ascr)
def FSelectable(self): def FSelectable(self):
return True return True
@ -29,30 +27,38 @@ class Project(Ownable):
Ownable.InitPersistent(self, owner) Ownable.InitPersistent(self, owner)
self.stName = stName self.stName = stName
self.user = user self.user = user
self.rgboard = [] self.rgdrawing = []
self.rgscript = [] self.rgscript = []
def NewBoard(self, stName, user): def NewBoard(self, stName, user):
board = Board(self, stName, user) board = Board(self, stName, user)
self.rgboard.insert(0, board) self.rgdrawing.insert(0, board)
return board return board
def BoardTouched(self, board):
if board != self.rgboard[0]: def NewSprite(self, stName, user, w, h):
self.rgboard.remove(board) sprite = Sprite(self, stName, user, w, h)
self.rgboard.insert(0, board) self.rgdrawing.insert(0, sprite)
self.owner.BoardTouched(board) return sprite
def DrawingTouched(self, drawing):
if drawing != self.rgdrawing[0]:
self.rgdrawing.remove(drawing)
self.rgdrawing.insert(0, drawing)
self.owner.DrawingTouched(drawing)
def StName(self): def StName(self):
return self.owner.StNameProject(self) return self.owner.StNameProject(self)
def StLastModified(self): def StLastModified(self):
boardLast = None drawingLast = None
for board in self.rgboard: for drawing in self.rgdrawing:
if boardLast == None or board.dtLastModified > boardLast.dtLastModified: if drawingLast == None or drawing.dtLastModified > drawingLast.dtLastModified:
boardLast = board drawingLast = drawing
if boardLast != None: if drawingLast != None:
return boardLast.StLastModified() return drawingLast.StLastModified()
return "never" return "never"
def RgstMetadata(self):
@Version(3) return ["by " + self.user, "", "Last modified:", self.StLastModified()]
class Board(Ownable):
class Drawing(Ownable):
def InitPersistent(self, owner, stName, user, rglayer=None, dtLastModified=None): def InitPersistent(self, owner, stName, user, rglayer=None, dtLastModified=None):
Ownable.InitPersistent(self, owner) Ownable.InitPersistent(self, owner)
if rglayer == None: if rglayer == None:
@ -65,9 +71,13 @@ class Board(Ownable):
self.SetTimestamp() self.SetTimestamp()
else: else:
self.dtLastModified = dtLastModified self.dtLastModified = dtLastModified
def StName(self): def StName(self):
return self.owner.owner.StNameBoard(self) return self.owner.owner.StNameDrawing(self)
def RgstMetadata(self):
return [self.StType(), "by " + self.user, "", "Last modified", self.StLastModified()]
def StLastModified(self): def StLastModified(self):
return self.dtLastModified.strftime("%b %d, %Y at %I:%M%p") return self.dtLastModified.strftime("%b %d, %Y at %I:%M%p")
@ -92,19 +102,23 @@ class Board(Ownable):
self.rglayer.remove(layer) self.rglayer.remove(layer)
self.rglayer.insert(ilayer, layer) self.rglayer.insert(ilayer, layer)
def W(self): return config.W
def H(self): return config.H
def Touch(self): def Touch(self):
self.SetTimestamp() self.SetTimestamp()
self.owner.BoardTouched(self) self.owner.DrawingTouched(self)
def SetTimestamp(self): def SetTimestamp(self):
self.dtLastModified = datetime.now() self.dtLastModified = datetime.now()
@Version(3)
class Board(Drawing):
def StType(self):
return "Board"
def W(self): return config.W
def H(self): return config.H
def draw(self, ascr): def draw(self, ascr):
for layer in reversed(self.rglayer): for layer in reversed(self.rglayer):
layer.Draw(ascr) ascr.PutAscr(layer.ascr)
def Save(self): def Save(self):
fn = config.DIR_ANSI + "/" + "_".join([str(x) for x in time.localtime()]) fn = config.DIR_ANSI + "/" + "_".join([str(x) for x in time.localtime()])
@ -116,7 +130,7 @@ class Board(Ownable):
fl.write("</center></body></html>") fl.write("</center></body></html>")
with open(fn + ".ans", "w") as fl: with open(fn + ".ans", "w") as fl:
fl.write(ascr.Ast()) fl.write(ascr.Ast())
def UpgradeFrom(self, versionOld): def UpgradeFrom(self, versionOld):
if versionOld < 2: if versionOld < 2:
gameWB = [gameWB for gameWB in self.owner.rggameWB if gameWB.rgtoken("whiteboard")[0].board == self][0] gameWB = [gameWB for gameWB in self.owner.rggameWB if gameWB.rgtoken("whiteboard")[0].board == self][0]
@ -125,6 +139,22 @@ class Board(Ownable):
if versionOld < 3: if versionOld < 3:
self.chat = Chat() self.chat = Chat()
class Sprite(Drawing):
def InitPersistent(self, owner, stName, user, w, h):
self.w = w
self.h = h
Drawing.InitPersistent(self, owner, stName, user, [Layer(ansi.Ascr(w, h), "Frame 1")])
def StType(self): return "Sprite"
def W(self): return self.w
def H(self): return self.h
def draw(self, ascr, x, y, iframe):
ascr.PutAscr(self.rglayer[iframe].ascr, x, y)
def RgstMetadata(self):
return [self.StType(), "by " + self.user, "", str(self.w) + "x" + str(self.h), str(len(self.rglayer)) + " frames", "", "Last modified", self.StLastModified()]
@Version(5) @Version(5)
class Whiteboard(Token): class Whiteboard(Token):
def InitPersistent(self, game, board): def InitPersistent(self, game, board):
@ -238,8 +268,15 @@ class Cursor(TokenClient):
TokenClient.InitPersistent(self, game, client, "drawable", "cursor") TokenClient.InitPersistent(self, game, client, "drawable", "cursor")
self.fBlink = False self.fBlink = False
self.cDontBlink = 0 self.cDontBlink = 0
self.whiteboard = self.game.rgtoken("whiteboard")[0].board self.pos = ansi.Pos(self.game.drawing.W(), self.game.drawing.H())
self.pos = ansi.Pos(self.whiteboard.W(), self.whiteboard.H()) self.SetupMenus()
self.SelectLayer(self.game.drawing.rglayer[0])
self.CreateDrawingToken()
def CreateDrawingToken(self):
WhiteboardDraw(self, self.client)
def SetupMenus(self):
miFg = MiColour("Foreground", ansi.rgcolorFg, ansi.WHITE) miFg = MiColour("Foreground", ansi.rgcolorFg, ansi.WHITE)
miBg = MiColour("Background", ansi.rgcolorBg, ansi.BLACK) miBg = MiColour("Background", ansi.rgcolorBg, ansi.BLACK)
miChars = MiChars([[49, 50, 51, 52, 53, 54, 55, 56, 57, 48], #digits miChars = MiChars([[49, 50, 51, 52, 53, 54, 55, 56, 57, 48], #digits
@ -259,21 +296,26 @@ class Cursor(TokenClient):
[139, 140, 141, 161, 153, 148, 147, 149, 162, 32], #i, o [139, 140, 141, 161, 153, 148, 147, 149, 162, 32], #i, o
[154, 129, 150, 151, 163, 32, 32, 32, 32, 32], #u [154, 129, 150, 151, 163, 32, 32, 32, 32, 32], #u
], miFg, miBg) ], miFg, miBg)
miQuit = MiButton("Back to Menu", self.client.leaveGame) miQuit = MiButton("Back to Menu", self.client.leaveGame)
self.cf = MiMenu([None, miFg, miBg, None, miChars, None, MiButton("Save", self.Save), None, miQuit, None]) self.cf = self.MenuDrawing(miFg, miBg, miChars, miQuit)
self.miChat = MiMenu([None, MiChat(client, 13, self.whiteboard.chat), MiTypein(self.SendMsg), None, miQuit, None]) self.miChat = MiMenu([None, MiChat(self.client, 13, self.game.drawing.chat), MiTypein(self.SendMsg), None, miQuit, None])
self.rgmiLayer = RgmiProjected(self.whiteboard.rglayer, DgProjectMiButton(self.SelectLayer)) self.rgmiLayer = RgmiProjected(self.game.drawing.rglayer, DgProjectMiButton(self.SelectLayer))
self.miLayers = MiMenu(Rgseq([None], self.rgmiLayer, [None, MiButton("New Layer", self.NewLayer), MiButton("Move up", self.LayerUp), MiButton("Move down", self.LayerDown), self.miLayers = self.MenuLayers(miQuit)
None, MiToggle("Show One"), None, MiStatic("Rename selected layer:"), MiTypein(self.RenameLayer, "LayerName", 80), None, miQuit, None])) self.ovPopup = OvPopup(self, self.client, MiTab.MiTabbed(["Drawing", self.cf], [self.StLayerTab(), self.miLayers], ["Chat", self.miChat]))
self.ovPopup = OvPopup(self, self.client, MiTab.MiTabbed(["Drawing", self.cf], ["Layers", self.miLayers], ["Chat", self.miChat]))
miStatus = MiMenuHoriz([MiStatic("Hit <Tab> for menu"), MiValue(miChars)]) miStatus = MiMenuHoriz([MiStatic("Hit <Tab> for menu"), MiValue(miChars)])
miStatus.ListenForNotice(self.miChat) miStatus.ListenForNotice(self.miChat)
self.ovStatus = OvStatic(self, self.client, miStatus, OvStatic.BOTTOM) self.ovStatus = OvStatic(self, self.client, miStatus, OvStatic.BOTTOM)
self.SelectLayer(self.whiteboard.rglayer[0]) def MenuDrawing(self, miFg, miBg, miChars, miQuit):
WhiteboardDraw(self, client) return MiMenu([None, miFg, miBg, None, miChars, None, MiButton("Save", self.Save), None, miQuit, None])
def MenuLayers(self, miQuit):
return MiMenu(Rgseq([None], self.rgmiLayer, [None, MiButton("New Layer", self.NewLayer), MiButton("Move up", self.LayerUp), MiButton("Move down", self.LayerDown),
None, MiToggle("Show One"), None, MiStatic("Rename selected layer:"), MiTypein(self.RenameLayer, "LayerName", 80), None, miQuit, None]))
def StLayerTab(self): return "Layers"
def Save(self): def Save(self):
self.whiteboard.Save() self.game.drawing.Save()
msgscroller = self.game.rgtoken("msgscroller")[0] msgscroller = self.game.rgtoken("msgscroller")[0]
msgscroller.evPost.fire("Saved picture") msgscroller.evPost.fire("Saved picture")
@ -290,20 +332,20 @@ class Cursor(TokenClient):
stLayer = None stLayer = None
while stLayer == None: while stLayer == None:
stLayer = "Layer " + str(ilayer) stLayer = "Layer " + str(ilayer)
if self.whiteboard.LayerByName(stLayer) != None: if self.game.drawing.LayerByName(stLayer) != None:
stLayer = None stLayer = None
ilayer = ilayer + 1 ilayer = ilayer + 1
layerNew = self.whiteboard.NewLayer(stLayer) layerNew = self.game.drawing.NewLayer(stLayer)
if layerNew != None: if layerNew != None:
self.SelectLayer(layerNew) self.SelectLayer(layerNew)
return True return True
def LayerUp(self): def LayerUp(self):
self.whiteboard.MoveLayer(self.GetLayer(), True) self.game.drawing.MoveLayer(self.GetLayer(), True)
return True return True
def LayerDown(self): def LayerDown(self):
self.whiteboard.MoveLayer(self.GetLayer(), False) self.game.drawing.MoveLayer(self.GetLayer(), False)
return True return True
def RenameLayer(self, st): def RenameLayer(self, st):
@ -318,16 +360,16 @@ class Cursor(TokenClient):
def SendMsg(self, st): def SendMsg(self, st):
if st.lower().startswith("/me ") and len(st.rstrip()) > 3: if st.lower().startswith("/me ") and len(st.rstrip()) > 3:
self.whiteboard.chat.Add(ChlAct(self.client, st[4:])) self.game.drawing.chat.Add(ChlAct(self.client, st[4:]))
else: else:
self.whiteboard.chat.Add(ChlMsg(self.client, st)) self.game.drawing.chat.Add(ChlMsg(self.client, st))
def OnChat(self, chl): def OnChat(self, chl):
if type(chl) != ChlSys: if type(chl) != ChlSys:
self.miChat.FlagNotice() self.miChat.FlagNotice()
def run(self): def run(self):
with self.whiteboard.chat.evChat.oob(self, self.OnChat): with self.game.drawing.chat.evChat.oob(self, self.OnChat):
while True: while True:
key = self.client.evKey.receive(self) key = self.client.evKey.receive(self)
fDontBlink = True fDontBlink = True
@ -370,21 +412,21 @@ class Cursor(TokenClient):
if fDontBlink: if fDontBlink:
self.cDontBlink = 2 if self.fBlink else 1 self.cDontBlink = 2 if self.fBlink else 1
if self.pos.Y() < self.whiteboard.H() / 2: if (self.game.drawing.H() < config.H) or (self.pos.Y() < self.game.drawing.H() / 2):
self.ovStatus.kplace = OvStatic.BOTTOM self.ovStatus.kplace = OvStatic.BOTTOM
else: else:
self.ovStatus.kplace = OvStatic.TOP self.ovStatus.kplace = OvStatic.TOP
def PutWb(self, ch): def PutWb(self, ch):
self.Put(ch, self.GetLayer().ascr) self.Put(ch, self.GetLayer().ascr)
self.whiteboard.Touch() self.game.drawing.Touch()
def Put(self, ch, ascr): def Put(self, ch, ascr, xzOffset = 0, yzOffset = 0):
if type(ch) == str: if type(ch) == str:
ach = ansi.MkAch(ch, self.cf.Value("Foreground"), self.cf.Value("Background")) ach = ansi.MkAch(ch, self.cf.Value("Foreground"), self.cf.Value("Background"))
else: else:
ach = ch ach = ch
ascr.PutAch(ach, self.pos.X(), self.pos.Y()) ascr.PutAch(ach, self.pos.X() + xzOffset, self.pos.Y() + yzOffset)
def GetAch(self): def GetAch(self):
return self.GetLayer().ascr.GetAch(self.pos.X(), self.pos.Y()) return self.GetLayer().ascr.GetAch(self.pos.X(), self.pos.Y())
@ -397,17 +439,59 @@ class Cursor(TokenClient):
while not fStop: while not fStop:
fStop = not dgMove() or self.GetAch() != ach fStop = not dgMove() or self.GetAch() != ach
def XzYzScreenPic(self):
layer = self.GetLayer()
return ((config.W - layer.ascr.W()) / 2, (config.H - layer.ascr.H()) / 2)
def FDrawCursor(self):
return self.fBlink or self.cDontBlink > 0
def draw(self, ascr, client): def draw(self, ascr, client):
if self.fBlink or self.cDontBlink > 0: if self.FDrawCursor():
if client == self.client: if client == self.client:
chCursor = chr(176) chCursor = chr(176)
ach = ascr.GetAch(self.pos.X(), self.pos.Y()) ach = ascr.GetAch(self.pos.X(), self.pos.Y())
if ach != None and ansi.ChFromAch(ach) == chCursor: if ach != None and ansi.ChFromAch(ach) == chCursor:
chCursor = chr(177) chCursor = chr(177)
self.Put(chCursor, ascr) self.Put(chCursor, ascr, *self.XzYzScreenPic())
elif self.fBlink: elif self.fBlink:
self.Put(str(self.client.Cldg().iclient)[0], ascr) self.Put(str(self.client.Cldg().iclient)[0], ascr, *self.XzYzScreenPic())
class CursorSprite(Cursor):
def InitPersistent(self, game, client):
Cursor.InitPersistent(self, game, client)
self.blinkerAnimate = None
def CreateDrawingToken(self):
SpriteDraw(self, self.client)
def MenuDrawing(self, miFg, miBg, miChars, miQuit):
return MiMenu([None, miFg, miBg, None, miChars, None, miQuit, None])
def MenuLayers(self, miQuit):
return MiMenu(Rgseq([None], self.rgmiLayer, [None, MiButton("New Frame", self.NewLayer), MiButton("Move up", self.LayerUp), MiButton("Move down", self.LayerDown),
None, MiStatic("Rename selected frame:"), MiTypein(self.RenameLayer, "LayerName", 80), None, MiButton("Animate", self.Animate), None, miQuit, None]))
def StLayerTab(self): return "Frames"
def NewLayer(self):
stLayer = "Frame " + str(len(self.game.drawing.rglayer) + 1)
layerNew = self.game.drawing.NewLayer(stLayer)
if layerNew != None:
self.SelectLayer(layerNew)
return True
def Animate(self):
if (self.blinkerAnimate == None):
self.blinkerAnimate = Blinker(self, self.SelectLayer, self.game.drawing.rglayer, interval = 300)
self.ovPopup.SetSelection("animate", self.miLayers.MiByName("Animate"))
else:
self.blinkerAnimate.die()
self.blinkerAnimate = None
self.ovPopup.SetSelection("animate", None)
def FDrawCursor(self):
if self.blinkerAnimate:
return False
return Cursor.FDrawCursor(self)
class WhiteboardDraw(TokenClient): class WhiteboardDraw(TokenClient):
def InitPersistent(self, owner, client): def InitPersistent(self, owner, client):
TokenClient.InitPersistent(self, owner, client, "drawable", "solid") TokenClient.InitPersistent(self, owner, client, "drawable", "solid")
@ -415,9 +499,31 @@ class WhiteboardDraw(TokenClient):
def draw(self, ascr, client): def draw(self, ascr, client):
if client == self.client: if client == self.client:
if self.owner.miLayers.Value("Show One"): if self.owner.miLayers.Value("Show One"):
self.owner.GetLayer().Draw(ascr) ascr.PutAscr(self.owner.GetLayer().ascr)
else: else:
self.owner.whiteboard.draw(ascr) self.game.drawing.draw(ascr)
class SpriteDraw(TokenClient):
def InitPersistent(self, owner, client):
TokenClient.InitPersistent(self, owner, client, "drawable", "solid")
def draw(self, ascr, client):
if client == self.client:
(xz, yz) = self.owner.XzYzScreenPic()
x = xz + 1
y = yz + 1
layer = self.owner.GetLayer()
ascr.PutAscr(layer.ascr, x, y)
# draw border
ascr.PutAch(ansi.MkAch(chr(218), ansi.WHITE | ansi.FBRIGHT), x - 1, y - 1) # top-left
ascr.PutAch(ansi.MkAch(chr(191), ansi.WHITE | ansi.FBRIGHT), x + layer.ascr.W(), y - 1) # top-right
ascr.PutAch(ansi.MkAch(chr(192), ansi.WHITE | ansi.FBRIGHT), x - 1, y + layer.ascr.H()) # bottom-left
ascr.PutAch(ansi.MkAch(chr(217), ansi.WHITE | ansi.FBRIGHT), x + layer.ascr.W(), y + layer.ascr.H()) # bottom-right
for yT in (y - 1, y + layer.ascr.H()):
ascr.PutSt(chr(196) * layer.ascr.W(), x, yT, ansi.WHITE | ansi.FBRIGHT) # -
for xT in (x - 1, x + layer.ascr.W()):
for yT in xrange(y, y + layer.ascr.H()):
ascr.PutAch(ansi.MkAch(chr(179), ansi.WHITE | ansi.FBRIGHT), xT, yT) # |
class CursorBlinker(Token): class CursorBlinker(Token):
def InitPersistent(self, owner): def InitPersistent(self, owner):
@ -539,7 +645,7 @@ class Joiner(LeaveJoinToken):
def InitPersistent(self, owner): def InitPersistent(self, owner):
Token.InitPersistent(self, owner) Token.InitPersistent(self, owner)
self.msgScroller = self.game.rgtoken("msgscroller")[0] self.msgScroller = self.game.rgtoken("msgscroller")[0]
self.board = self.game.rgtoken("whiteboard")[0].board self.board = self.game.drawing
def OnJoin(self, client): def OnJoin(self, client):
with client.Cldg().SetTransiently() as cldg: with client.Cldg().SetTransiently() as cldg:
@ -559,7 +665,11 @@ class Joiner(LeaveJoinToken):
class Lobby(TokenClient): class Lobby(TokenClient):
def InitPersistent(self, owner, client): def InitPersistent(self, owner, client):
TokenClient.InitPersistent(self, owner, client) TokenClient.InitPersistent(self, owner, client)
self.lobbyCurrent = LobbyProject(self, client) drawing = client.Cldg(self.game).drawingSelected
if drawing == None:
self.lobbyCurrent = LobbyProject(self, client)
else:
self.lobbyCurrent = LobbyBoard(self, client, drawing.owner, drawing)
def SwitchToLobby(self, lobbyNew): def SwitchToLobby(self, lobbyNew):
lobbyOld = self.lobbyCurrent lobbyOld = self.lobbyCurrent
@ -567,62 +677,88 @@ class Lobby(TokenClient):
lobbyOld.die() lobbyOld.die()
class LobbyI(TokenClient): class LobbyI(TokenClient):
def InitPersistent(self, owner, client, *rgmiListTop): def InitPersistent(self, owner, client, objSelected = None, *rgmiListTop):
TokenClient.InitPersistent(self, owner, client) TokenClient.InitPersistent(self, owner, client)
rgmiList = RgmiProjected(self.RgObj(), DgProjectMiButton(self.OnObjSelected)) rgmiList = RgmiProjected(self.RgObj(), DgProjectMiButton(self.OnObjSelected))
if rgmiListTop != None: if rgmiListTop != None:
rgmiList = Rgseq(rgmiListTop, rgmiList) rgmiList = Rgseq(rgmiListTop, rgmiList)
self.miDrawings = MiMenu(rgmiList) self.miDrawings = MiMenu(rgmiList)
self.miCmds = MiMenu([None, None, MiTypein(self.NewI, "ObjectName"), MiButton(self.StNewObj(), self.NewI), if objSelected:
None, None, None, None, None, None, None, None, MiStatic("Last modified:"), MiDgText(self.StLastModifiedI)]) mi = self.miDrawings.MiByName(objSelected.StName())
self.miDrawings.selMi.SetSelected(mi)
self.miCmds = self.CreateMiCmds()
OvMenu(self, client, MiMenuHoriz([self.miDrawings, self.miCmds], [65, 35]), OvMenu.FILL) OvMenu(self, client, MiMenuHoriz([self.miDrawings, self.miCmds], [65, 35]), OvMenu.FILL)
def StNewObj(self):
"Text for the 'New X' text field"
raise "not implemented"
def RgObj(self): def RgObj(self):
"Return the list of objects we are selecting from" "Return the list of objects we are selecting from"
raise "not implemented" raise "not implemented"
def OnObjSelected(self, obj): def OnObjSelected(self, obj):
"Called when an object is selected by the user" "Called when an object is selected by the user"
raise "not implemented" raise "not implemented"
def New(self, stName):
"Create a new object with the given name" def RgstMetadata(self, obj):
raise "not implemented" "Return a list of strings containing user-readable metadata about the object"
def StLastModified(self, obj):
"Return a string stating when the object was last modified"
raise "not implemented" raise "not implemented"
def StLastModifiedI(self): def StMetadata(self):
return self.StLastModified(self.miDrawings.Value()) try:
def NewI(self, stName = None): return "\n".join(self.RgstMetadata(self.miDrawings.Value()))
if stName == None: except:
stName = self.miCmds.Value("ObjectName") return ""
if stName != "":
self.New(stName) def MiTypein_MiButton(self, stBtnLabel, stMiTypein, dgOnSelect):
def NewI(stName = None):
if stName == None:
stName = self.miCmds.Value(stMiTypein)
if stName != "":
dgOnSelect(stName)
return (MiTypein(NewI, stMiTypein), MiButton(stBtnLabel, NewI))
class LobbyBoard(LobbyI): class LobbyBoard(LobbyI):
def InitPersistent(self, owner, client, project): def InitPersistent(self, owner, client, project, drawing = None):
self.project = project self.project = project
LobbyI.InitPersistent(self, owner, client, MiButton("<-- Back to projects", self.Back), None) LobbyI.InitPersistent(self, owner, client, drawing, MiButton("<-- Back to projects", self.Back), None)
def CreateMiCmds(self):
miTypeinBoard, miBtnNewBoard = self.MiTypein_MiButton("New Board", "BoardName", self.NewBoard)
miTypeinSpr, miBtnNewSpr = self.MiTypein_MiButton("New Sprite", "SpriteName", self.NewSprite)
miTypeinW = MiTypein(None, "w")
miTypeinW.SetValue("1")
miTypeinH = MiTypein(None, "h")
miTypeinH.SetValue("1")
self.miDimensions = MiMenuHoriz([MiStatic("W:"), miTypeinW, MiStatic("H:"), miTypeinH])
return MiMenu([None, None, miTypeinBoard, miBtnNewBoard, None, None, miTypeinSpr, self.miDimensions, miBtnNewSpr, None, None, None, None, None, MiDgText(self.StMetadata)])
def StNewObj(self):
return "New Board"
def RgObj(self): def RgObj(self):
return self.project.rgboard return self.project.rgdrawing
def OnObjSelected(self, board): def OnObjSelected(self, board):
self.client.leaveGame(board) self.client.leaveGame(board)
def New(self, stName): def NewBoard(self, stName):
self.OnObjSelected(self.project.NewBoard(stName, self.client.cld.user)) self.OnObjSelected(self.project.NewBoard(stName, self.client.cld.user))
def StLastModified(self, board): def NewSprite(self, stName):
try:
w = int(self.miDimensions.Value("w"))
h = int(self.miDimensions.Value("h"))
if 0 < w < config.W and 0 < h < config.H:
self.OnObjSelected(self.project.NewSprite(stName, self.client.cld.user, w, h))
except:
pass
def RgstMetadata(self, board):
if board != None: if board != None:
return board.StLastModified() return board.RgstMetadata()
return self.project.StLastModified() return self.project.RgstMetadata()
def Back(self): def Back(self):
self.owner.SwitchToLobby(LobbyProject(self.owner, self.client)) self.owner.SwitchToLobby(LobbyProject(self.owner, self.client, self.project))
class LobbyProject(LobbyI): class LobbyProject(LobbyI):
def CreateMiCmds(self):
miTypein, miBtnNew = self.MiTypein_MiButton("New Project", "ProjName", self.New)
return MiMenu([None, None, miTypein, miBtnNew, None, None, None, None, None, None, None, None, MiDgText(self.StMetadata)])
def StNewObj(self): def StNewObj(self):
return "New Project" return "New Project"
def RgObj(self): def RgObj(self):
@ -632,8 +768,8 @@ class LobbyProject(LobbyI):
def New(self, stName): def New(self, stName):
project = self.game.NewProject(stName, self.client.cld.user) project = self.game.NewProject(stName, self.client.cld.user)
self.OnObjSelected(project) self.OnObjSelected(project)
def StLastModified(self, project): def RgstMetadata(self, project):
return project.StLastModified() return project.RgstMetadata()
class RunnerWB(Runner): class RunnerWB(Runner):
def InitPersistent(self): def InitPersistent(self):
@ -642,9 +778,11 @@ class RunnerWB(Runner):
def RunGame(self, client): def RunGame(self, client):
if (client.joinGame(GameLogin())): if (client.joinGame(GameLogin())):
client.Cldg(self.gameLobby).drawingSelected = None
while True: while True:
board = client.joinGame(self.gameLobby) drawing = client.joinGame(self.gameLobby)
client.joinGame(self.gameLobby.GameFromBoard(board)) client.Cldg(self.gameLobby).drawingSelected = drawing
client.joinGame(self.gameLobby.GameFromDrawing(drawing))
class GameLogin(Game): class GameLogin(Game):
def GetRgclsTokTrans(self): def GetRgclsTokTrans(self):
@ -658,39 +796,44 @@ class GameLobby(Game):
def InitTransient(self): def InitTransient(self):
Game.InitTransient(self) Game.InitTransient(self)
self.mpboard_gameWB = {} self.mpdrawing_game = {}
def GetRgclsTokTrans(self): def GetRgclsTokTrans(self):
return [[AutoJoiner, Lobby]] return [[AutoJoiner, Lobby]]
def GameFromBoard(self, board): def GameFromDrawing(self, drawing):
if not (board in self.mpboard_gameWB): if not (drawing in self.mpdrawing_game):
gameWB = GameWB(self, board) if drawing.StType() == "Board":
game = GameWB(self, drawing)
elif drawing.StType() == "Sprite":
game = GameSprEdit(self, drawing)
else:
assert False, "Lobby not prepared to deal with drawing of type " + drawing.StType()
def KillBoard(): def KillBoard():
del self.mpboard_gameWB[board] del self.mpdrawing_game[drawing]
gameWB.rgdgdie.append(KillBoard) game.rgdgdie.append(KillBoard)
self.mpboard_gameWB[board] = gameWB self.mpdrawing_game[drawing] = game
return gameWB return game
return self.mpboard_gameWB[board] return self.mpdrawing_game[drawing]
def CclientBoard(self, board): def CclientDrawing(self, drawing):
if board in self.mpboard_gameWB: if drawing in self.mpdrawing_game:
return len(self.mpboard_gameWB[board].rgclient) return len(self.mpdrawing_game[drawing].rgclient)
return 0 return 0
def StNameProject(self, project): def StNameProject(self, project):
return project.stName + " (by " + project.user + ") [" + str(sum([self.CclientBoard(board) for board in project.rgboard])) + "]" return project.stName + " [" + str(sum([self.CclientDrawing(drawing) for drawing in project.rgdrawing])) + "]"
def StNameBoard(self, board): def StNameDrawing(self, drawing):
return board.stName + " (by " + board.user + ") [" + str(self.CclientBoard(board)) + "]" return drawing.stName + " [" + str(self.CclientDrawing(drawing)) + "]"
def NewProject(self, stName, user): def NewProject(self, stName, user):
proj = Project(self, stName, user) proj = Project(self, stName, user)
self.rgproject.insert(0, proj) self.rgproject.insert(0, proj)
return proj return proj
def BoardTouched(self, board): def DrawingTouched(self, drawing):
project = board.owner project = drawing.owner
if project != self.rgproject[0]: if project != self.rgproject[0]:
self.rgproject.remove(project) self.rgproject.remove(project)
self.rgproject.insert(0, project) self.rgproject.insert(0, project)
@ -711,30 +854,35 @@ class GameLobby(Game):
project = Project(self, "Drawings", "Willy Marmot") project = Project(self, "Drawings", "Willy Marmot")
for board in self.rgboard: for board in self.rgboard:
board.TransferToOwner(project) board.TransferToOwner(project)
project.rgboard.append(board) project.rgdrawing.append(board)
del self.rgboard del self.rgboard
self.rgproject = [project] self.rgproject = [project]
self.mpuser_cldg = {} # ugh, upgrading parent classes is broken in our model :(
class GameWB(Game): class GameWB(Game):
def InitPersistent(self, gameLobby, board): def InitPersistent(self, gameLobby, board):
self.gameLobby = gameLobby self.gameLobby = gameLobby
self.board = board self.drawing = board
Game.InitPersistent(self) Game.InitPersistent(self)
def InitTransient(self): def InitTransient(self):
Game.InitTransient(self) Game.InitTransient(self)
if not self.FDead(): if not self.FDead():
self.board.chat.AttachToGame(self) self.drawing.chat.AttachToGame(self)
self.rgdgdie.append(self.board.chat.DetachFromGame) self.rgdgdie.append(self.drawing.chat.DetachFromGame)
def GetRgclsTokPers(self): def ClsCursor(self):
return [[Whiteboard, self.board]] return Cursor
def GetRgclsTokTrans(self): def GetRgclsTokTrans(self):
return [MsgScroller, Joiner, [AutoJoiner, Cursor], [AliveWithPlayers, CursorBlinker], AutoKiller] return [MsgScroller, Joiner, [AutoJoiner, self.ClsCursor()], [AliveWithPlayers, CursorBlinker], AutoKiller]
def GetRgtagDraw(self): def GetRgtagDraw(self):
return ["background", "solid", "cursor", "menu", "msgscroller"] return ["background", "solid", "cursor", "menu", "msgscroller"]
class GameSprEdit(GameWB):
def ClsCursor(self):
return CursorSprite
if __name__ == "__main__": if __name__ == "__main__":
Run(RunnerWB, "whiteboard.marm") Run(RunnerWB, "whiteboard.marm")