Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWillian Padovani Germano <wpgermano@gmail.com>2005-05-17 11:17:52 +0400
committerWillian Padovani Germano <wpgermano@gmail.com>2005-05-17 11:17:52 +0400
commit859959b49c8122b1e37027cf5009fecd23f5d8c8 (patch)
tree0dbe86f455743795604d88b3b9a351d0d6d1d98e /release/scripts/console.py
parent7f4ff24462217328a6d0d0b193621949ed5e085a (diff)
BPython:
- fixing bug reported by Paolo Colombo: space handler slinks set for a 3d view were not set when the area got maximized; - Blender.Object: added object.isSB() method to know if an object is a soft body (has ob->soft != NULL). Used in fixfromarmature.py. Scripts: - updates: batch_name_edit (Campbell), fixfromarmature (JMS); - additions: X3D exporter by Bart; Envelope Suite by Jonas Petersen; BVH 2 Armature by Jean-Baptiste Perin; Camera Changer by Regis Montoya (3R); Interactive Console by Campbell (ideasman). - tiny updates in other scripts.
Diffstat (limited to 'release/scripts/console.py')
-rw-r--r--release/scripts/console.py517
1 files changed, 517 insertions, 0 deletions
diff --git a/release/scripts/console.py b/release/scripts/console.py
new file mode 100644
index 00000000000..1fbf7908c7a
--- /dev/null
+++ b/release/scripts/console.py
@@ -0,0 +1,517 @@
+#!BPY
+
+"""
+Name: 'Interactive Console'
+Blender: 236
+Group: 'System'
+Tooltip: 'Interactive Python Console'
+"""
+__author__ = "Campbell Barton AKA Ideasman"
+__url__ = ["http://members.iinet.net.au/~cpbarton/ideasman/", "blender", "elysiun", "Official Python site, http://www.python.org"]
+__bpydoc__ = """\
+This is an interactive console, similar to Python's own command line interpreter. Since it is embedded in Blender, it has access to all Blender Python modules.
+
+Those completely new to Python can check the link button above that points to
+its official homepage, with news, downloads and documentation.
+
+Usage:<br>
+ Type your code and hit "Enter" to get it executed.<br>
+ - Right mouse click: Save output;<br>
+ - Arrow keys: command history and cursor;<br>
+ - Ctrl + Tab: auto compleate based on variable names and modules loaded -- multiple choices popup a menu;<br>
+ - Ctrl + Enter: multiline functions -- delays executing code until only Enter is pressed.
+"""
+
+import Blender
+from Blender import *
+import sys as python_sys
+import StringIO
+import types
+
+# Constants
+__DELIMETERS__ = '. ,=+-*/%<>&~][{}():'
+__LINE_HISTORY__ = 200
+__LINE_HEIGHT__ = 14
+__FONT_SIZE__ = "normal"
+
+'''
+# Generic Blender functions
+def getActScriptWinRect():
+ area = Window.GetAreaSize()
+ area = (area[0]-1, area[1]-1)
+ for scrInfo in Window.GetScreenInfo(Window.Types['SCRIPT'], 'win', ''):
+ if scrInfo['vertices'][2]-scrInfo['vertices'][0] == area[0]:
+ if scrInfo['vertices'][3]-scrInfo['vertices'][1] == area[1]:
+ return scrInfo['vertices']
+ return None
+'''
+
+class cmdLine:
+ # cmd: is the command string, or any other message
+ # type: 0:user input 1:program feedback 2:error message. 3:option feedback
+ # exe; 0- not yet executed 1:executed
+ def __init__(self, cmd, type, exe):
+ self.cmd = cmd
+ self.type = type
+ self.exe = exe
+
+# Include external file with internal namespace
+def include(filename):
+ file = open(filename, 'r')
+ filedata = file.read()
+ file.close()
+ return compile(filedata, filename, 'exec')
+
+# Writes command line data to a blender text file.
+def writeCmdData(cmdLineList, type):
+ if type == 3:
+ typeList = [0,1,2, 3, None] # all
+ else:
+ typeList = [type] # so we can use athe lists 'in' methiod
+
+ newText = Text.New('command_output.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 insertCmdData(cmdBuffer):
+ textNames = [tex.name for tex in Text.Get()]
+ if textNames:
+ choice = Draw.PupMenu('|'.join(textNames))
+ if choice != -1:
+ text = Text.Get()[choice-1]
+
+ # Add the text!
+ for l in text.asLines():
+ cmdBuffer.append(cmdLine('%s ' % l, 0, 0))
+ Draw.Redraw()
+
+
+COLLECTED_VAR_NAMES = {} # a list of keys, each key has a list of absolute paths
+
+# Pain and simple recursice dir(), accepts a string
+def rdir(dirString):
+ global COLLECTED_VAR_NAMES
+ dirStringSplit = dirString.split('.')
+
+ exec('dirList = dir(%s)' % dirString)
+ for dirItem in dirList:
+ if not dirItem.startswith('_'):
+ if dirItem not in COLLECTED_VAR_NAMES.keys():
+ COLLECTED_VAR_NAMES[dirItem] = []
+
+ # Add the string
+ splitD = dirString.split('"')[-2]
+ if splitD not in COLLECTED_VAR_NAMES[dirItem]:
+ COLLECTED_VAR_NAMES[dirItem].append(splitD)
+
+
+
+ # Stops recursice stuff, overlooping
+ if type(dirItem) == types.ClassType or \
+ type(dirItem) == types.ModuleType:
+
+ print dirString, splitD, dirItem
+
+ # Dont loop up dirs for strings ints etc.
+ if d not in dirStringSplit:
+ rdir( '%s.%s' % (dirString, d))
+
+def recursive_dir():
+ global COLLECTED_VAR_NAMES
+
+ for name in __CONSOLE_VAR_DICT__.keys():
+ if not name.startswith('_'): # Dont pick names like __name__
+ rdir('__CONSOLE_VAR_DICT__["%s"]' % name)
+ #print COLLECTED_VAR_NAMES
+ COLLECTED_VAR_NAMES[name] = ['']
+ return COLLECTED_VAR_NAMES
+
+# Runs the code line(s) the user has entered and handle errors
+# As well as feeding back the output into the blender window.
+def runUserCode(__USER_CODE_STRING__):
+ global __CONSOLE_VAR_DICT__ # We manipulate the variables here. loading and saving from localspace to this global var.
+
+ # Open A File like object to write all output to, that would useually be printed.
+ python_sys.stdout.flush() # Get rid of whatever came before
+ __FILE_LIKE_STRING__ = StringIO.StringIO() # make a new file like string, this saves up from making a file.
+ __STD_OUTPUT__ = python_sys.stdout # we need to store the normal output.
+ python_sys.stdout=__FILE_LIKE_STRING__ # Now anything printed will be written to the file like string.
+
+ # Try and run the user entered line(s)
+ try:
+ # Load all variabls from global dict to local space.
+ for __TMP_VAR_NAME__ in __CONSOLE_VAR_DICT__.keys():
+ exec('%s%s%s%s' % (__TMP_VAR_NAME__,'=__CONSOLE_VAR_DICT__["', __TMP_VAR_NAME__, '"]'))
+ del __TMP_VAR_NAME__
+
+ # Now all the vars are loaded, execute the code. # Newline thanks to phillip,
+ exec(compile(__USER_CODE_STRING__, 'blender_cmd.py', 'single')) #exec(compile(__USER_CODE_STRING__, 'blender_cmd.py', 'exec'))
+
+ # Write local veriables to global __CONSOLE_VAR_DICT__
+ for __TMP_VAR_NAME__ in dir():
+ if __TMP_VAR_NAME__ != '__FILE_LIKE_STRING__' and\
+ __TMP_VAR_NAME__ != '__STD_OUTPUT__' and\
+ __TMP_VAR_NAME__ != '__TMP_VAR_NAME__' and\
+ __TMP_VAR_NAME__ != '__USER_CODE_STRING__':
+
+ # Execute the local > global coversion.
+ exec('%s%s' % ('__CONSOLE_VAR_DICT__[__TMP_VAR_NAME__]=', __TMP_VAR_NAME__))
+ del __TMP_VAR_NAME__
+
+ except: # Prints the REAL exception.
+ error = str(python_sys.exc_value)
+ for errorLine in error.split('\n'):
+ cmdBuffer.append(cmdLine(errorLine, 2, None)) # new line to type into
+
+ python_sys.stdout = __STD_OUTPUT__ # Go back to output to the normal blender console
+
+ # Copy all new output to cmdBuffer
+ __FILE_LIKE_STRING__.seek(0) # the readline function requires that we go back to the start of the file.
+ for line in __FILE_LIKE_STRING__.readlines():
+ cmdBuffer.append(cmdLine(line, 1, None))
+
+ cmdBuffer.append(cmdLine(' ', 0, 0)) # new line to type into
+ python_sys.stdout=__STD_OUTPUT__
+ __FILE_LIKE_STRING__.close()
+
+
+
+
+
+#------------------------------------------------------------------------------#
+# event handling code #
+#------------------------------------------------------------------------------#
+def handle_event(evt, val):
+
+ # Insert Char into the cammand line
+ 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:]))
+
+ #------------------------------------------------------------------------------#
+ # Define Complex Key Actions #
+ #------------------------------------------------------------------------------#
+ def actionEnterKey():
+ global histIndex, cursor, cmdBuffer
+ # Check for the neter kay hit
+ 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,
+ multiLineCode = ['if 1:']
+ if cmdBuffer[-1].cmd != ' ':
+ multiLineCode = ['%s%s' % (' ', cmdBuffer[-1].cmd)] # added space for fake if.
+ else:
+ cmdBuffer[-1].type = 1
+ multiLineCode = []
+ cmdBuffer[-1].exe = 1
+ i = 2
+ while cmdBuffer[-i].exe == 0:
+ if cmdBuffer[-i].cmd == ' ':# Tag as an output type so its not used in the key history
+ cmdBuffer[-i].type = 1
+ else: # space added at the start for added if 1: statement
+ multiLineCode.append('%s%s' % (' ', cmdBuffer[-i].cmd) )
+
+ # Mark as executed
+ cmdBuffer[-i].exe = 1
+ i+=1
+
+ # add if to the end, reverse will make it the start.
+ multiLineCode.append('if 1:')
+ multiLineCode.reverse()
+ multiLineCode.append(' pass') # Now this is the end
+
+
+ runUserCode('\n'.join(multiLineCode))
+
+ # Clear the output based on __LINE_HISTORY__
+ if len(cmdBuffer) > __LINE_HISTORY__:
+ cmdBuffer = cmdBuffer[-__LINE_HISTORY__:]
+
+ histIndex = cursor = -1 # Reset cursor and history
+
+ def actionUpKey():
+ global histIndex, cmdBuffer
+ 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
+
+ def actionDownKey():
+ global histIndex, cmdBuffer
+ 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
+
+ def actionRightMouse():
+ choice = Draw.PupMenu('Console Menu%t|Write Input Data (white)|Write Output Data (blue)|Write Error Data (red)|Write All Text|%l|Insert Blender text|%l|Quit')
+ print choice
+ 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
+ elif choice == 6:
+ insertCmdData(cmdBuffer) # All
+ elif choice == 8: # Exit
+ Draw.Exit()
+
+
+ # Auto compleating, quite complex- use recutsice dir for the moment.
+ def actionAutoCompleate(): # Ctrl + Tab
+ RECURSIVE_DIR = recursive_dir()
+
+ # get last name of user input
+ editVar = cmdBuffer[-1].cmd[:cursor]
+
+ # Split off spaces operators etc from the staryt of the command so we can use the startswith function.
+ for splitChar in __DELIMETERS__:
+ editVar = editVar.split(splitChar)[-1]
+
+ # Now we should have the var by its self
+ if editVar:
+
+ possibilities = []
+
+ print editVar, 'editVar'
+ for __TMP_VAR_NAME__ in RECURSIVE_DIR.keys():
+ if __TMP_VAR_NAME__ == editVar:
+ # print 'ADITVAR IS A VAR'
+ continue
+ elif __TMP_VAR_NAME__.startswith( editVar ):
+ possibilities.append( __TMP_VAR_NAME__ )
+
+
+ if len(possibilities) == 1:
+ cmdBuffer[-1].cmd = ('%s%s%s' % (cmdBuffer[-1].cmd[:cursor - len(editVar)], possibilities[0], cmdBuffer[-1].cmd[cursor:]))
+
+ elif possibilities: # If its not just []
+ # -1 with insert is the second last.
+
+ # Text choice
+ #cmdBuffer.insert(-1, cmdLine('options: %s' % ' '.join(possibilities), 3, None))
+
+ menuText = 'Choices (hold shift for whole name)%t|'
+ menuList = []
+ menuListAbs = []
+ possibilities.sort() # make nice :)
+ for __TMP_VAR_NAME__ in possibilities:
+ for usage in RECURSIVE_DIR[__TMP_VAR_NAME__]:
+ # Account for non absolute (variables for eg.)
+ if usage: # not ''
+ menuListAbs.append('%s.%s' % (usage, __TMP_VAR_NAME__)) # Used for names and can be entered when pressing shift.
+ else:
+ menuListAbs.append(__TMP_VAR_NAME__) # Used for names and can be entered when pressing shift.
+
+ menuList.append(__TMP_VAR_NAME__) # Used for non Shift
+
+
+ #choice = Draw.PupMenu('Select Variabe name%t|' + '|'.join(possibilities) )
+ choice = Draw.PupMenu(menuText + '|'.join(menuListAbs))
+ if choice != -1:
+
+ if not Window.GetKeyQualifiers() & Window.Qual.SHIFT: # Only paste in the Short name
+ cmdBuffer[-1].cmd = ('%s%s%s' % (cmdBuffer[-1].cmd[:cursor - len(editVar)], menuList[choice-1], cmdBuffer[-1].cmd[cursor:]))
+ else: # Put in the long name
+ cmdBuffer[-1].cmd = ('%s%s%s' % (cmdBuffer[-1].cmd[:cursor - len(editVar)], menuListAbs[choice-1], cmdBuffer[-1].cmd[cursor:]))
+ else:
+ # print 'NO EDITVAR'
+ return
+
+ # ------------------end------------------#
+
+
+ #if (evt == Draw.ESCKEY and not val):
+ # Draw.Exit()
+ if evt == Draw.MOUSEX: # AVOID TOO MANY REDRAWS.
+ return
+ elif evt == Draw.MOUSEY:
+ return
+
+
+ global cursor
+ global histIndex
+
+ ascii = Blender.event
+
+ #------------------------------------------------------------------------------#
+ # key codes and key handling #
+ #------------------------------------------------------------------------------#
+
+ # UP DOWN ARROW KEYS, TO TRAVERSE HISTORY
+ if (evt == Draw.UPARROWKEY and val): actionUpKey()
+ elif (evt == Draw.DOWNARROWKEY and val): actionDownKey()
+
+ elif (evt == Draw.RIGHTARROWKEY and val):
+ cursor +=1
+ if cursor > -1:
+ cursor = -1
+ elif (evt == Draw.LEFTARROWKEY and val):
+ cursor -=1
+
+ elif (evt == Draw.TABKEY and val):
+ if Window.GetKeyQualifiers() & Window.Qual.CTRL:
+ actionAutoCompleate()
+ else:
+ insCh('\t')
+
+ elif (evt == Draw.BACKSPACEKEY and val): cmdBuffer[-1].cmd = ('%s%s' % (cmdBuffer[-1].cmd[:cursor-1] , cmdBuffer[-1].cmd[cursor:]))
+ elif (evt == Draw.DELKEY and val) and cursor < -1:
+ cmdBuffer[-1].cmd = cmdBuffer[-1].cmd[:cursor] + cmdBuffer[-1].cmd[cursor+1:]
+ cursor +=1
+
+ elif ((evt == Draw.RETKEY or evt == Draw.PADENTER) and val): actionEnterKey()
+ elif (evt == Draw.RIGHTMOUSE and not val):actionRightMouse(); return
+
+ elif ascii:
+ insCh(chr(ascii))
+ else:
+ return # dont redraw.
+ Draw.Redraw()
+
+
+def draw_gui():
+
+ # Get the bounds from ObleGL directly
+ __CONSOLE_RECT__ = BGL.Buffer(BGL.GL_FLOAT, 4)
+ BGL.glGetFloatv(BGL.GL_SCISSOR_BOX, __CONSOLE_RECT__)
+ __CONSOLE_RECT__= __CONSOLE_RECT__.list
+
+
+ # 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], __FONT_SIZE__)
+ BGL.glColor3f(0.8, 0.2, 0.2)
+ BGL.glRecti(cmd2curWidth-1,4,cmd2curWidth+1, 20)
+
+ BGL.glColor3f(1,1,1)
+ # Draw the set of cammands to the buffer
+
+ consoleLineIdx = 1
+ wrapLineIndex = 0
+ while consoleLineIdx < len(cmdBuffer) and __CONSOLE_RECT__[3] > consoleLineIdx*__LINE_HEIGHT__ :
+ if cmdBuffer[-consoleLineIdx].type == 0:
+ BGL.glColor3f(1, 1, 1)
+ elif cmdBuffer[-consoleLineIdx].type == 1:
+ BGL.glColor3f(.3, .3, 1)
+ elif cmdBuffer[-consoleLineIdx].type == 2:
+ BGL.glColor3f(1.0, 0, 0)
+ elif cmdBuffer[-consoleLineIdx].type == 3:
+ BGL.glColor3f(0, 0.8, 0)
+ else:
+ BGL.glColor3f(1, 1, 0)
+
+ if consoleLineIdx == 1: # NEVER WRAP THE USER INPUT
+ BGL.glRasterPos2i(0, (__LINE_HEIGHT__*consoleLineIdx) - 8)
+ Draw.Text(cmdBuffer[-consoleLineIdx].cmd, __FONT_SIZE__)
+
+
+ else: # WRAP?
+ # LINE WRAP
+ if Draw.GetStringWidth(cmdBuffer[-consoleLineIdx].cmd, __FONT_SIZE__) > __CONSOLE_RECT__[2]:
+ wrapLineList = []
+ copyCmd = [cmdBuffer[-consoleLineIdx].cmd, '']
+ while copyCmd != ['','']:
+ while Draw.GetStringWidth(copyCmd[0], __FONT_SIZE__) > __CONSOLE_RECT__[2]:
+ #print copyCmd
+ copyCmd[1] = '%s%s'% (copyCmd[0][-1], copyCmd[1]) # Add the char on the end
+ copyCmd[0] = copyCmd[0][:-1]# remove last chat
+
+ # Now we have copyCmd[0] at a good length we can print it.
+ if copyCmd[0] != '':
+ wrapLineList.append(copyCmd[0])
+
+ copyCmd[0]=''
+ copyCmd = [copyCmd[1], copyCmd[0]]
+
+ # Now we have a list of lines, draw them (OpenGLs reverse ordering requires this odd change)
+ wrapLineList.reverse()
+ for wline in wrapLineList:
+ BGL.glRasterPos2i(0, (__LINE_HEIGHT__*(consoleLineIdx + wrapLineIndex)) - 8)
+ Draw.Text(wline, __FONT_SIZE__)
+ wrapLineIndex += 1
+ wrapLineIndex-=1 # otherwise we get a silly extra line.
+
+ else: # no wrapping.
+
+ BGL.glRasterPos2i(0, (__LINE_HEIGHT__*(consoleLineIdx+wrapLineIndex)) - 8)
+ Draw.Text(cmdBuffer[-consoleLineIdx].cmd, __FONT_SIZE__)
+
+
+ consoleLineIdx += 1
+
+
+# This recieves the event index, call a function from here depending on the event.
+def handle_button_event(evt):
+ pass
+
+
+# Run the console
+__CONSOLE_VAR_DICT__ = {} # Initialize var dict
+
+
+# Print Startup lines
+cmdBuffer = [cmdLine("Welcome to Ideasman's Blender Console", 1, None),\
+ cmdLine(' * Right Click: Save output', 1, None),\
+ cmdLine(' * Arrow Keys: Command history and cursor', 1, None),\
+ cmdLine(' * Ctrl + Tab: Auto compleate based on variable names and modules loaded, multiple choices popup a menu', 1, None),\
+ cmdLine(' * Ctrl + Enter: Multiline functions, delays executing code until only Enter is pressed.', 1, None)]
+
+histIndex = cursor = -1 # How far back from the first letter are we? - in current CMD line, history if for moving up and down lines.
+
+# Autoexec, startup code.
+console_autoexec = '%s%s' % (Get('datadir'), '/console_autoexec.py')
+if not sys.exists(console_autoexec):
+ # touch the file
+ open(console_autoexec, 'w').close()
+ cmdBuffer.append(cmdLine('...console_autoexec.py not found, making new in scripts data dir', 1, None))
+else:
+ cmdBuffer.append(cmdLine('...Using existing console_autoexec.py in scripts data dir', 1, None))
+
+
+
+#-Autoexec---------------------------------------------------------------------#
+# Just use the function to jump into local naming mode.
+# This is so we can loop through all of the autoexec functions / vars and add them to the __CONSOLE_VAR_DICT__
+def autoexecToVarList():
+ global __CONSOLE_VAR_DICT__ # write autoexec vars to this.
+
+ # Execute an external py file as if local
+ exec(include(console_autoexec))
+
+ # Write local to global __CONSOLE_VAR_DICT__ for reuse,
+ for __TMP_VAR_NAME__ in dir() + dir(Blender):
+ # Execute the local > global coversion.
+ exec('%s%s' % ('__CONSOLE_VAR_DICT__[__TMP_VAR_NAME__]=', __TMP_VAR_NAME__))
+
+autoexecToVarList() # pass the blender module
+#-end autoexec-----------------------------------------------------------------#
+
+
+# Append new line to write to
+cmdBuffer.append(cmdLine(' ', 0, 0))
+
+#------------------------------------------------------------------------------#
+# register the event handling code, GUI #
+#------------------------------------------------------------------------------#
+def main():
+ Draw.Register(draw_gui, handle_event, handle_button_event)
+
+main()