[Bf-committers] fully interactive python console

Campbell Barton cbarton at metavr.com
Thu Mar 24 20:15:33 CET 2005


Skipped content of type multipart/alternative-------------- next part --------------
#!BPY

""" Registration info for Blender menus:
Name: 'Blender Interactive Console'
Blender: 234
Group: 'Wizards'
Tip: 'Blenders python '
"""

global VARDICT
VARDICT = {}

import Blender
from Blender import *
import sys

filename = 'cmd_blender'

# Touch a file for storing anything printed.

file = open(filename, 'w')
file.close()

# Include external file with internal namespace
def include(filename):
	file = open(filename, 'r')
	filedata = file.read()
	file.close()
	return compile(filedata, filename, 'exec')

# Autoexec,bat??
#try:
#	exec(include(Get('scriptsdir')+ '/console_autoexec.py'))	
	

class cmdLine:
	# cmd: is the command string, or any other message
	# type: 0:user input  1:program feedback  2:error message.
	# exe; 0- not yet executed   1:executed
	def __init__(self, cmd, type, exe):
		self.cmd = cmd
		self.type = type
		self.exe = exe

def writeCmdData(cmdLineList, type):
	if type == 3:
		typeList = [0,1,2, None] # all
	else:
		typeList = [type] # so we can use athe lists 'in' methiod
	
	newText = Text.New('command.py', 1)
	for myCmd in cmdLineList:
		if myCmd.type in typeList: # user input
			newText.write('%s\n' % myCmd.cmd)
	Draw.PupMenu('%s written' % newText.name)


def run(py):
	global VARDICT
	# OPEN A FILE TO PUT THE STDOUT IN
	sys.stdout.flush() # Get rid of whatever came before
	file = open(filename, 'w')
	std=sys.stdout
	sys.stdout=file
	
	try:
		# Load all variabls from global dict to local space.
		for TMPVARNAME in VARDICT.keys():
			exec('%s%s%s%s' % (TMPVARNAME,'=VARDICT["', TMPVARNAME, '"]'))
		
		#exec(py) 
		exec(compile(py, 'blender_cmd.py', 'exec')) # EXECUTE THE CODE
		
		# WRITE VARS to global VARLIST
		for TMPVARNAME in dir():
			if TMPVARNAME not in ['file', 'std', 'py']:
				exec('%s%s' % ('VARDICT[TMPVARNAME]=', TMPVARNAME))
		
	except: # Prints the REAL exception.
		error = str(sys.exc_value)
		for errorLine in error.split('\n'):
			cmdBuffer.append(cmdLine(errorLine, 2, None)) # new line to type into
			
	sys.stdout=std # Close file
	file.close()

	# Open the file to read the lines to the buffer.
	file = open(filename, 'r')
	for line in file.readlines():
		cmdBuffer.append(cmdLine(line, 1, None))
	cmdBuffer.append(cmdLine(' ', 0, 0)) # new line to type into
	sys.stdout=std
	file.close()
	


cmdBuffer = [cmdLine("Welcome Ideasman's Blender Console", 1, None),\
	cmdLine(' * Right Click to save output', 1, None),\
	cmdLine(' * Arrow keys for command history and cursor', 1, None),\
	cmdLine(' * Ctrl + Enter for multiline functions', 1, None),\
	cmdLine(' ', 0, 0)] # A history of commands
shift = 0 # Bool used to work out if were using caps.
enter = 0
cursor = -1 # How far back from the first letter are we? - in cmd tha tis.
prompt = '>> '
def main():
	global cmd
	global shift
	global cursor
	global histIndex
	histIndex = -1
	#------------------------------------------------------------------------------#
	#                             event handling code                              #
	#------------------------------------------------------------------------------#
	def handle_event(evt, val):
		def insCh(ch): # Instert a char
			global cmdBuffer
			global cursor
			# Later account for a cursor variable
			cmdBuffer[-1].cmd = ('%s%s%s' % ( cmdBuffer[-1].cmd[:cursor], ch, cmdBuffer[-1].cmd[cursor:]))

		if (evt == Draw.ESCKEY and not val):
			Draw.Exit()
		elif evt == Draw.MOUSEX: # AVOID TOO MANY REDRAWS.
			return
		elif evt == Draw.MOUSEY:
			return
		
		
		global cmdBuffer
		global shift
		global enter
		global cursor
		global histIndex
		
		if (evt == Draw.AKEY and val and shift): insCh('A')
		elif (evt == Draw.AKEY and val and not shift): insCh('a')
		elif (evt == Draw.BKEY and val and shift): insCh('B')
		elif (evt == Draw.BKEY and val and not shift): insCh('b')
		elif (evt == Draw.CKEY and val and shift): insCh('C')
		elif (evt == Draw.CKEY and val and not shift): insCh('c')
		elif (evt == Draw.DKEY and val and shift): insCh('D')
		elif (evt == Draw.DKEY and val and not shift): insCh('d')
		elif (evt == Draw.EKEY and val and shift): insCh('E')
		elif (evt == Draw.EKEY and val and not shift): insCh('e')
		elif (evt == Draw.FKEY and val and shift): insCh('F')
		elif (evt == Draw.FKEY and val and not shift): insCh('f')
		elif (evt == Draw.GKEY and val and shift): insCh('G')
		elif (evt == Draw.GKEY and val and not shift): insCh('g')
		elif (evt == Draw.HKEY and val and shift): insCh('H')
		elif (evt == Draw.HKEY and val and not shift): insCh('h')
		elif (evt == Draw.IKEY and val and shift): insCh('I')
		elif (evt == Draw.IKEY and val and not shift): insCh('i')
		elif (evt == Draw.JKEY and val and shift): insCh('J')
		elif (evt == Draw.JKEY and val and not shift): insCh('j')
		elif (evt == Draw.KKEY and val and shift): insCh('K')
		elif (evt == Draw.KKEY and val and not shift): insCh('j')
		elif (evt == Draw.LKEY and val and shift): insCh('L')
		elif (evt == Draw.LKEY and val and not shift): insCh('l')
		elif (evt == Draw.MKEY and val and shift): insCh('M')
		elif (evt == Draw.MKEY and val and not shift): insCh('m')
		elif (evt == Draw.NKEY and val and shift): insCh('N')
		elif (evt == Draw.NKEY and val and not shift): insCh('n')
		elif (evt == Draw.OKEY and val and shift): insCh('O')
		elif (evt == Draw.OKEY and val and not shift): insCh('o')
		elif (evt == Draw.PKEY and val and shift): insCh('P')
		elif (evt == Draw.PKEY and val and not shift): insCh('p')
		elif (evt == Draw.QKEY and val and shift): insCh('Q')
		elif (evt == Draw.QKEY and val and not shift): insCh('q')
		elif (evt == Draw.RKEY and val and shift): insCh('R')
		elif (evt == Draw.RKEY and val and not shift): insCh('r')
		elif (evt == Draw.SKEY and val and shift): insCh('S')
		elif (evt == Draw.SKEY and val and not shift): insCh('s')
		elif (evt == Draw.TKEY and val and shift): insCh('T')
		elif (evt == Draw.TKEY and val and not shift): insCh('t')
		elif (evt == Draw.UKEY and val and shift): insCh('U')
		elif (evt == Draw.UKEY and val and not shift): insCh('u')
		elif (evt == Draw.VKEY and val and shift): insCh('V')
		elif (evt == Draw.VKEY and val and not shift): insCh('v')
		elif (evt == Draw.WKEY and val and shift): insCh('W')
		elif (evt == Draw.WKEY and val and not shift): insCh('w')
		elif (evt == Draw.XKEY and val and shift): insCh('X')
		elif (evt == Draw.XKEY and val and not shift): insCh('x')
		elif (evt == Draw.YKEY and val and shift): insCh('Y')
		elif (evt == Draw.YKEY and val and not shift): insCh('y')
		elif (evt == Draw.ZKEY and val and shift): insCh('Z')
		elif (evt == Draw.ZKEY and val and not shift): insCh('z')
		

		elif (evt == Draw.ONEKEY and val and shift): insCh('!')
		elif (evt == Draw.ONEKEY and val and not shift): insCh('1')
		elif (evt == Draw.TWOKEY and val and shift): insCh('@')
		elif (evt == Draw.TWOKEY and val and not shift): insCh('2')
		elif (evt == Draw.THREEKEY and val and shift): insCh('#')
		elif (evt == Draw.THREEKEY and val and not shift): insCh('3')         
		elif (evt == Draw.FOURKEY and val and shift): insCh('$')
		elif (evt == Draw.FOURKEY and val and not shift): insCh('4')   
		elif (evt == Draw.FIVEKEY and val and shift): insCh('%')
		elif (evt == Draw.FIVEKEY and val and not shift): insCh('5')   
		elif (evt == Draw.SIXKEY and val and shift): insCh('^')
		elif (evt == Draw.SIXKEY and val and not shift): insCh('6')   
		elif (evt == Draw.SEVENKEY and val and shift): insCh('&')
		elif (evt == Draw.SEVENKEY and val and not shift): insCh('7')   
		elif (evt == Draw.EIGHTKEY and val and shift): insCh('*')
		elif (evt == Draw.EIGHTKEY and val and not shift): insCh('8')   
		elif (evt == Draw.NINEKEY and val and shift): insCh('(')
		elif (evt == Draw.NINEKEY and val and not shift): insCh('9')            
		elif (evt == Draw.ZEROKEY and val and shift): insCh(')')
		elif (evt == Draw.ZEROKEY and val and not shift): insCh('0')
			 
		elif (evt == Draw.COMMAKEY and val and shift): insCh('<')
		elif (evt == Draw.COMMAKEY and val and not shift): insCh(",")
		
		elif (evt == Draw.PERIODKEY and val and shift): insCh('>')
		elif (evt == Draw.PERIODKEY and val and not shift): insCh(".")
		
		elif (evt == Draw.QUOTEKEY and val and shift): insCh('"')
		elif (evt == Draw.QUOTEKEY and val and not shift): insCh("'")
		
		elif (evt == Draw.LEFTBRACKETKEY and val and not shift): insCh('[')
		elif (evt == Draw.LEFTBRACKETKEY and val and shift): insCh('{')
		elif (evt == Draw.RIGHTBRACKETKEY and val and not shift): insCh(']')         
		elif (evt == Draw.RIGHTBRACKETKEY and val and shift): insCh('}')         
		elif (evt == Draw.SEMICOLONKEY and val and shift): insCh(':')
		elif (evt == Draw.SEMICOLONKEY and val and not shift): insCh(';')
		elif (evt == Draw.BACKSLASHKEY and val and shift): insCh('|')
		elif (evt == Draw.BACKSLASHKEY and val and not shift): insCh('\\')
		elif (evt == Draw.SLASHKEY and val and shift): insCh('?')
		elif (evt == Draw.SLASHKEY and val and not shift): insCh('/')


		# UP DOWN ARROW KEYS, TO TRAVERSE HISTORY
		elif (evt == Draw.UPARROWKEY and val):
			if abs(histIndex)+1 >= len(cmdBuffer):
				histIndex = -1
			histIndex -= 1
			while cmdBuffer[histIndex].type != 0 and abs(histIndex) < len(cmdBuffer):
				histIndex -= 1
			if cmdBuffer[histIndex].type == 0: # we found one
				cmdBuffer[-1].cmd = cmdBuffer[histIndex].cmd
		
		# UP DOWN ARROW KEYS, TO TRAVERSE HISTORY
		elif (evt == Draw.DOWNARROWKEY and val):
			if histIndex >= -2:
				histIndex = -len(cmdBuffer)
			histIndex += 1
			while cmdBuffer[histIndex].type != 0 and histIndex != -2:
				histIndex += 1
			if cmdBuffer[histIndex].type == 0: # we found one
				cmdBuffer[-1].cmd = cmdBuffer[histIndex].cmd


		elif (evt == Draw.MINUSKEY and val and shift): insCh("_")      
		elif (evt == Draw.MINUSKEY and val and not shift): insCh("-")   

		elif (evt == Draw.EQUALKEY and val and shift): insCh("+")      
		elif (evt == Draw.EQUALKEY and val and not shift): insCh("=")      
		
		# SPACE
		elif (evt == Draw.SPACEKEY and val): insCh(' ')
		elif (evt == Draw.TABKEY and val): insCh('\t')
		
		elif (evt == Draw.RIGHTARROWKEY and val): 
			cursor +=1
			if cursor > -1:
				cursor = -1
		elif (evt == Draw.LEFTARROWKEY and val):
			cursor -=1
		

			 
		
		elif (evt == Draw.BACKSPACEKEY and val): cmdBuffer[-1].cmd = ('%s%s' % (cmdBuffer[-1].cmd[:cursor-1] , cmdBuffer[-1].cmd[cursor:]))
		# FIXDEL
		elif (evt == Draw.DELKEY and val) and cursor < -1:
			cmdBuffer[-1].cmd = cmdBuffer[-1].cmd[:cursor] + cmdBuffer[-1].cmd[cursor+1:]
			print cursor
			cursor +=1
		
		# HANDLE CAPITALS/ SHIFT KEY
		elif (evt == Draw.LEFTSHIFTKEY and not val): shift = 0      
		elif (evt == Draw.RIGHTSHIFTKEY and not val): shift = 0      

		elif (evt == Draw.LEFTSHIFTKEY and val): shift = 1
		elif (evt == Draw.RIGHTSHIFTKEY and val): shift = 1
		
		elif (evt == Draw.RETKEY and not val): enter = 0      
		elif (evt == Draw.RETKEY and val): enter = 1
		
		elif (evt == Draw.RIGHTMOUSE and not val):
			choice = Draw.PupMenu('Console Data to Blender Text%t|Input Data (white)|Output Data (blue)?|Error Data (red)|All Text')
			if choice == 1:
				writeCmdData(cmdBuffer, 0) # type 0 user
			elif choice == 2:
				writeCmdData(cmdBuffer, 1) # type 1 user output
			elif choice == 3:
				writeCmdData(cmdBuffer, 2) # type 2 errors
			elif choice == 4:
				writeCmdData(cmdBuffer, 3) # All

		Draw.Redraw()
		
		print 'redraw', evt


	# This recieves the event index, call a function from here depending on the event.
	def handle_button_event(evt):
		pass


	def draw_gui():
		global cmdBuffer
		global enter
		global shift
		global cursor
		global histIndex
		lineHeight = 16
		# find the width of the widest button
		fontsize = "normal"
		
		# Check for the neter kay hit
		if enter:
			if Window.GetKeyQualifiers() & Window.Qual.CTRL: # HOLDING DOWN SHIFT, GO TO NEXT LINE.
				cmdBuffer.append(cmdLine(' ', 0, 0))
			else:
				# Multiline code will still run with 1 line,
				if cmdBuffer[-1].cmd != ' ':
					multiLineCode = [cmdBuffer[-1].cmd]
				else:
					multiLineCode = []
				cmdBuffer[-1].exe = 1
				i = 2
				while cmdBuffer[-i].exe == 0:
					if cmdBuffer[-i].cmd != ' ':
						multiLineCode.append(cmdBuffer[-i].cmd)
					# Mark as executed
					cmdBuffer[-i].exe = 1
					i+=1
				multiLineCode.reverse()
				run('\n'.join(multiLineCode))
			
			cursor = -1 # Reset cursor
			histIndex = -1
		
		# Clear the screen
		BGL.glClearColor(0.0, 0.0, 0.0, 1.0)
		BGL.glClear(BGL.GL_COLOR_BUFFER_BIT)         # use it to clear the color buffer
		
		# Draw cursor location colour
		cmd2curWidth = Draw.GetStringWidth(cmdBuffer[-1].cmd[:cursor], fontsize)
		BGL.glColor3f(0.8, 0.2, 0.2)
		BGL.glRecti(cmd2curWidth-1,12,cmd2curWidth+1, 28)
		
		BGL.glColor3f(1,1,1)
		# Draw the set of cammands to the buffer
		Ln = len(cmdBuffer)
		while Ln:

			if cmdBuffer[-Ln].type == 0:
				BGL.glColor3f(1, 1, 1)
			elif cmdBuffer[-Ln].type == 1:
				BGL.glColor3f(.3, .3, 1)
			elif cmdBuffer[-Ln].type == 2:
				BGL.glColor3f(1.0, 0, 0)
			else:
				BGL.glColor3f(1, 1, 0)
			
			BGL.glRasterPos2i(0, lineHeight*Ln)
			
			Draw.Text('%s' % cmdBuffer[-Ln].cmd  )
			Ln -= 1
		
	#------------------------------------------------------------------------------#
	#                    register the event handling code, GUI                     #
	#------------------------------------------------------------------------------#
	Draw.Register(draw_gui, handle_event, handle_button_event)

main() 


More information about the Bf-committers mailing list