153 lines
4.3 KiB
Python
153 lines
4.3 KiB
Python
|
"""
|
||
|
Simple console widget for rocket
|
||
|
"""
|
||
|
import sys, os.path
|
||
|
|
||
|
# workaround: https://www.panda3d.org/forums/viewtopic.php?t=10062&p=99697#p99054
|
||
|
#from panda3d import rocket
|
||
|
import _rocketcore as rocket
|
||
|
|
||
|
from panda3d.rocket import RocketRegion, RocketInputHandler
|
||
|
|
||
|
class Console(object):
|
||
|
def __init__(self, base, context, cols, rows, commandHandler):
|
||
|
self.base = base
|
||
|
|
||
|
self.context = context
|
||
|
self.loadFonts()
|
||
|
self.cols = cols
|
||
|
self.rows = rows
|
||
|
self.commandHandler = commandHandler
|
||
|
|
||
|
self.setupConsole()
|
||
|
self.allowEditing(True)
|
||
|
|
||
|
def getTextContainer(self):
|
||
|
return self.textEl
|
||
|
|
||
|
def setPrompt(self, prompt):
|
||
|
self.consolePrompt = prompt
|
||
|
|
||
|
def allowEditing(self, editMode):
|
||
|
self.editMode = editMode
|
||
|
if editMode:
|
||
|
self.input = ""
|
||
|
if not self.lastLine:
|
||
|
self.addLine("")
|
||
|
self.newEditLine()
|
||
|
|
||
|
def loadFonts(self):
|
||
|
rocket.LoadFontFace("Perfect DOS VGA 437.ttf")
|
||
|
|
||
|
def setupConsole(self):
|
||
|
self.document = self.context.LoadDocument("console.rml")
|
||
|
if not self.document:
|
||
|
raise AssertionError("did not find console.rml")
|
||
|
|
||
|
el = self.document.GetElementById('content')
|
||
|
|
||
|
self.textEl = el
|
||
|
|
||
|
# roundabout way of accessing the current object through rocket event...
|
||
|
|
||
|
# add attribute to let Rocket know about the receiver
|
||
|
self.context.console = self
|
||
|
|
||
|
# then reference through the string format (dunno how else to get the event...)
|
||
|
self.document.AddEventListener(
|
||
|
'keydown', 'document.context.console.handleKeyDown(event)', True)
|
||
|
self.document.AddEventListener(
|
||
|
'textinput', 'document.context.console.handleTextInput(event)', True)
|
||
|
|
||
|
self.consolePrompt = "C:\\>"
|
||
|
|
||
|
self.input = ""
|
||
|
self.lastLine = None
|
||
|
|
||
|
self.blinkState = False
|
||
|
self.queueBlinkCursor()
|
||
|
|
||
|
self.document.Show()
|
||
|
|
||
|
def queueBlinkCursor(self):
|
||
|
self.base.taskMgr.doMethodLater(0.2, self.blinkCursor, 'blinkCursor')
|
||
|
|
||
|
def blinkCursor(self, task):
|
||
|
self.blinkState = not self.blinkState
|
||
|
if self.editMode:
|
||
|
self.updateEditLine(self.input)
|
||
|
self.queueBlinkCursor()
|
||
|
|
||
|
def escape(self, text):
|
||
|
return text. \
|
||
|
replace('<', '<'). \
|
||
|
replace('>', '>'). \
|
||
|
replace('"', '"')
|
||
|
|
||
|
def addLine(self, text):
|
||
|
curKids = list(self.textEl.child_nodes)
|
||
|
while len(curKids) >= self.rows:
|
||
|
self.textEl.RemoveChild(curKids[0])
|
||
|
curKids = curKids[1:]
|
||
|
|
||
|
line = self.document.CreateTextNode(self.escape(text) + '\n')
|
||
|
self.textEl.AppendChild(line)
|
||
|
self.lastLine = line
|
||
|
|
||
|
def addLines(self, lines):
|
||
|
for line in lines:
|
||
|
self.addLine(line)
|
||
|
|
||
|
def updateEditLine(self, newInput=''):
|
||
|
newText = self.consolePrompt + newInput
|
||
|
self.lastLine.text = self.escape(newText) + (self.blinkState and '_' or '')
|
||
|
self.input = newInput
|
||
|
|
||
|
def scroll(self):
|
||
|
self.blinkState = False
|
||
|
self.updateEditLine(self.input + '\n')
|
||
|
|
||
|
def handleKeyDown(self, event):
|
||
|
"""
|
||
|
Handle control keys
|
||
|
"""
|
||
|
keyId = event.parameters['key_identifier']
|
||
|
if not self.editMode:
|
||
|
if keyId == rocket.key_identifier.PAUSE:
|
||
|
if event.parameters['ctrl_key']:
|
||
|
self.commandHandler(None)
|
||
|
|
||
|
return
|
||
|
|
||
|
if keyId == rocket.key_identifier.RETURN:
|
||
|
# emit line without cursor
|
||
|
self.scroll()
|
||
|
|
||
|
# handle command
|
||
|
self.commandHandler(self.input)
|
||
|
|
||
|
if self.editMode:
|
||
|
# start with new "command"
|
||
|
self.addLine(self.consolePrompt)
|
||
|
self.updateEditLine("")
|
||
|
|
||
|
elif keyId == rocket.key_identifier.BACK:
|
||
|
self.updateEditLine(self.input[0:-1])
|
||
|
|
||
|
def handleTextInput(self, event):
|
||
|
if not self.editMode:
|
||
|
return
|
||
|
|
||
|
# handle normal text character
|
||
|
data = event.parameters['data']
|
||
|
if 32 <= data < 128:
|
||
|
self.updateEditLine(self.input + chr(data))
|
||
|
|
||
|
def newEditLine(self):
|
||
|
self.addLine("")
|
||
|
self.updateEditLine()
|
||
|
|
||
|
def cls(self):
|
||
|
curKids = list(self.textEl.child_nodes)
|
||
|
for kid in curKids:
|
||
|
self.textEl.RemoveChild(kid)
|