diff options
Diffstat (limited to 'release/scripts/console.py')
-rw-r--r-- | release/scripts/console.py | 861 |
1 files changed, 0 insertions, 861 deletions
diff --git a/release/scripts/console.py b/release/scripts/console.py deleted file mode 100644 index c6ae22a86f5..00000000000 --- a/release/scripts/console.py +++ /dev/null @@ -1,861 +0,0 @@ -#!BPY - -""" -Name: 'Interactive Python Console' -Blender: 245 -Group: 'System' -Tooltip: 'Interactive Python Console' -""" - -__author__ = "Campbell Barton aka ideasman42" -__url__ = ["www.blender.org", "blenderartists.org", "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 are recommended to 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: Console Menu (Save output, etc);<br> - - Mousewheel: Scroll text - - Arrow keys: command history and cursor;<br> - - Shift + Backspace: Backspace whole word;<br> - - Shift + Arrow keys: jump words;<br> - - Ctrl + (+/- or mousewheel): Zoom text size;<br> - - Ctrl + Enter: auto compleate based on variable names and modules loaded -- multiple choices popup a menu;<br> - - Shift + Enter: multiline functions -- delays executing code until only Enter is pressed. -""" - -# -------------------------------------------------------------------------- -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software Foundation, -# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# -# ***** END GPL LICENCE BLOCK ***** -# -------------------------------------------------------------------------- - -import Blender -import bpy -from Blender import * -import sys as python_sys -import StringIO - -# Constants -__DELIMETERS__ = '. ,=+-*/%<>&~][{}():\t' -__VARIABLE_DELIMETERS__ = ' ,=+-*/%<>&~{}():\t' - -__LINE_HISTORY__ = 500 - -global __FONT_SIZE__ - -__FONT_SIZES__ = ( ('tiny', 10), ('small', 12), ('normalfix', 14), ('large', 16) ) -__FONT_SIZE__ = 2 # index for the list above, normal default. - -global __CONSOLE_LINE_OFFSET__ -__CONSOLE_LINE_OFFSET__ = 0 - -cmdBuffer = [] # dosnt need to be global - -''' -# 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 -''' - - -# menuText, # per group -def PupMenuLess(menu, groupSize=35): - more = [' more...'] - less = [' less...'] - - menuList= menu.split('|') - - # No Less Needed, just call. - if len(menuList) < groupSize: - return Draw.PupMenu(menu) - - title = menuList[0].split('%t')[0] - - # Split the list into groups - menuGroups = [[]] - for li in menuList[1:]: - if len(menuGroups[-1]) < groupSize: - menuGroups[-1].append(li) - else: - menuGroups.append([li]) - - # Stores teh current menu group we are looking at - groupIdx = 0 - while 1: - # Give us a title with the menu number - numTitle = [ ' '.join([title, str(groupIdx + 1), 'of', str(len(menuGroups)), '%t'])] - if groupIdx == 0: - menuString = '|'.join(numTitle + menuGroups[groupIdx] + more) - elif groupIdx == len(menuGroups)-1: - menuString = '|'.join(numTitle + less + menuGroups[groupIdx]) - else: # In the middle somewhere so Show a more and less - menuString = '|'.join(numTitle + less + menuGroups[groupIdx] + more) - result = Draw.PupMenu(menuString) - # User Exit - if result == -1: - return -1 - - if groupIdx == 0: # First menu - if result-1 < groupSize: - return result - else: # must be more - groupIdx +=1 - elif groupIdx == len(menuGroups): # Last Menu - if result == 1: # Must be less - groupIdx -= 1 - else: # Must be a choice - return result + (groupIdx*groupSize) - - else: - if result == 1: # Must be less - groupIdx -= 1 - elif result-2 == groupSize: - groupIdx +=1 - else: - return result - 1 + (groupIdx*groupSize) - - - -# Use newstyle classes, Im not bothering with inheretence -# but slots are faster. -class cmdLine(object): - __slots__ = [\ - 'cmd', # is the command string, or any other message - 'type',# 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(type): - newText = Text.New('command_output.py', 1) - if type == 3: newText.write('\n'.join( [ myCmd.cmd for myCmd in cmdBuffer ] )) - else: newText.write('\n'.join( [ myCmd.cmd for myCmd in cmdBuffer if myCmd.type is type] )) - Draw.PupMenu('%s written' % newText.name) - -def insertCmdData(): - texts = list(bpy.data.texts) - textNames = [tex.name for tex in texts] - if textNames: - choice = Draw.PupMenu('|'.join(textNames)) - if choice != -1: - text = texts[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 -unused_types = str, dict, list, float, int, str, type, tuple, type(dir), type(None) -def rdir(dirString, depth=0): - #print ' ' * depth, dirString - # MAX DEPTH SET HERE - if depth > 5: - # print 'maxdepoth reached.' - return - - global COLLECTED_VAR_NAMES - dirStringSplit = dirString.split('.') - - exec('value=' + dirString) - - if type(value) in unused_types: - # print 'bad type' - return - dirList = dir(value) - - for dirItem in dirList: - if dirItem.startswith('_'): - continue - - dirData = None - try: - # Rare cases this can mess up, material.shader was a problem. - exec('dirData = %s.%s' % (dirString, dirItem)) - #print dirData - except: - # Dont bother with this data. - continue - #print 'HEY', dirData, dirItem - #if type(dirItem) != str: - # print dirItem, type(dirItem) - - if dirItem not in COLLECTED_VAR_NAMES: # .keys() - COLLECTED_VAR_NAMES[dirItem] = [] - - # Add the string - # splitD = dirString.split('"')[-2] - - # Example of dirString - # __CONSOLE_VAR_DICT__["Main"].scenes.active.render - - # Works but can be faster - # splitD = dirString.replace('__CONSOLE_VAR_DICT__["', '').replace('"]', '') - - splitD = dirString[22:].replace('"]', '') - - if splitD not in COLLECTED_VAR_NAMES[dirItem]: - # print dirItem, dirString, splitD, - COLLECTED_VAR_NAMES[dirItem].append(splitD) - - - # Stops recursice stuff, overlooping - #print type(dirItem) - #if type(dirData) == types.ClassType or \ - # type(dirData) == types.ModuleType: - type_dirData = type(dirData) - if type_dirData not in unused_types: - # print type(dirData), dirItem - # Dont loop up dirs for strings ints etc. - if dirItem not in dirStringSplit: - rdir( '%s.%s' % (dirString, dirItem), depth+1) - ''' - elif depth == 0: # Add local variables - # print type(dirData), dirItem - # Dont loop up dirs for strings ints etc. - if dirItem not in dirStringSplit: - rdir( '%s.%s' % (dirString, dirItem), depth+1) - ''' - -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. - __TMP_VAR_NAME__ = __TMP_VAR__ = '' # so as not to raise an error when del'ing - - for __TMP_VAR_NAME__, __TMP_VAR__ in __CONSOLE_VAR_DICT__.items(): - exec('%s%s' % (__TMP_VAR_NAME__,'=__TMP_VAR__')) - del __TMP_VAR_NAME__ - del __TMP_VAR__ - - # 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')) - - # Flush global dict, allow the user to remove items. - __CONSOLE_VAR_DICT__ = {} - - __TMP_VAR_NAME__ = '' # so as not to raise an error when del'ing - # 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 = '%s: %s' % (python_sys.exc_type, 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 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 - - def getIndent(string): - # Gather white space to add in the previous line - # Ignore the last char since its padding. - whiteSpace = '' - #for i in range(len(cmdBuffer[-1].cmd)): - for i in xrange(len(string)-1): - if cmdBuffer[-1].cmd[i] == ' ' or cmdBuffer[-1].cmd[i] == '\t': - whiteSpace += string[i] - else: - break - return whiteSpace - - # Autocomplete - if Window.GetKeyQualifiers() & Window.Qual.CTRL: - actionAutoCompleate() - return - - # Are we in the middle of a multiline part or not? - # try be smart about it - if cmdBuffer[-1].cmd.split('#')[0].rstrip().endswith(':'): - # : indicates an indent is needed - cmdBuffer.append(cmdLine('\t%s ' % getIndent(cmdBuffer[-1].cmd), 0, 0)) - print ': indicates an indent is needed' - - elif cmdBuffer[-1].cmd[0] in [' ', '\t'] and len(cmdBuffer[-1].cmd) > 1 and cmdBuffer[-1].cmd.split(): - # white space at the start means he havnt finished the multiline. - cmdBuffer.append(cmdLine('%s ' % getIndent(cmdBuffer[-1].cmd), 0, 0)) - print 'white space at the start means he havnt finished the multiline.' - - elif Window.GetKeyQualifiers() & Window.Qual.SHIFT: - # Crtl forces multiline - cmdBuffer.append(cmdLine('%s ' % getIndent(cmdBuffer[-1].cmd), 0, 0)) - print 'Crtl forces multiline' - - else: # Execute multiline code block - - # Multiline code will still run with 1 line, - multiLineCode = ['if 1:'] # End of the multiline first. - - # Seek the start of the file multiline - i = 1 - while cmdBuffer[-i].exe == 0: - i+=1 - - while i > 1: - i-=1 - - if cmdBuffer[-i].cmd == ' ':# Tag as an output type so its not used in the key history - cmdBuffer[-i].type = 1 - else: # Tab added at the start for added if 1: statement - multiLineCode.append('\t%s' % cmdBuffer[-i].cmd ) - - # Mark as executed - cmdBuffer[-i].exe = 1 - - multiLineCode.append('\tpass') # reverse will make this the start. - - # Dubug, print the code that is executed. - #for m in multiLineCode: print m - - runUserCode('\n'.join(multiLineCode)) - - # Clear the output based on __LINE_HISTORY__ - if len(cmdBuffer) > __LINE_HISTORY__: - cmdBuffer[:__LINE_HISTORY__] = [] - - histIndex = cursor = -1 # Reset cursor and history - - def actionUpKey(): - global histIndex - if abs(histIndex)+1 >= len(cmdBuffer): - histIndex = -1 - - # When wrapping allow 1 plank lines - if cmdBuffer[-1].cmd != ' ': - cmdBuffer[-1].cmd = ' ' - return - - histIndex_orig = histIndex - histIndex -= 1 - - while (cmdBuffer[histIndex].type != 0 and abs(histIndex) < len(cmdBuffer)) or \ - ( cmdBuffer[histIndex].cmd == cmdBuffer[histIndex_orig].cmd): - histIndex -= 1 - - if cmdBuffer[histIndex].type == 0: # we found one - cmdBuffer[-1].cmd = cmdBuffer[histIndex].cmd - - def actionDownKey(): - global histIndex - if histIndex >= -2: - histIndex = -len(cmdBuffer) - - # When wrapping allow 1 plank lines - if cmdBuffer[-1].cmd != ' ': - cmdBuffer[-1].cmd = ' ' - return - - histIndex_orig = histIndex - histIndex += 1 - while (cmdBuffer[histIndex].type != 0 and histIndex != -2) or \ - ( cmdBuffer[histIndex].cmd == cmdBuffer[histIndex_orig].cmd): - - histIndex += 1 - - if cmdBuffer[histIndex].type == 0: # we found one - cmdBuffer[-1].cmd = cmdBuffer[histIndex].cmd - - def actionRightMouse(): - global __FONT_SIZE__ - 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|Font Size|%l|Clear Output|Quit') - - if choice == 1: - writeCmdData(0) # type 0 user - elif choice == 2: - writeCmdData(1) # type 1 user output - elif choice == 3: - writeCmdData(2) # type 2 errors - elif choice == 4: - writeCmdData(3) # All - elif choice == 6: - insertCmdData() # Insert text from Blender and run it. - elif choice == 8: - # Fontsize. - font_choice = Draw.PupMenu('Font Size%t|Large|Normal|Small|Tiny') - if font_choice != -1: - if font_choice == 1: - __FONT_SIZE__ = 3 - elif font_choice == 2: - __FONT_SIZE__ = 2 - elif font_choice == 3: - __FONT_SIZE__ = 1 - elif font_choice == 4: - __FONT_SIZE__ = 0 - Draw.Redraw() - elif choice == 10: # Clear all output - cmdBuffer[:] = [cmd for cmd in cmdBuffer if cmd.type == 0] # keep user input - Draw.Redraw() - elif choice == 11: # Exit - Draw.Exit() - - - # Auto compleating, quite complex- use recutsice dir for the moment. - def actionAutoCompleate(): # Ctrl + Tab - if not cmdBuffer[-1].cmd[:cursor].split(): - return - - - 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 __VARIABLE_DELIMETERS__: - editVar = editVar[:-1].split(splitChar)[-1] + editVar[-1] - - - # Now we should have the var by its self - if editVar: - possibilities = [] - - for __TMP_VAR_NAME__ in RECURSIVE_DIR: #.keys(): - #print '\t', __TMP_VAR_NAME__ - if __TMP_VAR_NAME__ == editVar: - # print 'ADITVAR IS A VAR' - pass - ''' - elif __TMP_VAR_NAME__.startswith( editVar ): - print __TMP_VAR_NAME__, 'aaa' - possibilities.append( __TMP_VAR_NAME__ ) - ''' - 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)) - - menuList = [] # A lits of tuples- ABSOLUTE, RELATIVE - - for __TMP_VAR_NAME__ in possibilities: - for usage in RECURSIVE_DIR[__TMP_VAR_NAME__]: - # Account for non absolute (variables for eg.) - if usage: # not '' - absName = '%s.%s' % (usage, __TMP_VAR_NAME__) - - if __TMP_VAR_NAME__.startswith(editVar): - menuList.append( # Used for names and can be entered when pressing shift. - (absName, # Absolute name - __TMP_VAR_NAME__) # Relative name, non shift - ) - - #else: - # if absName.find(editVar) != -1: - # menuList.append((__TMP_VAR_NAME__, __TMP_VAR_NAME__)) # Used for names and can be entered when pressing shift. - - # No items to display? no menu - if not menuList: - return - - menuList.sort() - - choice = PupMenuLess( # Menu for the user to choose the autocompleate - 'Choices (Shift for local name, Ctrl for Docs)%t|' + # Title Text - '|'.join(['%s, %s' % m for m in menuList])) # Use Absolute names m[0] - - if choice != -1: - if Window.GetKeyQualifiers() & Window.Qual.CTRL: # Help - cmdBuffer[-1].cmd = ('help(%s%s) ' % (cmdBuffer[-1].cmd[:cursor - len(editVar)], menuList[choice-1][0])) - elif Window.GetKeyQualifiers() & Window.Qual.SHIFT: # Put in the long name - cmdBuffer[-1].cmd = ('%s%s%s' % (cmdBuffer[-1].cmd[:cursor - len(editVar)], menuList[choice-1][1], cmdBuffer[-1].cmd[cursor:])) - else: # Only paste in the Short name - cmdBuffer[-1].cmd = ('%s%s%s' % (cmdBuffer[-1].cmd[:cursor - len(editVar)], menuList[choice-1][0], cmdBuffer[-1].cmd[cursor:])) - - - else: - # print 'NO EDITVAR' - return - - # ------------------end------------------ # - - # Quit from menu only - #if (evt == Draw.ESCKEY and not val): - # Draw.Exit() - if evt == Draw.MOUSEX or evt == Draw.MOUSEY: # AVOID TOO MANY REDRAWS. - return - - - global cursor - global histIndex - global __FONT_SIZE__ - global __CONSOLE_LINE_OFFSET__ - - ascii = Blender.event - - resetScroll = True - - #------------------------------------------------------------------------------# - # 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): - if Window.GetKeyQualifiers() & Window.Qual.SHIFT: - wordJump = False - newCursor = cursor+1 - while newCursor<0: - - if cmdBuffer[-1].cmd[newCursor] not in __DELIMETERS__: - newCursor+=1 - else: - wordJump = True - break - if wordJump: # Did we find a new cursor pos? - cursor = newCursor - else: - cursor = -1 # end of line - else: - cursor +=1 - if cursor > -1: - cursor = -1 - - elif (evt == Draw.LEFTARROWKEY and val): - if Window.GetKeyQualifiers() & Window.Qual.SHIFT: - wordJump = False - newCursor = cursor-1 - while abs(newCursor) < len(cmdBuffer[-1].cmd): - - if cmdBuffer[-1].cmd[newCursor] not in __DELIMETERS__ or\ - newCursor == cursor: - newCursor-=1 - else: - wordJump = True - break - if wordJump: # Did we find a new cursor pos? - cursor = newCursor - else: - cursor = -len(cmdBuffer[-1].cmd) # Start of line - - else: - if len(cmdBuffer[-1].cmd) > abs(cursor): - cursor -=1 - - elif (evt == Draw.HOMEKEY and val): - cursor = -len(cmdBuffer[-1].cmd) - - elif (evt == Draw.ENDKEY and val): - cursor = -1 - - elif (evt == Draw.TABKEY and val): - insCh('\t') - - elif (evt == Draw.BACKSPACEKEY and val): - if Window.GetKeyQualifiers() & Window.Qual.SHIFT: - i = -1 - for d in __DELIMETERS__: - i = max(i, cmdBuffer[-1].cmd[:cursor-1].rfind(d)) - if i == -1: - i=0 - cmdBuffer[-1].cmd = ('%s%s' % (cmdBuffer[-1].cmd[:i] , cmdBuffer[-1].cmd[cursor:])) - - else: - # Normal backspace. - 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 (evt == Draw.PADPLUSKEY or evt == Draw.EQUALKEY or evt == Draw.WHEELUPMOUSE) and val and Window.GetKeyQualifiers() & Window.Qual.CTRL: - __FONT_SIZE__ += 1 - __FONT_SIZE__ = min(len(__FONT_SIZES__)-1, __FONT_SIZE__) - elif (evt == Draw.PADMINUS or evt == Draw.MINUSKEY or evt == Draw.WHEELDOWNMOUSE) and val and Window.GetKeyQualifiers() & Window.Qual.CTRL: - __FONT_SIZE__ -=1 - __FONT_SIZE__ = max(0, __FONT_SIZE__) - - - elif evt == Draw.WHEELUPMOUSE and val: - __CONSOLE_LINE_OFFSET__ += 1 - __CONSOLE_LINE_OFFSET__ = min(len(cmdBuffer)-2, __CONSOLE_LINE_OFFSET__) - resetScroll = False - - elif evt == Draw.WHEELDOWNMOUSE and val: - __CONSOLE_LINE_OFFSET__ -= 1 - __CONSOLE_LINE_OFFSET__ = max(0, __CONSOLE_LINE_OFFSET__) - resetScroll = False - - - elif ascii: - insCh(chr(ascii)) - else: - return # dont redraw. - - # If the user types in anything then scroll to bottom. - if resetScroll: - __CONSOLE_LINE_OFFSET__ = 0 - 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 - - - # Fixed margin. use a margin since 0 margin can be hard to seewhen close to a crt's edge. - margin = 4 - - # Convenience - FNT_NAME, FNT_HEIGHT = __FONT_SIZES__[__FONT_SIZE__] - - # Draw cursor location colour - if __CONSOLE_LINE_OFFSET__ == 0: - cmd2curWidth = Draw.GetStringWidth(cmdBuffer[-1].cmd[:cursor], FNT_NAME) - BGL.glColor3f(0.8, 0.2, 0.2) - if cmd2curWidth == 0: - BGL.glRecti(margin,2,margin+2, FNT_HEIGHT+2) - else: - BGL.glRecti(margin + cmd2curWidth-2,2, margin+cmd2curWidth, FNT_HEIGHT+2) - - BGL.glColor3f(1,1,1) - # Draw the set of cammands to the buffer - consoleLineIdx = __CONSOLE_LINE_OFFSET__ + 1 - wrapLineIndex = 0 - while consoleLineIdx < len(cmdBuffer) and __CONSOLE_RECT__[3] > (consoleLineIdx - __CONSOLE_LINE_OFFSET__) * FNT_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: # user input - BGL.glRasterPos2i(margin, (FNT_HEIGHT * (consoleLineIdx-__CONSOLE_LINE_OFFSET__)) - 8) - Draw.Text(cmdBuffer[-consoleLineIdx].cmd, FNT_NAME) - else: # WRAP - lwid = Draw.GetStringWidth(cmdBuffer[-consoleLineIdx].cmd, FNT_NAME) - if margin + lwid > __CONSOLE_RECT__[2]: - wrapLineList = [] - wtext = cmdBuffer[-consoleLineIdx].cmd - wlimit = len(wtext) - chunksz = int(( __CONSOLE_RECT__[2] - margin ) / (lwid / len(wtext))) - lstart = 0 - fsize = FNT_NAME - while lstart < wlimit: - lend = min(lstart+chunksz,wlimit) - ttext = wtext[lstart:lend] - while lend < wlimit and Draw.GetStringWidth(ttext, fsize) + margin < __CONSOLE_RECT__[2]: - lend += 1 - ttext = wtext[lstart:lend] - while lend > lstart+1 and Draw.GetStringWidth(ttext, fsize) + margin > __CONSOLE_RECT__[2]: - lend -= 1 - ttext = wtext[lstart:lend] - wrapLineList.append(ttext) - lstart = lend - # Now we have a list of lines, draw them (OpenGLs reverse ordering requires this odd change) - wrapLineList.reverse() - for wline in wrapLineList: - BGL.glRasterPos2i(margin, (FNT_HEIGHT*((consoleLineIdx-__CONSOLE_LINE_OFFSET__) + wrapLineIndex)) - 8) - Draw.Text(wline, FNT_NAME) - wrapLineIndex += 1 - wrapLineIndex-=1 # otherwise we get a silly extra line. - - else: # no wrapping. - - BGL.glRasterPos2i(margin, (FNT_HEIGHT * ((consoleLineIdx-__CONSOLE_LINE_OFFSET__)+wrapLineIndex)) - 8) - Draw.Text(cmdBuffer[-consoleLineIdx].cmd, FNT_NAME) - 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, add __bpydoc__ to the console startup. -for l in __bpydoc__.split('<br>'): - cmdBuffer.append( cmdLine(l, 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. -scriptDir = Get('scriptsdir') -console_autoexec = None -if scriptDir: - if not scriptDir.endswith(Blender.sys.sep): - scriptDir += Blender.sys.sep - - console_autoexec = '%s%s' % (scriptDir, 'console_autoexec.py') - - if not sys.exists(console_autoexec): - # touch the file - try: - open(console_autoexec, 'w').close() - cmdBuffer.append(cmdLine('...console_autoexec.py not found, making new in scripts dir', 1, None)) - except: - cmdBuffer.append(cmdLine('...console_autoexec.py could not write, this is ok', 1, None)) - scriptDir = None # make sure we only use this for console_autoexec.py - - if not sys.exists(console_autoexec): - console_autoexec = None - - else: - cmdBuffer.append(cmdLine('...Using existing console_autoexec.py in scripts 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 include_console(includeFile): - global __CONSOLE_VAR_DICT__ # write autoexec vars to this. - - # Execute an external py file as if local - exec(include(includeFile)) - -def standard_imports(): - # Write local to global __CONSOLE_VAR_DICT__ for reuse, - - exec('%s%s' % ('__CONSOLE_VAR_DICT__["bpy"]=', 'bpy')) - exec('%s%s' % ('__CONSOLE_VAR_DICT__["Blender"]=', 'Blender')) - - for ls in (dir(), dir(Blender)): - for __TMP_VAR_NAME__ in ls: - # Execute the local > global coversion. - exec('%s%s' % ('__CONSOLE_VAR_DICT__[__TMP_VAR_NAME__]=', __TMP_VAR_NAME__)) - - # Add dummy imports to input so output scripts to a text file work as expected - cmdBuffer.append(cmdLine('import bpy', 0, 1)) - cmdBuffer.append(cmdLine('import Blender', 0, 1)) # pretend we have been executed, as we kindof have. - cmdBuffer.append(cmdLine('from Blender import *', 0, 1)) - -if scriptDir and console_autoexec: - include_console(console_autoexec) # pass the blender module - -standard_imports() # import Blender and bpy - -#-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) - -if __name__ == '__main__': - main() |