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:
parent
70529b610f
commit
19fe12a12a
372
whiteboard.py
372
whiteboard.py
|
@ -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")
|
||||||
|
|
Loading…
Reference in a new issue