forked from bartvdbraak/blender
Scripts:
- updating some bundled scripts, thanks to authors Jean-Michel Soler, Campbell Barton and Anthony D'Agostino. BPython: - removing wrong fix from BGL.c's glDrawPixels. note: applied guitargeek's setName patch to Blender.Key, but saw that he updated it with more functionality and assigned to stivs, so I won't commit this old version.
This commit is contained in:
parent
93a4f6a876
commit
b970eadedf
@ -18,11 +18,16 @@ 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 + arrow keys: jump words;<br>
|
||||
- Shift + Backspace: Backspace whole word;<br>
|
||||
- Shift + Arrow keys: jump words;<br>
|
||||
- Ctrl + (+/- or mousewheel): Zoom text size;<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.
|
||||
"""
|
||||
__author__ = "Campbell Barton AKA Ideasman"
|
||||
__url__ = ["http://members.iinet.net.au/~cpbarton/ideasman/", "blender", "elysiun"]
|
||||
|
||||
import Blender
|
||||
from Blender import *
|
||||
@ -31,14 +36,18 @@ import StringIO
|
||||
import types
|
||||
|
||||
# Constants
|
||||
__DELIMETERS__ = '. ,=+-*/%<>&~][{}():'
|
||||
__LINE_HISTORY__ = 200
|
||||
__DELIMETERS__ = '. ,=+-*/%<>&~][{}():\t'
|
||||
__VARIABLE_DELIMETERS__ = ' ,=+-*/%<>&~{}():\t'
|
||||
|
||||
__LINE_HISTORY__ = 500
|
||||
|
||||
global __LINE_HEIGHT__
|
||||
__LINE_HEIGHT__ = 14
|
||||
global __FONT_SIZE__
|
||||
__FONT_SIZE__ = "normal"
|
||||
|
||||
__FONT_SIZES__ = ( ('tiny', 10), ('small', 12), ('normal', 14), ('large', 16) )
|
||||
__FONT_SIZE__ = 2 # index for the list above, normal default.
|
||||
|
||||
global __CONSOLE_LINE_OFFSET__
|
||||
__CONSOLE_LINE_OFFSET__ = 0
|
||||
|
||||
'''
|
||||
# Generic Blender functions
|
||||
@ -52,10 +61,93 @@ def getActScriptWinRect():
|
||||
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
|
||||
|
||||
# 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)
|
||||
|
||||
|
||||
|
||||
def unzip(list):
|
||||
|
||||
"""
|
||||
unzip: inverse of zip - converts a list of tuples into a tuple of lists
|
||||
|
||||
e.g.
|
||||
a,b = unzip(zip(a,b))
|
||||
|
||||
* note: all tuples in list have to have the same length, if not,
|
||||
this function will fail
|
||||
"""
|
||||
|
||||
if len(list) == 0: return ()
|
||||
l = []
|
||||
for t in range(len(list[0])):
|
||||
l.append(map( lambda x,t=t: x[t], list ))
|
||||
return tuple(l)
|
||||
|
||||
|
||||
|
||||
# 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
|
||||
@ -97,32 +189,68 @@ def insertCmdData(cmdBuffer):
|
||||
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):
|
||||
def rdir(dirString, depth=0):
|
||||
|
||||
# MAX DEPTH SET HERE
|
||||
if depth > 4:
|
||||
print 'maxdepoth reached.'
|
||||
return
|
||||
|
||||
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] = []
|
||||
if dirItem.startswith('_'):
|
||||
continue
|
||||
|
||||
# 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))
|
||||
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
|
||||
|
||||
if type(dirItem) != type('str'):
|
||||
print dirItem, type(dirItem)
|
||||
|
||||
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
|
||||
#print type(dirItem)
|
||||
#if type(dirData) == types.ClassType or \
|
||||
# type(dirData) == types.ModuleType:
|
||||
|
||||
if type(dirData) != types.StringType and\
|
||||
type(dirData) != types.DictType and\
|
||||
type(dirData) != types.DictionaryType and\
|
||||
type(dirData) != types.FloatType and\
|
||||
type(dirData) != types.IntType and\
|
||||
type(dirData) != types.NoneType and\
|
||||
type(dirData) != types.StringTypes and\
|
||||
type(dirData) != types.TypeType and\
|
||||
type(dirData) != types.TupleType and\
|
||||
type(dirData) != types.BuiltinFunctionType:
|
||||
# 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
|
||||
@ -148,13 +276,17 @@ def runUserCode(__USER_CODE_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__, '"]'))
|
||||
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__ = {}
|
||||
|
||||
# Write local veriables to global __CONSOLE_VAR_DICT__
|
||||
for __TMP_VAR_NAME__ in dir():
|
||||
if __TMP_VAR_NAME__ != '__FILE_LIKE_STRING__' and\
|
||||
@ -167,14 +299,16 @@ def runUserCode(__USER_CODE_STRING__):
|
||||
del __TMP_VAR_NAME__
|
||||
|
||||
except: # Prints the REAL exception.
|
||||
error = str(python_sys.exc_value)
|
||||
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))
|
||||
|
||||
@ -203,34 +337,61 @@ def handle_event(evt, val):
|
||||
#------------------------------------------------------------------------------#
|
||||
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:
|
||||
|
||||
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 range(len(string)-1):
|
||||
if cmdBuffer[-1].cmd[i] == ' ' or cmdBuffer[-1].cmd[i] == '\t':
|
||||
whiteSpace += string[i]
|
||||
else:
|
||||
break
|
||||
return whiteSpace
|
||||
|
||||
# Are we in the moddle 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.CTRL:
|
||||
# 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:']
|
||||
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
|
||||
multiLineCode = ['if 1:'] # End of the multiline first.
|
||||
|
||||
# Seek the start of the file multiline
|
||||
i = 1
|
||||
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
|
||||
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))
|
||||
|
||||
@ -262,9 +423,8 @@ def handle_event(evt, val):
|
||||
|
||||
def actionRightMouse():
|
||||
global __FONT_SIZE__
|
||||
global __LINE_HEIGHT__
|
||||
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|Help|%l|Quit')
|
||||
# print choice
|
||||
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|Quit')
|
||||
|
||||
if choice == 1:
|
||||
writeCmdData(cmdBuffer, 0) # type 0 user
|
||||
elif choice == 2:
|
||||
@ -274,55 +434,56 @@ def handle_event(evt, val):
|
||||
elif choice == 4:
|
||||
writeCmdData(cmdBuffer, 3) # All
|
||||
elif choice == 6:
|
||||
insertCmdData(cmdBuffer) # All
|
||||
insertCmdData(cmdBuffer) # 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__ = 'large'
|
||||
__LINE_HEIGHT__ = 16
|
||||
__FONT_SIZE__ = 3
|
||||
elif font_choice == 2:
|
||||
__FONT_SIZE__ = 'normal'
|
||||
__LINE_HEIGHT__ = 14
|
||||
__FONT_SIZE__ = 2
|
||||
elif font_choice == 3:
|
||||
__FONT_SIZE__ = 'small'
|
||||
__LINE_HEIGHT__ = 12
|
||||
__FONT_SIZE__ = 1
|
||||
elif font_choice == 4:
|
||||
__FONT_SIZE__ = 'tiny'
|
||||
__LINE_HEIGHT__ = 10
|
||||
__FONT_SIZE__ = 0
|
||||
Draw.Redraw()
|
||||
elif choice == 10:
|
||||
Blender.ShowHelp('console.py')
|
||||
elif choice == 12: # Exit
|
||||
|
||||
elif choice == 10: # 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 __DELIMETERS__:
|
||||
editVar = editVar.split(splitChar)[-1]
|
||||
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 = []
|
||||
|
||||
print editVar, 'editVar'
|
||||
for __TMP_VAR_NAME__ in RECURSIVE_DIR.keys():
|
||||
#print '\t', __TMP_VAR_NAME__
|
||||
if __TMP_VAR_NAME__ == editVar:
|
||||
# print 'ADITVAR IS A VAR'
|
||||
continue
|
||||
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:]))
|
||||
|
||||
@ -332,36 +493,50 @@ def handle_event(evt, val):
|
||||
# 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 :)
|
||||
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 ''
|
||||
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
|
||||
absName = '%s.%s' % (usage, __TMP_VAR_NAME__)
|
||||
if absName.find('.'+editVar) != -1 or\
|
||||
absName.startswith(editVar) or\
|
||||
__TMP_VAR_NAME__.startswith(editVar):
|
||||
#print editVar, 'found in', absName
|
||||
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.
|
||||
|
||||
|
||||
#choice = Draw.PupMenu('Select Variabe name%t|' + '|'.join(possibilities) )
|
||||
choice = Draw.PupMenu(menuText + '|'.join(menuListAbs))
|
||||
if choice != -1:
|
||||
# No items to display? no menu
|
||||
if not menuList:
|
||||
return
|
||||
|
||||
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:]))
|
||||
menuList.sort()
|
||||
|
||||
choice = PupMenuLess( # Menu for the user to choose the autocompleate
|
||||
'Choices (Shift for Whole 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][0], 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][1], cmdBuffer[-1].cmd[cursor:]))
|
||||
|
||||
else:
|
||||
# print 'NO EDITVAR'
|
||||
return
|
||||
|
||||
# ------------------end------------------#
|
||||
|
||||
# ------------------end------------------ #
|
||||
|
||||
# Quit from menu only
|
||||
#if (evt == Draw.ESCKEY and not val):
|
||||
# Draw.Exit()
|
||||
if evt == Draw.MOUSEX: # AVOID TOO MANY REDRAWS.
|
||||
@ -370,15 +545,20 @@ def handle_event(evt, val):
|
||||
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()
|
||||
@ -436,23 +616,57 @@ def handle_event(evt, val):
|
||||
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.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.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__)
|
||||
@ -462,20 +676,24 @@ def draw_gui():
|
||||
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
|
||||
|
||||
# Draw cursor location colour
|
||||
cmd2curWidth = Draw.GetStringWidth(cmdBuffer[-1].cmd[:cursor], __FONT_SIZE__)
|
||||
BGL.glColor3f(0.8, 0.2, 0.2)
|
||||
if cmd2curWidth == 0:
|
||||
BGL.glRecti(0,2,2, __LINE_HEIGHT__+2)
|
||||
else:
|
||||
BGL.glRecti(cmd2curWidth-2,2,cmd2curWidth, __LINE_HEIGHT__+2)
|
||||
if __CONSOLE_LINE_OFFSET__ == 0:
|
||||
cmd2curWidth = Draw.GetStringWidth(cmdBuffer[-1].cmd[:cursor], __FONT_SIZES__[__FONT_SIZE__][0])
|
||||
BGL.glColor3f(0.8, 0.2, 0.2)
|
||||
if cmd2curWidth == 0:
|
||||
BGL.glRecti(margin,2,margin+2, __FONT_SIZES__[__FONT_SIZE__][1]+2)
|
||||
else:
|
||||
BGL.glRecti(margin + cmd2curWidth-2,2, margin+cmd2curWidth, __FONT_SIZES__[__FONT_SIZE__][1]+2)
|
||||
|
||||
BGL.glColor3f(1,1,1)
|
||||
# Draw the set of cammands to the buffer
|
||||
|
||||
consoleLineIdx = 1
|
||||
consoleLineIdx = __CONSOLE_LINE_OFFSET__ + 1
|
||||
wrapLineIndex = 0
|
||||
while consoleLineIdx < len(cmdBuffer) and __CONSOLE_RECT__[3] > consoleLineIdx*__LINE_HEIGHT__ :
|
||||
while consoleLineIdx < len(cmdBuffer) and __CONSOLE_RECT__[3] > (consoleLineIdx - __CONSOLE_LINE_OFFSET__) * __FONT_SIZES__[__FONT_SIZE__][1]:
|
||||
if cmdBuffer[-consoleLineIdx].type == 0:
|
||||
BGL.glColor3f(1, 1, 1)
|
||||
elif cmdBuffer[-consoleLineIdx].type == 1:
|
||||
@ -484,21 +702,22 @@ def draw_gui():
|
||||
BGL.glColor3f(1.0, 0, 0)
|
||||
elif cmdBuffer[-consoleLineIdx].type == 3:
|
||||
BGL.glColor3f(0, 0.8, 0)
|
||||
else:
|
||||
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__)
|
||||
BGL.glRasterPos2i(margin, (__FONT_SIZES__[__FONT_SIZE__][1] * (consoleLineIdx-__CONSOLE_LINE_OFFSET__)) - 8)
|
||||
# BUG, LARGE TEXT DOSENT DISPLAY
|
||||
Draw.Text(cmdBuffer[-consoleLineIdx].cmd, __FONT_SIZES__[__FONT_SIZE__][0])
|
||||
|
||||
|
||||
else: # WRAP?
|
||||
# LINE WRAP
|
||||
if Draw.GetStringWidth(cmdBuffer[-consoleLineIdx].cmd, __FONT_SIZE__) > __CONSOLE_RECT__[2]:
|
||||
if Draw.GetStringWidth(cmdBuffer[-consoleLineIdx].cmd, __FONT_SIZES__[__FONT_SIZE__][0]) > __CONSOLE_RECT__[2]:
|
||||
wrapLineList = []
|
||||
copyCmd = [cmdBuffer[-consoleLineIdx].cmd, '']
|
||||
while copyCmd != ['','']:
|
||||
while Draw.GetStringWidth(copyCmd[0], __FONT_SIZE__) > __CONSOLE_RECT__[2]:
|
||||
while margin + Draw.GetStringWidth(copyCmd[0], __FONT_SIZES__[__FONT_SIZE__][0]) > __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
|
||||
@ -513,17 +732,16 @@ def draw_gui():
|
||||
# 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__)
|
||||
BGL.glRasterPos2i(margin, (__FONT_SIZES__[__FONT_SIZE__][1]*((consoleLineIdx-__CONSOLE_LINE_OFFSET__) + wrapLineIndex)) - 8)
|
||||
Draw.Text(wline, __FONT_SIZES__[__FONT_SIZE__][0])
|
||||
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__)
|
||||
|
||||
|
||||
BGL.glRasterPos2i(margin, (__FONT_SIZES__[__FONT_SIZE__][1] * ((consoleLineIdx-__CONSOLE_LINE_OFFSET__)+wrapLineIndex)) - 8)
|
||||
Draw.Text(cmdBuffer[-consoleLineIdx].cmd, __FONT_SIZES__[__FONT_SIZE__][0])
|
||||
|
||||
consoleLineIdx += 1
|
||||
|
||||
|
||||
@ -536,42 +754,45 @@ def handle_button_event(evt):
|
||||
__CONSOLE_VAR_DICT__ = {} # Initialize var dict
|
||||
|
||||
|
||||
# Print Startup lines
|
||||
cmdBuffer = [cmdLine("Welcome to Ideasman's Blender Console", 1, None),\
|
||||
cmdLine(' * Right Click: Console Menu (Save output, etc.)', 1, None),\
|
||||
cmdLine(' * Arrow Keys: Command history and cursor', 1, None),\
|
||||
cmdLine(' * Shift With Arrow Keys: Jump words', 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)]
|
||||
# Print Startup lines, add __bpydoc__ to the console startup.
|
||||
cmdBuffer = []
|
||||
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.
|
||||
console_autoexec = '%s%s' % (Get('datadir'), '/console_autoexec.py')
|
||||
scriptDir = Get('scriptsdir')
|
||||
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
|
||||
cmdBuffer.append(cmdLine('...console_autoexec.py not found, making new in scripts dir', 1, None))
|
||||
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))
|
||||
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 autoexecToVarList():
|
||||
def include_console(includeFile):
|
||||
global __CONSOLE_VAR_DICT__ # write autoexec vars to this.
|
||||
|
||||
# Execute an external py file as if local
|
||||
exec(include(console_autoexec))
|
||||
exec(include(includeFile))
|
||||
|
||||
# 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
|
||||
include_console(console_autoexec) # pass the blender module
|
||||
#-end autoexec-----------------------------------------------------------------#
|
||||
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
""" Registration info for Blender menus: <- these words are ignored
|
||||
Name: 'Dispaint'
|
||||
Blender: 233
|
||||
Blender: 237
|
||||
Group: 'Mesh'
|
||||
Tip: 'use vertex paint color value to modify shape displacing vertices along normal'
|
||||
"""
|
||||
@ -11,7 +11,7 @@ __author__ = "Jean-Michel Soler (jms)"
|
||||
__url__ = ("blender", "elysiun",
|
||||
"Script's homepage, http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_displacementpainting.htm",
|
||||
"Communicate problems and errors, http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender")
|
||||
__version__ = "233i"
|
||||
__version__ = "237"
|
||||
|
||||
__bpydoc__ = """\
|
||||
This script displaces mesh vertices according to vertex color values.
|
||||
@ -81,6 +81,7 @@ from Blender.Draw import *
|
||||
from Blender.BGL import *
|
||||
from Blender.Noise import *
|
||||
from Blender.Scene import *
|
||||
from Blender.Window import *
|
||||
sc=Scene.getCurrent()
|
||||
|
||||
# niveau du deplacement
|
||||
@ -117,6 +118,7 @@ E_AXESELX = 46
|
||||
E_AXESELY = 47
|
||||
E_AXESELZ = 48
|
||||
|
||||
|
||||
E_NOISEME = 49
|
||||
E_NOISEH = 50
|
||||
E_NOISELAC = 51
|
||||
@ -126,10 +128,28 @@ E_NOISEBAS = 54
|
||||
E_NOISEVAL=[E_NOISEH,E_NOISELAC,E_NOISEOCT,E_NOISEOFF,E_NOISEBAS]
|
||||
E_NOISEDIM = 55
|
||||
|
||||
E_GETCOLORS = 56
|
||||
E_UVCOLORS = 57
|
||||
E_SAVECOLORS = 58
|
||||
B_SAVECOLORS = 0
|
||||
|
||||
E_RESTCOLORS = 60
|
||||
V_RESTCOL=0
|
||||
F_RESTCOL=0
|
||||
|
||||
BUF_COLORS=[]
|
||||
|
||||
RVBA_VALUE=61
|
||||
RVBA_VERTICES=62
|
||||
RVBA_FACES=63
|
||||
|
||||
ExitTIP="Exit from this script session "
|
||||
CreateTIP="Create a new copy of the selected shape"
|
||||
ActionTIP="Do the current selected actions"
|
||||
|
||||
UVCOLORSTIP="Get colrs from first available UV image "
|
||||
GETCOLORSTIP="Get color from textures "
|
||||
REPEATTIP="Replay the same action with new values ."
|
||||
|
||||
def copy_transform(ozero,Obis):
|
||||
Obis.setSize(ozero.getSize());
|
||||
@ -298,9 +318,23 @@ def DOCMat_list(TMATList):
|
||||
TMATList[0]=0
|
||||
return TMATList
|
||||
|
||||
MOname = "MODE MENU %t|Normal %x1|Material %x2|Selected %x3"
|
||||
MOname = "MODE MENU %t|Normal %x1|Material %x2|Selected %x3| Find color %x4"
|
||||
MOname_doc=["",
|
||||
"Displace all vertices",
|
||||
"Displace vertices only on selected materials . ",
|
||||
"Displace only selected vertices .",
|
||||
"Try to find and set selected the vertices with this color."]
|
||||
|
||||
ORname = "ORIENT MENU %t|From Normal %x1|Local Axes %x2| Noise %x3"
|
||||
NOname = "NOISE MENU %t|BLENDER %x1|STDPERLIN %x2|NEWPERLIN %x3|VORONOI_F1%x4|VORONOI_F2%x5|VORONOI_F3%x6|VORONOI_F4%x7|VORONOI_F2F1%x8|VORONOI_CRACKLE%x9|CELLNOISE%x10|HETEROTENOISE%x11"
|
||||
ORname_doc=["",
|
||||
"Use normal orientation to calculate displacement",
|
||||
"Use selected axes value to calculate displacement",
|
||||
"Blend the color value with Nosie values to calculate the displacement"]
|
||||
|
||||
NOname = "NOISE MENU %t|BLENDER %x1|STDPERLIN %x2|\
|
||||
NEWPERLIN %x3|VORONOI_F1%x4|VORONOI_F2%x5|\
|
||||
VORONOI_F3%x6|VORONOI_F4%x7|VORONOI_F2F1%x8|\
|
||||
VORONOI_CRACKLE%x9|CELLNOISE%x10|HETEROTENOISE%x11"
|
||||
|
||||
MODEMenu = Create(1)
|
||||
ORIENTMenu = Create(1)
|
||||
@ -351,48 +385,190 @@ glCl3=glColor3f
|
||||
glCl4=glColor4f
|
||||
glRct=glRectf
|
||||
|
||||
def triangle(a,b,c):
|
||||
glBegin(GL_TRIANGLES);
|
||||
glColor3f(a[2],a[3],a[4])
|
||||
glVertex2f(a[0],a[1]);
|
||||
glVertex2f(b[0],b[1]);
|
||||
glVertex2f(c[0],c[1]);
|
||||
glEnd();
|
||||
|
||||
def triangleFcolor(a,b,c):
|
||||
glBegin(GL_TRIANGLES);
|
||||
glColor4f(a[2],a[3],a[4],a[5])
|
||||
glVertex2f(a[0],a[1]);
|
||||
glColor4f(b[2],b[3],b[4],a[5])
|
||||
glVertex2f(b[0],b[1]);
|
||||
glColor4f(c[2],c[3],c[4],a[5])
|
||||
glVertex2f(c[0],c[1]);
|
||||
glEnd();
|
||||
|
||||
def Ltriangle(a,b,c,LC=0.5):
|
||||
TL=[a,b,c,a]
|
||||
for v in [0,1,2] :
|
||||
glBegin(GL_LINES);
|
||||
glColor3f(LC,LC,LC)
|
||||
glVertex2f(TL[v][0],TL[v][1]);
|
||||
glVertex2f(TL[v+1][0],TL[v+1][1]);
|
||||
glEnd();
|
||||
|
||||
|
||||
def carreFcolor(a,b,c,d):
|
||||
triangleFcolor(a,b,c)
|
||||
triangleFcolor(a,c,d)
|
||||
|
||||
RVBA=[Create(255),Create(255),Create(255),Create(255),Create(0)]
|
||||
|
||||
# _*_ p1
|
||||
# _/ \_
|
||||
# _/ \_
|
||||
# / \_
|
||||
# p0*_ /* p2
|
||||
# | \_ _/ |
|
||||
# | \_ _/ |
|
||||
# | \_ _/ |
|
||||
# | * p3 |
|
||||
# | | |
|
||||
# *_ | /* p4
|
||||
# p6 \_ | _/
|
||||
# \_ | _/
|
||||
# \_|_/
|
||||
# * p5
|
||||
|
||||
def flatcolorcube(r,g,b,a,m,x,y):
|
||||
h0=60
|
||||
v0=40
|
||||
A=[x, y, (r-m)/255.0,g/255.0,b/255.0,a/255.0] #p0
|
||||
B=[x+h0,y-v0, r/255.0,g/255.0,b/255.0,a/255.0] #p3
|
||||
c=[x+h0*2,y, r/255.0, g/255.0, (b-m)/255.0,a/255.0] #p2
|
||||
d=[x+h0,y+v0, (r-m)/255.0,g/255.0,(b-m)/255.0,a/255.0] #p1
|
||||
carreFcolor(A,B,c,d)
|
||||
|
||||
|
||||
A=[x,y,(r-m)/255.0,g/255.0,b/255.0,a/255.0] #p0
|
||||
B=[x+h0,y-v0,r/255.0,g/255.0,b/255.0,a/255.0] #p3
|
||||
c=[x+h0,y-v0*2.5, r/255.0, (g-m)/255.0, b/255.0,a/255.0] #p5
|
||||
d=[x,y-v0*1.5,(r-m)/255.0,(g-m)/255.0,b/255.0,a/255.0] #p6
|
||||
carreFcolor(A,B,c,d)
|
||||
|
||||
d=[x+h0,y-v0,r/255.0,g/255.0,b/255.0,a/255.0] #p3
|
||||
A=[x+h0*2,y,r/255.0,g/255.0,(b-m)/255.0,a/255.0] #p2
|
||||
B=[x+h0*2,y-v0*1.5, r/255.0, (g-m)/255.0,(b-m)/255.0,a/255.0] #p4
|
||||
c=[x+h0,y-v0*2.5,r/255.0,(g-m)/255.0,b/255.0,a/255.0] #p5
|
||||
carreFcolor(A,B,c,d)
|
||||
|
||||
def col_egal2col(col,RVBA):
|
||||
eps=RVBA[4].val
|
||||
if ( (RVBA[0].val-col[0]>=0 and RVBA[0].val-col[0]<=eps) and
|
||||
(RVBA[1].val-col[1]>=0 and RVBA[1].val-col[1]<=eps) and
|
||||
(RVBA[2].val-col[2]>=0 and RVBA[2].val-col[2]<=eps) and
|
||||
(RVBA[3].val-col[3]>=0 and RVBA[3].val-col[3]<=eps) ) :
|
||||
#print 'ok',col, [RVBA[n].val-col[n] for n in 0,1,2,3]
|
||||
return 1
|
||||
else:
|
||||
#print 'not',col, [RVBA[n].val-col[n] for n in 0,1,2,3]
|
||||
return 0
|
||||
|
||||
def select_bycolors(TYPE,RVBA):
|
||||
global RVBA_VERTICES, RVBA_FACES
|
||||
SEL = Blender.NMesh.FaceFlags['SELECT']
|
||||
try:
|
||||
ME=Blender.Scene.getCurrent().getActiveObject().getData()
|
||||
VC={}
|
||||
for f in ME.faces:
|
||||
for v in f.v:
|
||||
try:
|
||||
VC[v].append(f)
|
||||
except:
|
||||
VC[v]=[f]
|
||||
#print '.',
|
||||
for C in VC.iteritems():
|
||||
color=[0,0,0]
|
||||
for f in C[1]:
|
||||
col=f.col[f.v.index(C[0])]
|
||||
col=[col.r,col.g,col.b,col.a]
|
||||
if col_egal2col(col,RVBA):
|
||||
if TYPE== RVBA_VERTICES:
|
||||
C[0].sel=1
|
||||
else:
|
||||
f.sel=1
|
||||
f.flag |= SEL
|
||||
#VC[C[0]].append(color[:])
|
||||
ME.update()
|
||||
except:
|
||||
pass
|
||||
|
||||
def draw():
|
||||
global MODEMenu, NSIZE, TDOCMat,TMATList, TAXEList
|
||||
global mat, ORIName, NEWName, ORIENTMenu
|
||||
global NRepeat, ERROR, TextERROR , NOISE, NOISEMenu, NOISEDIMbout,NOISEDIM
|
||||
global NRepeat, ERROR, TextERROR , NOISE, NOISEMenu
|
||||
global NOISEDIMbout,NOISEDIM, RVBA,RVB_VALUE, RVBA_VERTICES
|
||||
global HBout,lacunarityBout,octavesBout,offsetBout,basisBout
|
||||
global noiseTYPE, ExitTIP, CreateTIP, ActionTIP
|
||||
|
||||
global noiseTYPE, ExitTIP, CreateTIP, ActionTIP, E_GETCOLORS
|
||||
global E_UVCOLORS, UVCOLORSTIP, GETCOLORSTIP, REPEATTIP,RVBA_FACES
|
||||
global E_SAVECOLORS, B_SAVECOLORS, E_RESTCOLORS, MOname_doc, ORname_doc
|
||||
|
||||
size=Buffer(GL_FLOAT, 4)
|
||||
glGetFloatv(GL_SCISSOR_BOX, size)
|
||||
size= size.list
|
||||
|
||||
for s in [0,1,2,3]: size[s]=int(size[s])
|
||||
|
||||
|
||||
glClearColor(0.72,0.72,0.72,1.0)
|
||||
glClear(GL_COLOR_BUFFER_BIT)
|
||||
|
||||
glColor3f(0.0,0.0,0.0)
|
||||
glRectf(4,size[3],534,size[3]-32 )
|
||||
glColor3f(0.66,0.66,0.66)
|
||||
glRectf(4,size[3]-4,404,size[3]-32 )
|
||||
|
||||
glColor3f(0.76,0.76,0.76)
|
||||
glRectf(4,size[3]-32,404,size[3]-294 )
|
||||
|
||||
triangle([4+9,size[3],0.72,0.72,0.72],
|
||||
[4,size[3],],
|
||||
[4,size[3]-9])
|
||||
|
||||
triangle([404-9,size[3],0.72,0.72,0.72],
|
||||
[404,size[3],],
|
||||
[404,size[3]-9])
|
||||
|
||||
triangle([404,size[3]-294,.72,0.72,0.72],
|
||||
[404,size[3]-294+9,],
|
||||
[404-9,size[3]-294])
|
||||
|
||||
triangle([4,size[3]-294,.72,0.72,0.72],
|
||||
[4,size[3]-294+9,],
|
||||
[4+9,size[3]-294])
|
||||
|
||||
glColor3f(1.0,1.0,1.0)
|
||||
glRasterPos2f(20, size[3]-15)
|
||||
Text("Script Python de displacement paintingt")
|
||||
Text("Script Python de displacement painting")
|
||||
|
||||
glRasterPos2f(20, size[3]-28)
|
||||
Text("Jean-michel Soler, juillet 2004")
|
||||
Text("Jean-michel Soler, Aout 2005")
|
||||
|
||||
|
||||
n0=70
|
||||
n1=55
|
||||
if MODEMenu.val<4 :
|
||||
Button("Create" ,E_CREATE ,5 ,size[3]-n0+11 ,60 ,20,CreateTIP)
|
||||
Button("Action" ,E_ACTION ,5 ,size[3]-n0-11 ,60 ,20,ActionTIP)
|
||||
NRepeat=Number("repeat" ,E_REPEAT ,5 ,size[3]-n0-56 ,75 ,20, NRepeat.val,1,10,REPEATTIP)
|
||||
|
||||
Button("Exit" ,E_EXIT ,5 ,size[3]-n0-32 ,60 ,20,ExitTIP)
|
||||
Button("Tex colors" ,E_GETCOLORS ,5 ,size[3]-n0-80 ,75 ,20,GETCOLORSTIP)
|
||||
Button("UV colors" ,E_UVCOLORS ,5 ,size[3]-n0-102 ,75 ,20,UVCOLORSTIP)
|
||||
if B_SAVECOLORS :
|
||||
Button("Rest colors" ,E_RESTCOLORS ,5 ,size[3]-n0-146 ,75 ,20,UVCOLORSTIP)
|
||||
else:
|
||||
Button("Save colors" ,E_SAVECOLORS ,5 ,size[3]-n0-124 ,75 ,20,GETCOLORSTIP)
|
||||
|
||||
|
||||
Button("Create" ,E_CREATE ,5 ,size[3]-n0+16 ,60 ,20,CreateTIP)
|
||||
Button("Action" ,E_ACTION ,5 ,size[3]-n0-4 ,60 ,20,ActionTIP)
|
||||
Button("Exit" ,E_EXIT ,5 ,size[3]-n0-24 ,60 ,20,ExitTIP)
|
||||
|
||||
NRepeat=Number("repeat" ,E_REPEAT ,5 ,size[3]-n0-50 ,75 ,20, NRepeat.val,1,10)
|
||||
|
||||
glColor3f(0.0,0.0,0.0)
|
||||
glRasterPos2f(80 ,size[3]-n0+24)
|
||||
Text("MODE")
|
||||
|
||||
MODEMenu= Menu(MOname, E_MODE ,80 ,size[3]-n0 ,100,20, MODEMenu.val, "MODE menu.")
|
||||
MODEMenu= Menu(MOname, E_MODE ,80 ,size[3]-n0 ,100,20, MODEMenu.val, MOname_doc[MODEMenu.val])
|
||||
|
||||
if MODEMenu.val==2:
|
||||
TDOCMat=Toggle("Doc Mat" ,E_DOCMAT ,180 ,size[3]-n0 ,60 ,20,TDOCMat.val)
|
||||
@ -402,14 +578,22 @@ def draw():
|
||||
glCl3(TMATList[1][t][0],
|
||||
TMATList[1][t][1],
|
||||
TMATList[1][t][2])
|
||||
glRct(80+t*40,
|
||||
size[3]-n0-60,
|
||||
80+t*40+40,
|
||||
size[3]-n0-60+40)
|
||||
TMATList[2][t]=Toggle("%s"%t , 32+t ,80+t*40+5 ,size[3]-n0-50 ,30 , 20,TMATList[2][t].val)
|
||||
|
||||
if t<=7:
|
||||
glRct(80+t*40,
|
||||
size[3]-n0-60,
|
||||
80+t*40+40,
|
||||
size[3]-n0-60+40)
|
||||
TMATList[2][t]=Toggle("%s"%(t+1) , 32+t ,80+t*40+5 ,size[3]-n0-50 ,30 , 20,TMATList[2][t].val)
|
||||
else:
|
||||
glRct(80+(t-8)*40,
|
||||
size[3]-n0-50-50,
|
||||
80+(t-8)*40+40,
|
||||
size[3]-n0-60)
|
||||
TMATList[2][t]=Toggle("%s"%(t+1) , 32+t ,80+(t-8)*40+5 ,size[3]-n0-45*2 ,30 , 20,TMATList[2][t].val)
|
||||
|
||||
glColor3f(1.0,0.3,0.0)
|
||||
glRasterPos2f(80+40+5 ,size[3]-n0-80)
|
||||
glRasterPos2f(80+40+5 ,size[3]-n0-110)
|
||||
if ERROR>1:
|
||||
Text('Last error : '+TextERROR)
|
||||
else:
|
||||
@ -417,35 +601,66 @@ def draw():
|
||||
|
||||
glColor3f(0.0,0.0,0.0)
|
||||
glRasterPos2f(240 ,size[3]-n0+24)
|
||||
Text("ORIENTATION")
|
||||
ORIENTMenu= Menu(ORname, E_ORIENT ,240 ,size[3]-n0 ,100,20, ORIENTMenu.val, "ORIENT menu.")
|
||||
|
||||
if ORIENTMenu.val==2 :
|
||||
for t in range(3):
|
||||
TAXEList[1][t]=Toggle("%s"%TAXEList[0][t],
|
||||
E_AXESEL+t,
|
||||
240+100+t*30 , size[3]-n0 ,30 , 20,
|
||||
TAXEList[1][t].val)
|
||||
|
||||
|
||||
if ORIENTMenu.val==3 :
|
||||
glRasterPos2f(240 ,size[3]-n0-90-4)
|
||||
Text("NOISE")
|
||||
NOISEMenu= Menu(NOname, E_NOISEME , 240 ,size[3]-n0-118 ,110,20, NOISEMenu.val, "NOISE menu.")
|
||||
NOISEDIMbout=Number(" Dim: " ,E_NOISEDIM , 240 ,size[3]-n0-138 ,110,20, NOISEDIMbout.val, 1,100)
|
||||
|
||||
if NOISEMenu.val==11:
|
||||
basisBout=Slider(noiseTYPE[basisBout.val],
|
||||
E_NOISEBAS ,40 ,size[3]-n0-118 ,175,20, basisBout.val, 0,9,)
|
||||
HBout= Slider("H", E_NOISEH ,40 ,size[3]-n0-138 ,175,20, HBout.val, -2.0,+2.0,0,)
|
||||
lacunarityBout=Slider("lacunarity", E_NOISELAC ,40 ,size[3]-n0-158 ,175,20, lacunarityBout.val, -4.0,+4.0,0,)
|
||||
octavesBout=Slider("octave", E_NOISEOCT ,40 ,size[3]-n0-178 ,175,20, octavesBout.val, -10.0,+10.0,0,)
|
||||
offsetBout=Slider("offset", E_NOISEOFF ,40 ,size[3]-n0-198 ,175,20, offsetBout.val, -5.0,+5.0,0,)
|
||||
|
||||
NSIZE= Slider("Disp Size", E_NSIZE ,80 ,size[3]-n0-20 ,260,20, NSIZE.val, -4.0,+4.0,0,"SIZE.")
|
||||
if MODEMenu.val<4:
|
||||
Text("ORIENTATION")
|
||||
ORIENTMenu= Menu(ORname, E_ORIENT ,240 ,size[3]-n0 ,100,20, ORIENTMenu.val, ORname_doc[ORIENTMenu.val])
|
||||
if ORIENTMenu.val==2 :
|
||||
for t in [0,1]:
|
||||
TAXEList[1][t]=Toggle("%s"%TAXEList[0][t],
|
||||
E_AXESEL+t,
|
||||
240+100+t*30+2 , size[3]-n0+10 ,28 , 18,
|
||||
TAXEList[1][t].val)
|
||||
TAXEList[1][2]=Toggle("%s"%TAXEList[0][2],
|
||||
E_AXESEL+2,
|
||||
int(240+100+.5*30+2) , size[3]-n0-10 ,28 , 18,
|
||||
TAXEList[1][2].val)
|
||||
if ORIENTMenu.val==3 :
|
||||
glRasterPos2f(240 ,size[3]-n0-120-4)
|
||||
Text("NOISE")
|
||||
NOISEMenu= Menu(NOname, E_NOISEME , 240 ,size[3]-n0-148 ,110,20, NOISEMenu.val, "NOISE menu.")
|
||||
NOISEDIMbout=Number(" Dim: " ,E_NOISEDIM , 240 ,size[3]-n0-172 ,110,20, NOISEDIMbout.val, 1,100)
|
||||
if NOISEMenu.val==11:
|
||||
basisBout=Slider(noiseTYPE[basisBout.val],
|
||||
E_NOISEBAS ,40 ,size[3]-n0-178 ,175,20, basisBout.val, 0,9,)
|
||||
HBout= Slider("H", E_NOISEH ,40 ,size[3]-n0-198 ,175,20, HBout.val, -2.0,+2.0,0,)
|
||||
lacunarityBout=Slider("lacunarity", E_NOISELAC ,40 ,size[3]-n0-218 ,175,20, lacunarityBout.val, -4.0,+4.0,0,)
|
||||
octavesBout=Slider("octave", E_NOISEOCT ,219 ,size[3]-n0-198 ,175,20, octavesBout.val, -10.0,+10.0,0,)
|
||||
offsetBout=Slider("offset", E_NOISEOFF ,219 ,size[3]-n0-218 ,175,20, offsetBout.val, -5.0,+5.0,0,)
|
||||
NSIZE= Slider("Disp Size", E_NSIZE ,80 ,size[3]-n0-20 ,260,20, NSIZE.val, -4.0,+4.0,0,"SIZE.")
|
||||
|
||||
|
||||
|
||||
else:
|
||||
# degrades de couleurs
|
||||
glShadeModel(GL_SMOOTH)
|
||||
#transparence
|
||||
glEnable(GL_BLEND)
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
|
||||
|
||||
RVBA[0]=Slider("Red :", RVBA_VALUE , 105 ,size[3]-n0-25 ,280,20, RVBA[0].val, 0,255,0,"")
|
||||
RVBA[1]=Slider("Green :", RVBA_VALUE , 105 ,size[3]-n0-47 ,280,20, RVBA[1].val, 0,255,0,"")
|
||||
RVBA[2]=Slider("Blue :", RVBA_VALUE , 105 ,size[3]-n0-69 ,280,20, RVBA[2].val, 0,255,0,"")
|
||||
RVBA[3]=Slider("Alpha :", RVBA_VALUE , 105 ,size[3]-n0-91 ,150,20, RVBA[3].val, 0,255,0,"")
|
||||
RVBA[4]=Slider("margin :", RVBA_VALUE , 105 ,size[3]-n0-113 ,150,20, RVBA[4].val, 0,255,0,"")
|
||||
flatcolorcube(RVBA[0].val,
|
||||
RVBA[1].val,
|
||||
RVBA[2].val,
|
||||
RVBA[3].val,
|
||||
RVBA[4].val,
|
||||
270,size[3]-n0-120)
|
||||
|
||||
Button("Vertex" ,RVBA_VERTICES ,5 ,size[3]-n0-148 ,75 ,20,CreateTIP)
|
||||
Button("Faces" ,RVBA_FACES ,5 ,size[3]-n0-169 ,75 ,20,ActionTIP)
|
||||
|
||||
|
||||
def on_MESH():
|
||||
Me=Object.GetSelected()
|
||||
if Me!=[] and Me[0].getType()=='Mesh':
|
||||
editmode = Window.EditMode()
|
||||
if editmode: Window.EditMode(0)
|
||||
return 1,Me[0].getData()
|
||||
else:
|
||||
return 0, None
|
||||
|
||||
def event(evt, val):
|
||||
if (evt== QKEY and not val): Exit()
|
||||
@ -455,21 +670,20 @@ def bevent(evt):
|
||||
global mat, ORIENTMenu, NRepeat, TAXEList
|
||||
global ERROR,TextERROR, NOISE, NOISEMenu, NOISEDIMbout,NOISEDIM
|
||||
global HBout,lacunarityBout,octavesBout,offsetBout,basisBout
|
||||
global H,lacunarity,octaves,offset,basis
|
||||
|
||||
global H,lacunarity,octaves,offset,basis, E_RESTCOLORS, RVBA_VERTICES
|
||||
global E_GETCOLORS, E_UVCOLORS, E_SAVECOLORS, B_SAVECOLORS
|
||||
global V_RESTCOLORS, F_RESTCOLORS, BUF_COLORS, RVBA, RVBA_FACES
|
||||
|
||||
if (evt== E_EXIT):
|
||||
Exit()
|
||||
|
||||
|
||||
elif (evt== E_ACTION):
|
||||
for n in range(NRepeat.val):
|
||||
paint()
|
||||
|
||||
elif (evt== E_NSIZE):
|
||||
ng=NSIZE.val
|
||||
|
||||
elif (evt== E_DOCMAT) or (evt in E_MATVAL):
|
||||
Me=Object.GetSelected()
|
||||
|
||||
if Me!=[]:
|
||||
if Me[0].getType()=='Mesh':
|
||||
TMATList=DOCMat_list(TMATList)
|
||||
@ -484,29 +698,68 @@ def bevent(evt):
|
||||
else:
|
||||
ERROR=1
|
||||
TextERROR='No Selected Object.'
|
||||
|
||||
|
||||
elif (evt== E_CREATE):
|
||||
|
||||
NEWMEcreation(Blender.Object.GetSelected()[0])
|
||||
Blender.Draw.Redraw()
|
||||
|
||||
ERROR=1
|
||||
TextERROR='No Selected Object.'
|
||||
|
||||
elif (evt== E_NOISEME):
|
||||
NOISE=NOISEMenu.val-1
|
||||
|
||||
elif (evt in E_NOISEVAL):
|
||||
H=HBout.val
|
||||
lacunarity=lacunarityBout.val
|
||||
octaves=octavesBout.val
|
||||
offset=offsetBout.val
|
||||
basis=basisBout.val
|
||||
|
||||
elif (evt== E_NOISEDIM):
|
||||
NOISEDIM=NOISEDIMbout.val
|
||||
|
||||
elif (evt == E_GETCOLORS):
|
||||
OK,MESH=on_MESH()
|
||||
if OK: MESH.update(1,0,1)
|
||||
elif (evt == E_UVCOLORS):
|
||||
OK,MESH=on_MESH()
|
||||
if OK and MESH.hasFaceUV():
|
||||
for f in MESH.faces:
|
||||
if f.image:
|
||||
im=Blender.Image.Get(f.image.name)
|
||||
break
|
||||
imX,imY = im.getMaxXY()
|
||||
for f in MESH.faces:
|
||||
for uv in f.uv:
|
||||
color=[int(c*255.0) for c in im.getPixelF(abs(uv[0]*imX%imX), abs(uv[1]*imY%imY))]
|
||||
f.col[f.uv.index(uv)].r=color[0]
|
||||
f.col[f.uv.index(uv)].g=color[1]
|
||||
f.col[f.uv.index(uv)].b=color[2]
|
||||
f.col[f.uv.index(uv)].a=color[3]
|
||||
MESH.update()
|
||||
elif (evt == E_SAVECOLORS):
|
||||
OK,MESH=on_MESH()
|
||||
print OK, MESH
|
||||
if OK and (MESH.hasFaceUV() or MESH.hasVertexColours()):
|
||||
F_RESTCOLORS=1
|
||||
for f in MESH.faces:
|
||||
b=[MESH.faces.index(f)]
|
||||
for c in f.col:
|
||||
b.append([c.r,c.g,c.b,c.a])
|
||||
BUF_COLORS.append(b)
|
||||
B_SAVECOLORS = 1
|
||||
else:
|
||||
B_SAVECOLORS = 0
|
||||
elif (evt == E_RESTCOLORS):
|
||||
OK,MESH=on_MESH()
|
||||
print F_RESTCOLORS, len(BUF_COLORS),len(MESH.faces)
|
||||
if OK and F_RESTCOLORS==1 and len(BUF_COLORS)==len(MESH.faces):
|
||||
for b in BUF_COLORS:
|
||||
ncol=0
|
||||
for c in MESH.faces[b[0]].col :
|
||||
print b[ncol+1]
|
||||
c.r,c.g,c.b,c.a= b[ncol+1]
|
||||
ncol+=1
|
||||
F_RESTCOLORS=0
|
||||
B_SAVECOLORS = 0
|
||||
BUF_COLORS=[]
|
||||
MESH.update()
|
||||
elif (evt == RVBA_VERTICES or evt == RVBA_FACES):
|
||||
select_bycolors(evt,RVBA)
|
||||
Blender.Draw.Redraw()
|
||||
|
||||
Register(draw, event, bevent)
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
""" Registration info for Blender menus:
|
||||
Name: 'HotKey and MouseAction Reference'
|
||||
Blender: 232
|
||||
Blender: 237
|
||||
Group: 'Help'
|
||||
Tip: 'All the hotkeys/short keys'
|
||||
"""
|
||||
@ -11,7 +11,7 @@ __author__ = "Jean-Michel Soler (jms)"
|
||||
__url__ = ("blender", "elysiun",
|
||||
"Script's homepage, http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_hotkeyscript.htm",
|
||||
"Communicate problems and errors, http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender")
|
||||
__version__ = "10/2004"
|
||||
__version__ = "10/04/2005"
|
||||
|
||||
__bpydoc__ = """\
|
||||
This script is a reference about all hotkeys and mouse actions in Blender.
|
||||
@ -22,6 +22,8 @@ Open the script from the Help menu and select group of keys to browse.
|
||||
|
||||
Notes:<br>
|
||||
Additional entries in the database (c) 2004 by Bart.
|
||||
Additional entries in the database for blender 2.37 (c) 2005 by jms.
|
||||
|
||||
"""
|
||||
|
||||
# $Id$
|
||||
@ -67,11 +69,12 @@ from Blender.Draw import *
|
||||
from Blender.BGL import *
|
||||
|
||||
hotkeys={
|
||||
'Search ':[['', '']],
|
||||
'Specials 1 ':[
|
||||
[',', 'Set Bounding Box rotation scaling pivot'],
|
||||
['Ctrl-,', 'Set Median Point rotation scaling pivot'],
|
||||
['.', 'Set 3D cursor as rotation scaling pivot'],
|
||||
['Ctrl-.', 'Set Individual Object Centers as rotation scaling pivot'] ,
|
||||
['Ctrl-.', 'Set Individual Object Centers as rotation scaling pivot'],
|
||||
['~', 'Display all layers (German keys: ö)'],
|
||||
['Shift-~', 'Display all/previous layers (German keys: Shift-ö)'],
|
||||
['Space', 'Popup menu'],
|
||||
@ -82,9 +85,10 @@ hotkeys={
|
||||
['TAB', 'IPO: Edit selected'],
|
||||
['Ctrl-TAB', 'Enter/exit Pose Mode'],
|
||||
['Shift-TAB', 'Enter Object Mode'],
|
||||
['Ctrl-Open menu/', ''],
|
||||
['Ctrl-Open menu /', ''],
|
||||
['Ctrl-Load Image', 'Opens a thumbnail browser instead of file browser for images']
|
||||
],
|
||||
|
||||
'Mouse ':[
|
||||
['Actions:', ''],
|
||||
['LMB', '3D View: Set 3D Cursor'],
|
||||
@ -111,6 +115,7 @@ hotkeys={
|
||||
['MMB', 'Toggle optional transform feature'],
|
||||
['RMB', 'Abort transformation']
|
||||
],
|
||||
|
||||
'F-Keys ':[
|
||||
['F1', 'Open File'],
|
||||
['F2', 'Save File'],
|
||||
@ -133,13 +138,18 @@ hotkeys={
|
||||
['Shift-F7', 'Buttons Window'],
|
||||
['Shift-F8', 'Video Sequencer Window'],
|
||||
['Shift-F9', 'OOP Window'],
|
||||
['Alt-Shift-F9', 'OutLiner Window'],
|
||||
['Shift-F10', 'UV Image Editor'],
|
||||
['Shift-F11', 'Text Editor'],
|
||||
['Shift-F12', 'Action Editor']
|
||||
['Shift-F12', 'Action Editor'],
|
||||
['Ctrl-F2', 'Save/export in vrml 1.0 format' ],
|
||||
['Ctrl-F3', 'Save image : dump 3d view'],
|
||||
['Ctrl-Shift-F3', 'Save image : dump screen']
|
||||
],
|
||||
|
||||
'Numbers ':[
|
||||
['1..2..0-=', 'Show layer 1..2..12'],
|
||||
['1..2..0-=', 'Edit Mode with Size, Grab, rotate tools : enter value'],
|
||||
['Alt-1..2..0', 'Show layer 11..12..20'],
|
||||
['Shift-1..2..0-=', 'Toggle layer 1..2..12'],
|
||||
['Shift-ALT-...', 'Toggle layer 11..12..20']
|
||||
@ -150,10 +160,12 @@ hotkeys={
|
||||
['Numpad /', 'Local view on object (hide others)'],
|
||||
['Numpad *', 'Rotate view to objects local axes'],
|
||||
['Numpad +', 'Zoom in (works everywhere)'],
|
||||
['Numpad +', 'Proportional vertex Edit Mode: Increase range of influence'],
|
||||
['Numpad +', 'In OutLiner window, Collapse one level of the hierarchy'],
|
||||
['Alt-Numpad +', 'Proportional vertex Edit Mode: Increase range of influence'],
|
||||
['Ctrl-Numpad +', 'Edit Mode: Select More vertices'],
|
||||
['Numpad -', 'Zoom out (works everywhere)'],
|
||||
['Numpad -', 'Proportional vertex Edit Mode: Decrease range of influence'],
|
||||
['Numpad +', 'In OutLiner window, Expand one level of the hierarchy'],
|
||||
['Alt-Numpad -', 'Proportional vertex Edit Mode: Decrease range of influence'],
|
||||
['Ctrl-Numpad +', 'Edit Mode: Select Less vertices'],
|
||||
['Numpad INS', 'Set Camera view'],
|
||||
['Ctrl-Numpad INS', 'Set active object as camera'],
|
||||
@ -174,10 +186,19 @@ hotkeys={
|
||||
|
||||
'Arrows ':[
|
||||
['Home/Pos1', 'View all'],
|
||||
['Home', 'In OutLiner Windows, Show hierarchy'],
|
||||
['PgUp', 'Edit Mode and Proportionnal Editing Tools, increase influence'],
|
||||
['PgUp', 'Strip Editor, Move Down'],
|
||||
['PgUn', 'TimeLine: Jump to next marker'],
|
||||
['PgUp', 'IPO: Select next keyframe'],
|
||||
['Ctrl-PgUp', 'IPO: Select and jump to next keyframe'],
|
||||
['Ctrl-PgUn', 'TimeLine: Jump to next key'],
|
||||
['PgDn', 'Edit Mode and Proportionnal Editing Tools, decrease influence'],
|
||||
['PgDn', 'Strip Editor, Move Up'],
|
||||
['PgDn', 'TimeLine: Jump to prev marker'],
|
||||
['PgDn', 'IPO: Select previous keyframe'],
|
||||
['Ctrl-PgDn', 'IPO: Select and jump to previous keyframe'],
|
||||
['Ctrl-PgDn', 'TimeLine: Jump to prev key'],
|
||||
['Left', 'One frame backwards'],
|
||||
['Right', 'One frame forwards'],
|
||||
['Down', '10 frames backwards'],
|
||||
@ -191,7 +212,9 @@ hotkeys={
|
||||
['Shift-Arrow', 'Toggle first frame/ last frame']
|
||||
],
|
||||
|
||||
'Letters ':[ {"A":[
|
||||
'Letters ':[
|
||||
{
|
||||
"A":[
|
||||
['A', 'Select all/Deselect all'],
|
||||
['Alt-A', 'Play animation in current window'],
|
||||
['Ctrl-A', 'Apply objects size/rotation to object data'],
|
||||
@ -199,7 +222,8 @@ hotkeys={
|
||||
['Shift-A', 'Sequencer: Add menu'],
|
||||
['Shift-A', '3D-View: Add menu'],
|
||||
['Shift-ALT-A', 'Play animation in all windows'],
|
||||
['Shift-CTRL-A', 'Apply lattice / Make dupliverts real']
|
||||
['Shift-CTRL-A', 'Apply lattice / Make dupliverts real'],
|
||||
['Shift-CTRL-A', 'Apply Deform ']
|
||||
],
|
||||
|
||||
"B":[
|
||||
@ -214,6 +238,7 @@ hotkeys={
|
||||
['C', 'UV Image Editor: Active Face Select toggle'],
|
||||
['C', 'Sequencer: Change images'],
|
||||
['C', 'IPO: Snap current frame to selected key'],
|
||||
['C', 'TimeLine: Center View'],
|
||||
['Alt-C', 'Object Mode: Convert menu'],
|
||||
['Alt-C', 'Text Editor: Copy selection to clipboard'],
|
||||
['Ctrl-C', 'Copy menu (Copy properties of active to selected objects)'],
|
||||
@ -232,6 +257,7 @@ hotkeys={
|
||||
"E":[
|
||||
['E', 'Edit Mode: Extrude'],
|
||||
['E', 'UV Image Editor: LSCM Unwrap'],
|
||||
['E', 'TimeLine: Set End'],
|
||||
['ER', 'Edit Mode: Extrude Rotate'],
|
||||
['ES', 'Edit Mode: Extrude Scale'],
|
||||
['ESX', 'Edit Mode: Extrude Scale X axis'],
|
||||
@ -267,10 +293,13 @@ hotkeys={
|
||||
"H":[
|
||||
['H', 'Hide selected vertices/faces'],
|
||||
['H', 'Curves: Set handle type'],
|
||||
['H', 'Action editor: Handle type aligned'],
|
||||
['H', 'Action editor: Handle type free'],
|
||||
['Alt-H', 'Show Hidden vertices/faces'],
|
||||
['Ctrl-H', 'Curves: Automatic handle calculation'],
|
||||
['Shift-H', 'Hide deselected vertices/faces'],
|
||||
['Shift-H', 'Curves: Set handle type']
|
||||
['Shift-H', 'Curves: Automatic handle calculation'],
|
||||
['Shift-H', 'Action editor: Handle type auto'],
|
||||
['Shift-H', 'Edit Mode, Hide deselected vertices/faces'],
|
||||
['Ctrl-H', 'Edit Mode, Add a hook on selected points or show the hook menu .']
|
||||
],
|
||||
|
||||
"I":[
|
||||
@ -279,12 +308,11 @@ hotkeys={
|
||||
|
||||
"J":[
|
||||
['J', 'IPO: Join menu'],
|
||||
['J', 'Mesh: Join all adjacent triangles to quads'],
|
||||
['J', 'Mesh: Join all adjacent triangles to quads'],
|
||||
['J', 'Render Window: Swap render buffer'],
|
||||
['Ctrl-J', 'Join selected objects'],
|
||||
['Ctrl-J', 'Nurbs: Add segment'],
|
||||
['Ctrl-J', 'IPO: Join keyframes menu'],
|
||||
['Alt-J', 'Edit Mode: convert quads to triangles']
|
||||
],
|
||||
|
||||
"K":[
|
||||
@ -304,7 +332,7 @@ hotkeys={
|
||||
['L', 'Edit mode: Select linked vertices (near mouse pointer)'],
|
||||
['L', 'OOPS window: Select linked objects'],
|
||||
['L', 'UV Face Select: Select linked faces'],
|
||||
['Ctrl-L', 'Make links menu'],
|
||||
['Ctrl-L', 'Make links menu (for instance : to scene...)'],
|
||||
['Shift-L', 'Select links menu']
|
||||
],
|
||||
|
||||
@ -312,8 +340,12 @@ hotkeys={
|
||||
['M', 'Move object to different layer'],
|
||||
['M', 'Sequencer: Make meta strip (group) from selected strips'],
|
||||
['M', 'Edit Mode: Mirros Axis menu'],
|
||||
['M', 'Video Sequence Editor : Make Meta strip...'],
|
||||
['M', 'TimeLine: Add marker'],
|
||||
['Alt-M', 'Edit Mode: Merge vertices menu'],
|
||||
['Ctrl-M', 'Object Mode: Mirros Axis menu']
|
||||
['Alt-M', 'Video Sequence Editor : Separate Meta strip...'],
|
||||
['Ctrl-M', 'Object Mode: Mirros Axis menu'],
|
||||
['Ctrl-M', 'TimeLine: Name marker']
|
||||
],
|
||||
|
||||
"N":[
|
||||
@ -360,6 +392,7 @@ hotkeys={
|
||||
|
||||
"S":[
|
||||
['S', 'Scale'] ,
|
||||
['S', 'TimeLine: Set Start'],
|
||||
['SX', 'Flip around X axis'] ,
|
||||
['SY', 'Flip around Y axis'] ,
|
||||
['SZ', 'Flip around Z axis'] ,
|
||||
@ -376,14 +409,15 @@ hotkeys={
|
||||
['T', 'Adjust texture space'] ,
|
||||
['T', 'Edit mode: Flip 3d curve'] ,
|
||||
['T', 'IPO: Change IPO type'] ,
|
||||
['T', 'TimeLine: Show second'],
|
||||
['Alt-T', 'Clear tracking of object'] ,
|
||||
['Ctrl-T', 'Make selected object track active object'] ,
|
||||
['Ctrl-T', 'Edit Mode: Convert to triangles'] ,
|
||||
['Ctrl-ALT-T', 'Benchmark'] ],
|
||||
|
||||
"U":[
|
||||
['U', 'Make single user menu'] ,
|
||||
['U', '3D View: Global undo'] ,
|
||||
['U', 'Make single user menu (for import completly linked object to another scene for instance) '] ,
|
||||
['U', '3D View: Make Single user Menu'] ,
|
||||
['U', 'Edit Mode: Reload object data from before entering Edit Mode'] ,
|
||||
['U', 'UV Face Select: Automatic UV calculation menu'] ,
|
||||
['U', 'Vertex-/Weightpaint mode: Undo'] ,
|
||||
@ -395,9 +429,11 @@ hotkeys={
|
||||
['V', 'Curves/Nurbs: Vector handle'],
|
||||
['V', 'Vertexpaint mode'],
|
||||
['V', 'UV Image Editor: Stitch UVs'],
|
||||
['V', 'Action editor: Vector'],
|
||||
['Alt-V', "Scale object to match image texture's aspect ratio"],
|
||||
['Shift-V', 'Edit mode: Align view to selected vertices'],
|
||||
['Shift-V', 'UV Image Editor: Limited Stitch UVs popup'],
|
||||
|
||||
],
|
||||
|
||||
"W":[
|
||||
@ -408,11 +444,16 @@ hotkeys={
|
||||
['WY', 'UV Image Editor: Weld/Align Y axis'],
|
||||
['Ctrl-W', 'Save current file'] ,
|
||||
['Ctrl-W', 'Nurbs: Switch direction'] ,
|
||||
['Shift-W', 'Warp/bend selected vertices around cursor'] ],
|
||||
['Shift-W', 'Warp/bend selected vertices around cursor'],
|
||||
['alt-W', 'Export in videoscape format']
|
||||
],
|
||||
|
||||
"X":[
|
||||
['X', 'Delete menu'] ,
|
||||
['Ctrl-X', 'Restore default state (Erase all)'] ],
|
||||
['X', 'TimeLine: Remove marker'],
|
||||
['Ctrl-X', 'Restore default state (Erase all)']
|
||||
|
||||
],
|
||||
|
||||
"Y":[
|
||||
['Y', 'Mesh: Split selected vertices/faces from the rest'] ],
|
||||
@ -429,6 +470,12 @@ hotkeys={
|
||||
up=128
|
||||
down=129
|
||||
UP=0
|
||||
SEARCH=131
|
||||
OLDSEARCHLINE=''
|
||||
SEARCHLINE=Create('')
|
||||
LINE=130
|
||||
FINDED=[]
|
||||
LEN=0
|
||||
|
||||
for k in hotkeys.keys():
|
||||
hotkeys[k].append(Create(0))
|
||||
@ -442,6 +489,24 @@ hotL.sort()
|
||||
hot=hotkeys.keys()
|
||||
hot.sort()
|
||||
|
||||
def searchfor(SEARCHLINE):
|
||||
global hotkeys, hot
|
||||
FINDLIST=[]
|
||||
for k in hot:
|
||||
if k not in ['Letters ', 'Search '] :
|
||||
for l in hotkeys[k][:-1]:
|
||||
#print 'k, l : ', k, l, l[1]
|
||||
if l[1].upper().find(SEARCHLINE.upper())!=-1:
|
||||
FINDLIST.append(l)
|
||||
elif k == 'Letters ':
|
||||
for l in hotL :
|
||||
for l0 in hotkeys['Letters '][0][l][:-1]:
|
||||
#print 'k, l : ',l, k, l0
|
||||
if l0[1].upper().find(SEARCHLINE.upper())!=-1:
|
||||
FINDLIST.append(l0)
|
||||
return FINDLIST
|
||||
|
||||
|
||||
glCr=glRasterPos2d
|
||||
glCl3=glColor3f
|
||||
glCl4=glColor4f
|
||||
@ -462,8 +527,8 @@ def trace_rectangle3(r,c,c1):
|
||||
glCl3(c1[0],c1[1],c1[2])
|
||||
|
||||
def draw():
|
||||
global r,c,c1,hotkeys, hot, hotL, up, down, UP
|
||||
|
||||
global r,c,c1,hotkeys, hot, hotL, up, down, UP, SEARCH, SEARCHLINE,LINE
|
||||
global OLDSEARCHLINE, FINDED, SCROLL, LEN
|
||||
size=Buffer(GL_FLOAT, 4)
|
||||
glGetFloatv(GL_SCISSOR_BOX, size)
|
||||
size= size.list
|
||||
@ -490,7 +555,7 @@ def draw():
|
||||
glRasterPos2f(42, size[3]-25)
|
||||
|
||||
Text("HotKey and MouseAction Reference")
|
||||
|
||||
|
||||
l=0
|
||||
listed=0
|
||||
Llisted=0
|
||||
@ -499,14 +564,12 @@ def draw():
|
||||
for k in hot:
|
||||
#hotkeys[k][-1]=Toggle(k, hot.index(k)+10, 4+(20*26)/6*hot.index(k), size[3]-(42), len(k)*8, 20, hotkeys[k][-1].val )
|
||||
hotkeys[k][-1]=Toggle(k, hot.index(k)+10, 78*hot.index(k), size[3]-(47), 78, 24, hotkeys[k][-1].val )
|
||||
|
||||
l+=len(k)
|
||||
|
||||
if hotkeys[k][-1].val==1.0:
|
||||
listed=hot.index(k)
|
||||
l=0
|
||||
size[3]=size[3]-4
|
||||
if hot[listed]!='Letters ':
|
||||
if hot[listed]!='Letters ' and hot[listed]!='Search ' :
|
||||
size[3]=size[3]-8
|
||||
SCROLL=size[3]/21
|
||||
END=-1
|
||||
@ -520,9 +583,7 @@ def draw():
|
||||
UP=len(hotkeys[hot[listed]][:-1])-SCROLL
|
||||
else :
|
||||
UP=0
|
||||
|
||||
for n in hotkeys[hot[listed]][:-1][UP:END]:
|
||||
|
||||
if l%2==0:
|
||||
r=[0,size[3]-(21*l+66),
|
||||
size[2], size[3]-(21*l+43)]
|
||||
@ -533,20 +594,50 @@ def draw():
|
||||
glRasterPos2f(4+8*15, size[3]-(58+21*l))
|
||||
Text(' : '+n[1])
|
||||
l+=1
|
||||
elif hot[listed]=='Search ' :
|
||||
r=[0,size[3]-70,
|
||||
size[2], size[3]-44]
|
||||
trace_rectangle4(r,c2)
|
||||
SEARCHLINE=String(' ', LINE, 42, size[3]-68,200,18,SEARCHLINE.val, 256,'')
|
||||
if len(FINDED)>0:
|
||||
LEN=len(FINDED)
|
||||
size[3]=size[3]-8
|
||||
SCROLL=size[3]/21
|
||||
END=-1
|
||||
if SCROLL < len(FINDED):
|
||||
Button('/\\',up,4,size[3]+8,20,14,'Scroll up')
|
||||
Button('\\/',down,4,size[3]-8,20,14,'Scroll down')
|
||||
if (SCROLL+UP)<len(FINDED):
|
||||
END=(UP+SCROLL-1)
|
||||
else:
|
||||
END=-1
|
||||
#UP=len(FINDED)-SCROLL
|
||||
else:
|
||||
UP=0
|
||||
for n in FINDED[UP:END]:
|
||||
if l%2==0:
|
||||
r=[0,size[3]-(21*l+66+24),
|
||||
size[2], size[3]-(21*l+43+24)]
|
||||
trace_rectangle4(r,c2)
|
||||
glColor3f(0,0,0)
|
||||
glRasterPos2f(4+8, size[3]-(58+24+21*l))
|
||||
Text(n[0])
|
||||
glRasterPos2f(4+8*15, size[3]-(58+24+21*l))
|
||||
Text(' : '+n[1])
|
||||
l+=1
|
||||
else:
|
||||
for k in hotL:
|
||||
pos=hotL.index(k)
|
||||
hotkeys['Letters '][0][k][-1]=Toggle(k,pos+20,hotL.index(k)*21, size[3]-(52+18), 21, 18, hotkeys['Letters '][0][k][-1].val )
|
||||
if hotkeys['Letters '][0][k][-1].val==1.0:
|
||||
Llisted=pos
|
||||
|
||||
size[3]=size[3]-8
|
||||
|
||||
SCROLL=(size[3]-88)/21
|
||||
END=-1
|
||||
if SCROLL < len(hotkeys['Letters '][0][hotL[Llisted]]):
|
||||
Button('/\\',up,4,size[3]+8,20,14,'Scroll up')
|
||||
Button('\\/',down,4,size[3]-8,20,14,'Scroll down')
|
||||
LEN=len(hotkeys['Letters '][0][hotL[Llisted]])
|
||||
Button('/\\',up,4,size[3]+8,20,14,'Scroll up, you can use arrow or page keys too ')
|
||||
Button('\\/',down,4,size[3]-8,20,14,'Scroll down, you can use arrow or page keys too ')
|
||||
if (UP+SCROLL)<len(hotkeys['Letters '][0][hotL[Llisted]]):
|
||||
END=(UP+SCROLL)
|
||||
else:
|
||||
@ -569,13 +660,27 @@ def draw():
|
||||
l+=1
|
||||
|
||||
def event(evt, val):
|
||||
global hotkeys, UP
|
||||
if ((evt== QKEY or evt== ESCKEY) and not val):
|
||||
global hotkeys, UP, SCROLL , LEN
|
||||
if (evt== QKEY or evt== ESCKEY):
|
||||
Exit()
|
||||
|
||||
elif val:
|
||||
if (evt== PAGEUPKEY):
|
||||
if (UP+SCROLL)<LEN-5:
|
||||
UP+=5
|
||||
elif (evt== PAGEDOWNKEY):
|
||||
if UP>4:
|
||||
UP-=5
|
||||
elif (evt== UPARROWKEY):
|
||||
if (UP+SCROLL)<LEN-1:
|
||||
UP+=1
|
||||
elif (evt== DOWNARROWKEY):
|
||||
if UP>0:
|
||||
UP-=1
|
||||
Redraw()
|
||||
|
||||
def bevent(evt):
|
||||
global hotkeysmhot, hotL, up,down,UP
|
||||
global hotkeysmhot, hotL, up,down,UP, FINDED
|
||||
global SEARCH, SEARCHLINE,LINE, OLDSEARCHLINE
|
||||
|
||||
if (evt== 1):
|
||||
Exit()
|
||||
@ -602,4 +707,11 @@ def bevent(evt):
|
||||
if UP>0: UP-=1
|
||||
Blender.Window.Redraw()
|
||||
|
||||
elif (evt==LINE):
|
||||
if SEARCHLINE.val!='' and SEARCHLINE.val!=OLDSEARCHLINE:
|
||||
OLDSEARCHLINE=SEARCHLINE.val
|
||||
FINDED=searchfor(OLDSEARCHLINE)
|
||||
Blender.Window.Redraw()
|
||||
|
||||
|
||||
Register(draw, event, bevent)
|
||||
|
@ -26,7 +26,7 @@ Usage:<br>
|
||||
Supported:<br>
|
||||
UV Coordinates, Meshes, Materials, Material Indices, Specular
|
||||
Highlights, and Vertex Colors. For added functionality, each object is
|
||||
placed on its own layer.
|
||||
placed on its own layer. Someone added the CLIP chunk and imagename support.
|
||||
|
||||
Missing:<br>
|
||||
Not too much, I hope! :).
|
||||
@ -95,6 +95,7 @@ def write(filename):
|
||||
bbox = generate_bbox(mesh)
|
||||
pols = generate_pols(mesh)
|
||||
ptag = generate_ptag(mesh, material_names)
|
||||
clip = generate_clip(mesh, material_names)
|
||||
|
||||
if mesh.hasFaceUV():
|
||||
vmad_uv = generate_vmad_uv(mesh) # per face
|
||||
@ -111,10 +112,6 @@ def write(filename):
|
||||
write_chunk(meshdata, "POLS", pols); chunks.append(pols)
|
||||
write_chunk(meshdata, "PTAG", ptag); chunks.append(ptag)
|
||||
|
||||
if mesh.hasFaceUV():
|
||||
write_chunk(meshdata, "VMAD", vmad_uv)
|
||||
chunks.append(vmad_uv)
|
||||
|
||||
if meshtools.has_vertex_colors(mesh):
|
||||
if meshtools.average_vcols:
|
||||
write_chunk(meshdata, "VMAP", vmap_vc)
|
||||
@ -122,6 +119,13 @@ def write(filename):
|
||||
else:
|
||||
write_chunk(meshdata, "VMAD", vmad_vc)
|
||||
chunks.append(vmad_vc)
|
||||
|
||||
if mesh.hasFaceUV():
|
||||
write_chunk(meshdata, "VMAD", vmad_uv)
|
||||
chunks.append(vmad_uv)
|
||||
write_chunk(meshdata, "CLIP", clip)
|
||||
chunks.append(clip)
|
||||
|
||||
layer_index += 1
|
||||
|
||||
for surf in surfs:
|
||||
@ -135,6 +139,7 @@ def write(filename):
|
||||
file.write(meshdata.getvalue()); meshdata.close()
|
||||
for surf in surfs:
|
||||
write_chunk(file, "SURF", surf)
|
||||
write_chunk(file, "DATE", "August 19, 2005")
|
||||
|
||||
Blender.Window.DrawProgressBar(1.0, "") # clear progressbar
|
||||
file.close()
|
||||
@ -456,6 +461,46 @@ def generate_surf(material_name):
|
||||
comment = generate_nstring(comment)
|
||||
data.write(struct.pack(">H", len(comment)))
|
||||
data.write(comment)
|
||||
|
||||
# Check if the material contains any image maps
|
||||
mtextures = material.getTextures() # Get a list of textures linked to the material
|
||||
for mtex in mtextures:
|
||||
if (mtex) and (mtex.tex.type == Blender.Texture.Types.IMAGE): # Check if the texture is of type "IMAGE"
|
||||
data.write("BLOK") # Surface BLOK header
|
||||
data.write(struct.pack(">H", 104)) # Hardcoded and ugly! Will only handle 1 image per material
|
||||
|
||||
# IMAP subchunk (image map sub header)
|
||||
data.write("IMAP")
|
||||
data_tmp = cStringIO.StringIO()
|
||||
data_tmp.write(struct.pack(">H", 0)) # Hardcoded - not sure what it represents
|
||||
data_tmp.write("CHAN")
|
||||
data_tmp.write(struct.pack(">H", 4))
|
||||
data_tmp.write("COLR")
|
||||
data_tmp.write("OPAC") # Hardcoded texture layer opacity
|
||||
data_tmp.write(struct.pack(">H", 8))
|
||||
data_tmp.write(struct.pack(">H", 0))
|
||||
data_tmp.write(struct.pack(">f", 1.0))
|
||||
data_tmp.write(struct.pack(">H", 0))
|
||||
data_tmp.write("ENAB")
|
||||
data_tmp.write(struct.pack(">HH", 2, 1)) # 1 = texture layer enabled
|
||||
data_tmp.write("NEGA")
|
||||
data_tmp.write(struct.pack(">HH", 2, 0)) # Disable negative image (1 = invert RGB values)
|
||||
data_tmp.write("AXIS")
|
||||
data_tmp.write(struct.pack(">HH", 2, 1))
|
||||
data.write(struct.pack(">H", len(data_tmp.getvalue())))
|
||||
data.write(data_tmp.getvalue())
|
||||
|
||||
# IMAG subchunk
|
||||
data.write("IMAG")
|
||||
data.write(struct.pack(">HH", 2, 1))
|
||||
data.write("PROJ")
|
||||
data.write(struct.pack(">HH", 2, 5)) # UV projection
|
||||
|
||||
data.write("VMAP")
|
||||
uvname = generate_nstring("Blender's UV Coordinates")
|
||||
data.write(struct.pack(">H", len(uvname)))
|
||||
data.write(uvname)
|
||||
|
||||
return data.getvalue()
|
||||
|
||||
# =============================================
|
||||
@ -536,6 +581,27 @@ def generate_icon():
|
||||
#print len(icon_data)
|
||||
return data.getvalue()
|
||||
|
||||
# ===============================================
|
||||
# === Generate CLIP chunk with STIL subchunks ===
|
||||
# ===============================================
|
||||
def generate_clip(mesh, material_names):
|
||||
data = cStringIO.StringIO()
|
||||
clipid = 1
|
||||
for i in range(len(mesh.materials)): # Run through list of materials used by mesh
|
||||
material = Blender.Material.Get(mesh.materials[i].name)
|
||||
mtextures = material.getTextures() # Get a list of textures linked to the material
|
||||
for mtex in mtextures:
|
||||
if (mtex) and (mtex.tex.type == Blender.Texture.Types.IMAGE): # Check if the texture is of type "IMAGE"
|
||||
pathname = mtex.tex.image.filename # If full path is needed use filename in place of name
|
||||
pathname = pathname[0:2] + pathname.replace("\\", "/")[3:] # Convert to Modo standard path
|
||||
imagename = generate_nstring(pathname)
|
||||
data.write(struct.pack(">L", clipid)) # CLIP sequence/id
|
||||
data.write("STIL") # STIL image
|
||||
data.write(struct.pack(">H", len(imagename))) # Size of image name
|
||||
data.write(imagename)
|
||||
clipid += 1
|
||||
return data.getvalue()
|
||||
|
||||
# ===================
|
||||
# === Write Chunk ===
|
||||
# ===================
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -9,7 +9,7 @@ Tooltip: 'Save a Wavefront OBJ File'
|
||||
|
||||
__author__ = "Campbell Barton, Jiri Hnidek"
|
||||
__url__ = ["blender", "elysiun"]
|
||||
__version__ = "0.9"
|
||||
__version__ = "1.0"
|
||||
|
||||
__bpydoc__ = """\
|
||||
This script is an exporter to OBJ file format.
|
||||
@ -49,134 +49,287 @@ def newFName(ext):
|
||||
return Get('filename')[: -len(Get('filename').split('.', -1)[-1]) ] + ext
|
||||
|
||||
|
||||
def fixName(name):
|
||||
if name == None:
|
||||
return 'None'
|
||||
else:
|
||||
return name.replace(' ', '_')
|
||||
|
||||
|
||||
|
||||
|
||||
from Blender import *
|
||||
|
||||
NULL_MAT = '(null)'
|
||||
NULL_IMG = '(null)' # from docs at http://astronomy.swin.edu.au/~pbourke/geomformats/obj/ also could be 'off'
|
||||
global MTL_DICT
|
||||
|
||||
# A Dict of Materials
|
||||
# (material.name, image.name):matname_imagename # matname_imagename has gaps removed.
|
||||
MTL_DICT = {}
|
||||
|
||||
def save_mtl(filename):
|
||||
global MTL_DICT
|
||||
|
||||
world = World.GetCurrent()
|
||||
if world:
|
||||
worldAmb = world.getAmb()
|
||||
else:
|
||||
worldAmb = (0,0,0) # Default value
|
||||
|
||||
file = open(filename, "w")
|
||||
file.write('# Blender MTL File: %s\n' % (Get('filename')))
|
||||
for mat in Material.Get():
|
||||
file.write('newmtl %s\n' % (mat.getName())) # Define a new material
|
||||
file.write('Ns %s\n' % ((mat.getHardness()-1) * 1.9607843137254901 ) ) # Hardness, convert blenders 1-511 to MTL's
|
||||
file.write('Kd %.6f %.6f %.6f\n' % tuple(mat.getRGBCol())) # Diffuse
|
||||
file.write('Ka %.6f %.6f %.6f\n' % tuple(mat.getMirCol())) # Ambient, uses mirror colour,
|
||||
file.write('Ks %.6f %.6f %.6f\n' % tuple(mat.getSpecCol())) # Specular
|
||||
file.write('Ni %.6f\n' % mat.getIOR()) # Refraction index
|
||||
file.write('d %.6f\n' % mat.getAlpha()) # Alpha (obj uses 'd' for dissolve)
|
||||
file.write('# Blender MTL File: %s\n' % Get('filename').split('\\')[-1].split('/')[-1])
|
||||
file.write('# Material Count: %i\n' % len(MTL_DICT))
|
||||
# Write material/image combinations we have used.
|
||||
for key, mtl_mat_name in MTL_DICT.iteritems():
|
||||
|
||||
# illum, 0 to disable lightng, 2 is normal.
|
||||
if mat.getMode() & Material.Modes['SHADELESS']:
|
||||
file.write('illum 0\n\n') # ignore lighting
|
||||
# Get the Blender data for the material and the image.
|
||||
# Having an image named None will make a bug, dont do it :)
|
||||
|
||||
file.write('newmtl %s\n' % mtl_mat_name) # Define a new material: matname_imgname
|
||||
|
||||
if key[0] == None:
|
||||
#write a dummy material here?
|
||||
file.write('Ns 0\n')
|
||||
file.write('Ka %s %s %s\n' % tuple([round(c, 6) for c in worldAmb]) ) # Ambient, uses mirror colour,
|
||||
file.write('Kd 0.8 0.8 0.8\n')
|
||||
file.write('Ks 0.8 0.8 0.8\n')
|
||||
file.write('d 1\n') # No alpha
|
||||
file.write('illum 2\n') # light normaly
|
||||
|
||||
else:
|
||||
file.write('illum 2\n\n') # light normaly
|
||||
mat = Material.Get(key[0])
|
||||
file.write('Ns %s\n' % round((mat.getHardness()-1) * 1.9607843137254901 ) ) # Hardness, convert blenders 1-511 to MTL's
|
||||
file.write('Ka %s %s %s\n' % tuple([round(c*mat.getAmb(), 6) for c in worldAmb]) ) # Ambient, uses mirror colour,
|
||||
file.write('Kd %s %s %s\n' % tuple([round(c*mat.getRef(), 6) for c in mat.getRGBCol()]) ) # Diffuse
|
||||
file.write('Ks %s %s %s\n' % tuple([round(c*mat.getSpec(), 6) for c in mat.getSpecCol()]) ) # Specular
|
||||
file.write('Ni %s\n' % round(mat.getIOR(), 6)) # Refraction index
|
||||
file.write('d %s\n' % round(mat.getAlpha(), 6)) # Alpha (obj uses 'd' for dissolve)
|
||||
|
||||
# 0 to disable lighting, 1 for ambient & diffuse only (specular color set to black), 2 for full lighting.
|
||||
if mat.getMode() & Material.Modes['SHADELESS']:
|
||||
file.write('illum 0\n') # ignore lighting
|
||||
elif mat.getSpec() == 0:
|
||||
file.write('illum 1\n') # no specular.
|
||||
else:
|
||||
file.write('illum 2\n') # light normaly
|
||||
|
||||
|
||||
# Write images!
|
||||
if key[1] != None: # We have an image on the face!
|
||||
img = Image.Get(key[1])
|
||||
file.write('map_Kd %s\n' % img.filename.split('\\')[-1].split('/')[-1]) # Diffuse mapping image
|
||||
|
||||
elif key[0] != None: # No face image. if we havea material search for MTex image.
|
||||
for mtex in mat.getTextures():
|
||||
if mtex and mtex.tex.type == Texture.Types.IMAGE:
|
||||
try:
|
||||
filename = mtex.tex.image.filename.split('\\')[-1].split('/')[-1]
|
||||
file.write('map_Kd %s\n' % filename) # Diffuse mapping image
|
||||
break
|
||||
except:
|
||||
# Texture has no image though its an image type, best ignore.
|
||||
pass
|
||||
|
||||
file.write('\n\n')
|
||||
|
||||
file.close()
|
||||
|
||||
|
||||
|
||||
def save_obj(filename):
|
||||
global MTL_DICT
|
||||
|
||||
time1 = sys.time()
|
||||
scn = Scene.GetCurrent()
|
||||
# First output all material
|
||||
mtlfilename = '%s.mtl' % '.'.join(filename.split('.')[:-1])
|
||||
save_mtl(mtlfilename)
|
||||
|
||||
file = open(filename, "w")
|
||||
|
||||
# Write Header
|
||||
file.write('# Blender OBJ File: %s\n' % (Get('filename')))
|
||||
file.write('# Blender OBJ File: %s\n' % (Get('filename').split('/')[-1].split('\\')[-1] ))
|
||||
file.write('# www.blender.org\n')
|
||||
|
||||
# Tell the obj file what material file to use.
|
||||
mtlfilename = '%s.mtl' % '.'.join(filename.split('.')[:-1])
|
||||
file.write('mtllib %s\n' % ( mtlfilename.split('\\')[-1].split('/')[-1] ))
|
||||
|
||||
# Initialize totals, these are updated each object
|
||||
totverts = totuvco = 0
|
||||
totverts = totuvco = totno = 1
|
||||
|
||||
globalUVCoords = {}
|
||||
globalNormals = {}
|
||||
|
||||
# Get all meshs
|
||||
for ob in scn.getChildren():
|
||||
if ob.getType() != 'Mesh':
|
||||
#for ob in Object.GetSelected():
|
||||
try:
|
||||
# Will work for non meshes now! :)
|
||||
m = NMesh.GetRawFromObject(ob.name)
|
||||
except:
|
||||
continue
|
||||
m = NMesh.GetRawFromObject(ob.name)
|
||||
m.transform(ob.matrix)
|
||||
|
||||
if not m.faces: # Make sure there is somthing to write
|
||||
continue #dont bother with this mesh.
|
||||
|
||||
faces = [ f for f in m.faces if len(f) > 2 ]
|
||||
materials = m.materials
|
||||
|
||||
# Sort by Material so we dont over context switch in the obj file.
|
||||
if len(materials) > 1:
|
||||
faces.sort(lambda a,b: cmp(a.mat, b.mat))
|
||||
if not faces: # Make sure there is somthing to write
|
||||
continue # dont bother with this mesh.
|
||||
|
||||
# Set the default mat
|
||||
currentMatName = NULL_MAT
|
||||
currentImgName = NULL_IMG
|
||||
m.transform(ob.matrix)
|
||||
|
||||
file.write('o %s_%s\n' % (ob.getName(), m.name)) # Write Object name
|
||||
# # Crash Blender
|
||||
#materials = m.getMaterials(1) # 1 == will return None in the list.
|
||||
materials = m.getMaterials()
|
||||
|
||||
|
||||
if materials:
|
||||
materialNames = map(lambda mat: mat.name, materials) # Bug Blender, dosent account for null materials, still broken.
|
||||
else:
|
||||
materialNames = []
|
||||
|
||||
# Possible there null materials, will mess up indicies
|
||||
# but at least it will export, wait until Blender gets fixed.
|
||||
materialNames.extend((16-len(materialNames)) * [None])
|
||||
|
||||
|
||||
# Sort by Material, then images
|
||||
# so we dont over context switch in the obj file.
|
||||
faces.sort(lambda a,b: cmp((a.mat, a.image, a.smooth), (b.mat, b.image, b.smooth)))
|
||||
|
||||
|
||||
# Set the default mat to no material and no image.
|
||||
contextMat = (0, 0) # Can never be this, so we will label a new material teh first chance we get.
|
||||
contextSmooth = None # Will either be true or false, set bad to force initialization switch.
|
||||
|
||||
file.write('o %s_%s\n' % (fixName(ob.name), fixName(m.name))) # Write Object name
|
||||
|
||||
# Vert
|
||||
for v in m.verts:
|
||||
file.write('v %.6f %.6f %.6f\n' % tuple(v.co))
|
||||
|
||||
|
||||
# UV
|
||||
if m.hasFaceUV():
|
||||
for f in faces:
|
||||
for uv in f.uv:
|
||||
uvKey = '%.6f %.6f' % uv
|
||||
try:
|
||||
dummy = globalUVCoords[uvKey]
|
||||
except KeyError:
|
||||
totuvco +=1 # 1 based index.
|
||||
for uvKey in f.uv:
|
||||
if not globalUVCoords.has_key(uvKey):
|
||||
globalUVCoords[uvKey] = totuvco
|
||||
file.write('vt %s 0.0\n' % uvKey)
|
||||
|
||||
# NORMAL
|
||||
for v in m.verts:
|
||||
file.write('vn %.6f %.6f %.6f\n' % tuple(v.no))
|
||||
totuvco +=1
|
||||
file.write('vt %.6f %.6f 0.0\n' % uvKey)
|
||||
|
||||
# NORMAL, Smooth/Non smoothed.
|
||||
|
||||
for f in faces:
|
||||
if f.smooth:
|
||||
for v in f.v:
|
||||
noKey = tuple(v.no)
|
||||
if not globalNormals.has_key( noKey ):
|
||||
globalNormals[noKey] = totno
|
||||
totno +=1
|
||||
file.write('vn %.6f %.6f %.6f\n' % noKey)
|
||||
else:
|
||||
# Hard, 1 normal from the face.
|
||||
noKey = tuple(f.no)
|
||||
if not globalNormals.has_key( noKey ):
|
||||
globalNormals[noKey] = totno
|
||||
totno +=1
|
||||
file.write('vn %.6f %.6f %.6f\n' % noKey)
|
||||
|
||||
|
||||
uvIdx = 0
|
||||
for f in faces:
|
||||
# Check material and change if needed.
|
||||
if len(materials) > 0:
|
||||
if currentMatName != materials[f.mat].getName():
|
||||
currentMatName = materials[f.mat].getName()
|
||||
file.write('usemtl %s\n' % (currentMatName))
|
||||
|
||||
elif currentMatName != NULL_MAT:
|
||||
currentMatName = NULL_MAT
|
||||
file.write('usemtl %s\n' % (currentMatName))
|
||||
|
||||
# UV IMAGE
|
||||
# If the face uses a different image from the one last set then add a usemap line.
|
||||
if f.image:
|
||||
if f.image.filename != currentImgName:
|
||||
currentImgName = f.image.filename
|
||||
# Set a new image for all following faces
|
||||
file.write( 'usemap %s\n' % currentImgName.split('\\')[-1].split('/')[-1] )
|
||||
# MAKE KEY
|
||||
if f.image: # Object is always true.
|
||||
key = materialNames[f.mat], f.image.name
|
||||
else:
|
||||
key = materialNames[f.mat], None # No image, use None instead.
|
||||
|
||||
# CHECK FOR CONTEXT SWITCH
|
||||
if key == contextMat:
|
||||
pass # Context alredy switched, dont do anythoing
|
||||
elif key[0] == None and key[1] == None:
|
||||
# Write a null material, since we know the context has changed.
|
||||
file.write('usemtl (null)\n') # mat, image
|
||||
|
||||
elif currentImgName != NULL_IMG: # Not using an image so set to NULL_IMG
|
||||
currentImgName = NULL_IMG
|
||||
# Set a ne w image for all following faces
|
||||
file.write( 'usemap %s\n' % currentImgName) # No splitting needed.
|
||||
else:
|
||||
try: # Faster to try then 2x dict lookups.
|
||||
|
||||
# We have the material, just need to write the context switch,
|
||||
file.write('usemtl %s\n' % MTL_DICT[key]) # mat, image
|
||||
|
||||
except KeyError:
|
||||
# First add to global dict so we can export to mtl
|
||||
# Then write mtl
|
||||
|
||||
# Make a new names from the mat and image name,
|
||||
# converting any spaces to underscores with fixName.
|
||||
|
||||
# If none image dont bother adding it to the name
|
||||
if key[1] == None:
|
||||
tmp_matname = MTL_DICT[key] ='%s' % fixName(key[0])
|
||||
file.write('usemtl %s\n' % tmp_matname) # mat, image
|
||||
|
||||
else:
|
||||
tmp_matname = MTL_DICT[key] = '%s_%s' % (fixName(key[0]), fixName(key[1]))
|
||||
file.write('usemtl %s\n' % tmp_matname) # mat, image
|
||||
|
||||
contextMat = key
|
||||
|
||||
if f.smooth != contextSmooth:
|
||||
if f.smooth:
|
||||
file.write('s 1\n')
|
||||
else:
|
||||
file.write('s off\n')
|
||||
contextSmooth = f.smooth
|
||||
|
||||
file.write('f')
|
||||
if m.hasFaceUV():
|
||||
for vi, v in enumerate(f.v):
|
||||
uvIdx = globalUVCoords[ '%.6f %.6f' % f.uv[vi] ]
|
||||
i = v.index + totverts + 1
|
||||
file.write( ' %d/%d/%d' % (i, uvIdx, i)) # vert, uv, normal
|
||||
|
||||
if f.smooth: # Smoothed, use vertex normals
|
||||
for vi, v in enumerate(f.v):
|
||||
file.write( ' %d/%d/%d' % (\
|
||||
v.index+totverts,\
|
||||
globalUVCoords[ f.uv[vi] ],\
|
||||
globalNormals[ tuple(v.no) ])) # vert, uv, normal
|
||||
else: # No smoothing, face normals
|
||||
no = globalNormals[ tuple(f.no) ]
|
||||
for vi, v in enumerate(f.v):
|
||||
file.write( ' %d/%d/%d' % (\
|
||||
v.index+totverts,\
|
||||
globalUVCoords[ f.uv[vi] ],\
|
||||
no)) # vert, uv, normal
|
||||
|
||||
else: # No UV's
|
||||
for v in f.v:
|
||||
file.write( ' %d' % (v.index + totverts+1))
|
||||
if f.smooth: # Smoothed, use vertex normals
|
||||
for v in f.v:
|
||||
file.write( ' %d//%d' % (\
|
||||
v.index+totverts,\
|
||||
globalNormals[ tuple(v.no) ]))
|
||||
else: # No smoothing, face normals
|
||||
no = globalNormals[ tuple(f.no) ]
|
||||
for v in f.v:
|
||||
file.write( ' %d//%d' % (\
|
||||
v.index+totverts,\
|
||||
no))
|
||||
|
||||
file.write('\n')
|
||||
|
||||
# Make the indicies global rather then per mesh
|
||||
totverts += len(m.verts)
|
||||
file.close()
|
||||
|
||||
|
||||
# Now we have all our materials, save them
|
||||
save_mtl(mtlfilename)
|
||||
|
||||
print "obj export time: %.2f" % (sys.time() - time1)
|
||||
|
||||
Window.FileSelector(save_obj, 'Export Wavefront OBJ', newFName('obj'))
|
||||
|
||||
'''
|
||||
TIME = sys.time()
|
||||
import os
|
||||
OBJDIR = '/obj_out/'
|
||||
for scn in Scene.Get():
|
||||
scn.makeCurrent()
|
||||
obj = OBJDIR + scn.name
|
||||
print obj
|
||||
save_obj(obj)
|
||||
|
||||
print "TOTAL EXPORT TIME: ", sys.time() - TIME
|
||||
'''
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,15 +1,15 @@
|
||||
#!BPY
|
||||
|
||||
"""
|
||||
Name: 'Bridge/Skin/Loft'
|
||||
Blender: 234
|
||||
Name: 'Bridge Faces/Edge-Loops'
|
||||
Blender: 237
|
||||
Group: 'Mesh'
|
||||
Tooltip: 'Select 2 or more vert loops, then run this script'
|
||||
Tooltip: 'Select 2 vert loops, then run this script.'
|
||||
"""
|
||||
|
||||
__author__ = "Campbell Barton AKA Ideasman"
|
||||
__url__ = ["http://members.iinet.net.au/~cpbarton/ideasman/", "blender", "elysiun"]
|
||||
__version__ = "1.1 2005/06/13"
|
||||
__version__ = "1.0 2004/04/25"
|
||||
|
||||
__bpydoc__ = """\
|
||||
With this script vertex loops can be skinned: faces are created to connect the
|
||||
@ -19,11 +19,7 @@ Usage:
|
||||
|
||||
In mesh Edit mode select the vertices of the loops (closed paths / curves of
|
||||
vertices: circles, for example) that should be skinned, then run this script.
|
||||
A pop-up will provide further options.
|
||||
|
||||
Notes:
|
||||
|
||||
If the results of a method chosen from the pop-up are not adequate, undo and try one of the others.
|
||||
A pop-up will provide further options, if the results of a method are not adequate try one of the others.
|
||||
"""
|
||||
|
||||
|
||||
@ -51,536 +47,443 @@ If the results of a method chosen from the pop-up are not adequate, undo and try
|
||||
# ***** END GPL LICENCE BLOCK *****
|
||||
# --------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
# Made by Ideasman/Campbell 2004/04/25 - ideasman@linuxmail.org
|
||||
# Made by Ideasman/Campbell 2005/06/15 - ideasman@linuxmail.org
|
||||
|
||||
import Blender
|
||||
from Blender import *
|
||||
import math
|
||||
from math import *
|
||||
|
||||
BIG_NUM = 1<<30
|
||||
|
||||
choice = Draw.PupMenu(\
|
||||
'Loft-loop - shortest edge method|\
|
||||
Loft-loop - even method|\
|
||||
Loft-segment - shortest edge|\
|
||||
Loft-segment - even method')
|
||||
global CULL_METHOD
|
||||
CULL_METHOD = 0
|
||||
|
||||
if choice == 1:
|
||||
arg='A1'
|
||||
elif choice == 2:
|
||||
arg='A2'
|
||||
elif choice == 3:
|
||||
arg='B1'
|
||||
elif choice == 4:
|
||||
arg='B2'
|
||||
|
||||
|
||||
|
||||
#================#
|
||||
# Math functions #
|
||||
#================#
|
||||
|
||||
# Measure 2 points
|
||||
def measure(v1, v2):
|
||||
return Mathutils.Vector([v1[0]-v2[0], v1[1] - v2[1], v1[2] - v2[2]]).length
|
||||
|
||||
# Clamp
|
||||
def clamp(max, number):
|
||||
while number >= max:
|
||||
number = number - max
|
||||
return number
|
||||
|
||||
#=============================================================#
|
||||
# List func that takes the last item and adds it to the front #
|
||||
#=============================================================#
|
||||
def listRotate(ls):
|
||||
ls.append(ls.pop(0))
|
||||
|
||||
#=================================================================#
|
||||
# Recieve a list of locs: [x,y,z] and return the average location #
|
||||
#=================================================================#
|
||||
def averageLocation(locList):
|
||||
avLoc = [0,0,0]
|
||||
|
||||
# Loop through x/y/z
|
||||
for coordIdx in [0,1,2]:
|
||||
class edge:
|
||||
def __init__(self, v1,v2):
|
||||
self.v1 = v1
|
||||
self.v2 = v2
|
||||
|
||||
# Add all the values from 1 of the 3 coords at the avLoc.
|
||||
for loc in locList:
|
||||
avLoc[coordIdx] += loc[coordIdx]
|
||||
# uv1 uv2 vcol1 vcol2 # Add later
|
||||
self.length = (v1.co - v2.co).length
|
||||
|
||||
avLoc[coordIdx] = avLoc[coordIdx] / len(locList)
|
||||
return avLoc
|
||||
self.removed = 0 # Have we been culled from the eloop
|
||||
self.match = None # The other edge were making a face with
|
||||
|
||||
|
||||
|
||||
#=============================#
|
||||
# Blender functions/shortcuts #
|
||||
#=============================#
|
||||
def error(str):
|
||||
Draw.PupMenu('ERROR%t|'+str)
|
||||
|
||||
# Returns a new face that has the same properties as the origional face
|
||||
# With no verts though
|
||||
def copyFace(face):
|
||||
newFace = NMesh.Face()
|
||||
# Copy some generic properties
|
||||
newFace.mode = face.mode
|
||||
if face.image != None:
|
||||
newFace.image = face.image
|
||||
newFace.flag = face.flag
|
||||
newFace.mat = face.mat
|
||||
newFace.smooth = face.smooth
|
||||
return newFace
|
||||
|
||||
#=============================================#
|
||||
# Find a selected vert that 2 faces share. #
|
||||
#=============================================#
|
||||
def selVertBetween2Faces(face1, face2):
|
||||
for v1 in face1.v:
|
||||
if v1.sel:
|
||||
for v2 in face2.v:
|
||||
if v1 == v2:
|
||||
return v1
|
||||
|
||||
|
||||
#=======================================================#
|
||||
# Measure the total distance between all the edges in #
|
||||
# 2 vertex loops #
|
||||
#=======================================================#
|
||||
def measureVloop(mesh, v1loop, v2loop, surplusFaces, bestSoFar):
|
||||
totalDist = 0
|
||||
|
||||
# Rotate the vertloops to cycle through each pair.
|
||||
# of faces to compate the distance between the 2 poins
|
||||
for ii in range(len(v1loop)):
|
||||
if ii not in surplusFaces:
|
||||
# Clamp
|
||||
v2clampii = ii
|
||||
while v2clampii >= len(v2loop):
|
||||
v2clampii -= len(v2loop)
|
||||
print v2clampii
|
||||
|
||||
V1 = selVertBetween2Faces(mesh.faces[v1loop[ii-1]], mesh.faces[v1loop[ii]])
|
||||
V2 = selVertBetween2Faces(mesh.faces[v2loop[v2clampii-1]], mesh.faces[v2loop[v2clampii]])
|
||||
|
||||
totalDist += measure(V1, V2)
|
||||
# Bail out early if not an improvement on previously measured.
|
||||
if bestSoFar != None and totalDist > bestSoFar:
|
||||
return totalDist
|
||||
|
||||
#selVertBetween2Faces(mesh.faces[v2loop[0]], mesh.faces[v2loop[1]])
|
||||
return totalDist
|
||||
|
||||
# Remove the shortest edge from a vert loop
|
||||
def removeSmallestFace(mesh, vloop):
|
||||
bestDistSoFar = None
|
||||
bestFIdxSoFar = None
|
||||
for fIdx in vloop:
|
||||
vSelLs = []
|
||||
for v in mesh.faces[fIdx].v:
|
||||
if v.sel:
|
||||
vSelLs.append(v)
|
||||
class edgeLoop:
|
||||
def __init__(self, loop): # Vert loop
|
||||
# Use next and prev, nextDist, prevDist
|
||||
|
||||
dist = measure(vSelLs[0].co, vSelLs[1].co)
|
||||
# Get Loops centre.
|
||||
self.centre = Mathutils.Vector()
|
||||
f = 1.0/len(loop)
|
||||
for v in loop:
|
||||
self.centre += v.co * f
|
||||
|
||||
if bestDistSoFar == None:
|
||||
bestDistSoFar = dist
|
||||
bestFIdxSoFar = fIdx
|
||||
elif dist < bestDistSoFar:
|
||||
bestDistSoFar = dist
|
||||
bestFIdxSoFar = fIdx
|
||||
|
||||
|
||||
|
||||
# Convert Vert loop to Edges.
|
||||
self.edges = []
|
||||
vIdx = 0
|
||||
while vIdx < len(loop):
|
||||
self.edges.append( edge(loop[vIdx-1], loop[vIdx]) )
|
||||
vIdx += 1
|
||||
|
||||
# Assign linked list
|
||||
for eIdx in range(len(self.edges)-1):
|
||||
self.edges[eIdx].next = self.edges[eIdx+1]
|
||||
self.edges[eIdx].prev = self.edges[eIdx-1]
|
||||
# Now last
|
||||
self.edges[-1].next = self.edges[0]
|
||||
self.edges[-1].prev = self.edges[-2]
|
||||
|
||||
|
||||
|
||||
# GENERATE AN AVERAGE NORMAL FOR THE WHOLE LOOP.
|
||||
self.normal = Mathutils.Vector()
|
||||
for e in self.edges:
|
||||
n = Mathutils.CrossVecs(self.centre-e.v1.co, self.centre-e.v2.co)
|
||||
# Do we realy need tot normalize?
|
||||
n.normalize()
|
||||
self.normal += n
|
||||
self.normal.normalize()
|
||||
|
||||
|
||||
# Generate a normal for each edge.
|
||||
for e in self.edges:
|
||||
|
||||
n1 = e.v1.co
|
||||
n2 = e.v2.co
|
||||
n3 = e.prev.v1.co
|
||||
|
||||
a = n1-n2
|
||||
b = n1-n3
|
||||
normal1 = Mathutils.CrossVecs(a,b)
|
||||
normal1.normalize()
|
||||
|
||||
n1 = e.v2.co
|
||||
n3 = e.next.v2.co
|
||||
n2 = e.v1.co
|
||||
|
||||
a = n1-n2
|
||||
b = n1-n3
|
||||
|
||||
normal2 = Mathutils.CrossVecs(a,b)
|
||||
normal2.normalize()
|
||||
|
||||
# Reuse normal1 var
|
||||
normal1 += normal1 + normal2
|
||||
normal1.normalize()
|
||||
|
||||
e.normal = normal1
|
||||
#print e.normal
|
||||
|
||||
|
||||
|
||||
|
||||
def backup(self):
|
||||
# Keep a backup of the edges
|
||||
self.backupEdges = self.edges[:]
|
||||
|
||||
def restore(self):
|
||||
self.edges = self.backupEdges[:]
|
||||
for e in self.edges:
|
||||
e.removed = 0
|
||||
|
||||
def reverse(self):
|
||||
self.edges.reverse()
|
||||
for e in self.edges:
|
||||
e.normal = -e.normal
|
||||
e.v1, e.v2 = e.v2, e.v1
|
||||
self.normal = -self.normal
|
||||
|
||||
# Return the smallest face index of the vloop that was sent
|
||||
return bestFIdxSoFar
|
||||
# Removes N Smallest edges and backs up
|
||||
def removeSmallest(self, cullNum, otherLoopLen):
|
||||
global CULL_METHOD
|
||||
if CULL_METHOD == 0: # Shortest edge
|
||||
|
||||
eloopCopy = self.edges[:]
|
||||
eloopCopy.sort(lambda e1, e2: cmp(e1.length, e2.length )) # Length sort, smallest first
|
||||
eloopCopy = eloopCopy[:cullNum]
|
||||
for e in eloopCopy:
|
||||
e.removed = 1
|
||||
self.edges.remove( e ) # Remove from own list, still in linked list.
|
||||
|
||||
else: # CULL METHOD is even
|
||||
|
||||
culled = 0
|
||||
|
||||
step = int(otherLoopLen / float(cullNum))
|
||||
|
||||
currentEdge = self.edges[0]
|
||||
while culled < cullNum:
|
||||
|
||||
# Get the shortest face in the next STEP
|
||||
while currentEdge.removed == 1:
|
||||
# Bug here!
|
||||
currentEdge = currentEdge.next
|
||||
smallestEdge = currentEdge
|
||||
|
||||
for i in range(step):
|
||||
currentEdge = currentEdge.next
|
||||
while currentEdge.removed == 1:
|
||||
currentEdge = currentEdge.next
|
||||
if smallestEdge.length > currentEdge.length:
|
||||
smallestEdge = currentEdge
|
||||
|
||||
# In that stepping length we have the smallest edge.remove it
|
||||
smallestEdge.removed = 1
|
||||
self.edges.remove(smallestEdge)
|
||||
|
||||
culled+=1
|
||||
|
||||
|
||||
# Returns face edges.
|
||||
# face must have edge data.
|
||||
def faceEdges(me, f):
|
||||
if len(f) == 3:
|
||||
return [\
|
||||
me.findEdge(f[0], f[1]),\
|
||||
me.findEdge(f[1], f[2]),\
|
||||
me.findEdge(f[2], f[0])\
|
||||
]
|
||||
elif len(f) == 4:
|
||||
return [\
|
||||
me.findEdge(f[0], f[1]),\
|
||||
me.findEdge(f[1], f[2]),\
|
||||
me.findEdge(f[2], f[3]),\
|
||||
me.findEdge(f[3], f[0])\
|
||||
]
|
||||
|
||||
|
||||
#=============================================#
|
||||
# Take 2 vert loops and skin them #
|
||||
#=============================================#
|
||||
def skinVertLoops(mesh, v1loop, v2loop):
|
||||
def getSelectedEdges(me, ob):
|
||||
SEL_FLAG = NMesh.EdgeFlags['SELECT']
|
||||
FGON_FLAG = NMesh.EdgeFlags['FGON']
|
||||
|
||||
edges = [e for e in me.edges if e.flag & SEL_FLAG if (e.flag & FGON_FLAG) == 0 ]
|
||||
|
||||
# Now remove edges that face 2 or more selected faces usoing them
|
||||
edgeFromSelFaces = []
|
||||
for f in me.faces:
|
||||
if len(f) >2 and f.sel:
|
||||
edgeFromSelFaces.extend(faceEdges(me, f))
|
||||
|
||||
# Remove all edges with 2 or more selected faces as uses.
|
||||
for e in edgeFromSelFaces:
|
||||
if edgeFromSelFaces.count(e) > 1:
|
||||
me.removeEdge(e.v1, e.v2)
|
||||
|
||||
# Remove selected faces?
|
||||
fIdx = len(me.faces)
|
||||
while fIdx:
|
||||
fIdx-=1
|
||||
if len(me.faces[fIdx]) > 2:
|
||||
if me.faces[fIdx].sel:
|
||||
me.faces.pop(fIdx)
|
||||
return [e for e in edges if edgeFromSelFaces.count(e) < 2]
|
||||
|
||||
|
||||
#=============================================#
|
||||
# Handle uneven vert loops, this is tricky #
|
||||
#=============================================#
|
||||
# Reorder so v1loop is always the biggest
|
||||
if len(v1loop) < len(v2loop):
|
||||
v1loop, v2loop = v2loop, v1loop
|
||||
|
||||
# Work out if the vert loops are equel or not, if not remove the extra faces from the larger
|
||||
surplusFaces = []
|
||||
tempv1loop = v1loop[:] # strip faces off this one, use it to keep track of which we have taken faces from.
|
||||
if len(v1loop) > len(v2loop):
|
||||
# Like vert loops
|
||||
def getVertLoops(selEdges):
|
||||
mainVertLoops = []
|
||||
while selEdges:
|
||||
e = selEdges.pop()
|
||||
contextVertLoop= [e.v1, e.v2] # start the vert loop
|
||||
|
||||
# Even face method.
|
||||
if arg[1] == '2':
|
||||
remIdx = 0
|
||||
faceStepping = len( v1loop) / len(v2loop)
|
||||
while len(v1loop) - len(surplusFaces) > len(v2loop):
|
||||
remIdx += faceStepping
|
||||
surplusFaces.append(tempv1loop[ clamp(len(tempv1loop),remIdx) ])
|
||||
tempv1loop.remove(surplusFaces[-1])
|
||||
eIdx = 1 # Get us into the loop. dummy var.
|
||||
|
||||
# Shortest face
|
||||
elif arg[1] == '1':
|
||||
while len(v1loop) - len(surplusFaces) > len(v2loop):
|
||||
surplusFaces.append(removeSmallestFace(mesh, tempv1loop))
|
||||
tempv1loop.remove(surplusFaces[-1])
|
||||
|
||||
|
||||
tempv1loop = None
|
||||
|
||||
v2loop = optimizeLoopOrdedShortEdge(mesh, v1loop, v2loop, surplusFaces)
|
||||
|
||||
# make Faces from
|
||||
lenVloop = len(v1loop)
|
||||
lenSupFaces = len(surplusFaces)
|
||||
fIdx = 0
|
||||
offset = 0
|
||||
while fIdx < lenVloop:
|
||||
|
||||
face = copyFace( mesh.faces[v1loop[clamp(lenVloop, fIdx+1)]] )
|
||||
|
||||
if v1loop[fIdx] in surplusFaces:
|
||||
# Draw a try, this face does not catch with an edge.
|
||||
# So we must draw a tri and wedge it in.
|
||||
|
||||
# Copy old faces properties
|
||||
|
||||
face.v.append( selVertBetween2Faces(\
|
||||
mesh.faces[v1loop[clamp(lenVloop, fIdx)]],\
|
||||
mesh.faces[v1loop[clamp(lenVloop, fIdx+1)]]) )
|
||||
|
||||
face.v.append( selVertBetween2Faces(\
|
||||
mesh.faces[v1loop[clamp(lenVloop, fIdx+1)]],\
|
||||
mesh.faces[v1loop[clamp(lenVloop, fIdx+2)]]) )
|
||||
|
||||
#face.v.append( selVertBetween2Faces(\
|
||||
#mesh.faces[v2loop[clamp(lenVloop - lenSupFaces, (fIdx - offset +1 ))]],\
|
||||
#mesh.faces[v2loop[clamp(lenVloop - lenSupFaces, (fIdx - offset + 2))]]) )
|
||||
|
||||
face.v.append( selVertBetween2Faces(\
|
||||
mesh.faces[v2loop[clamp(lenVloop - lenSupFaces, (fIdx - offset))]],\
|
||||
mesh.faces[v2loop[clamp(lenVloop - lenSupFaces, fIdx - offset + 1)]]) )
|
||||
|
||||
mesh.faces.append(face)
|
||||
|
||||
# We need offset to work out how much smaller v2loop is at this current index.
|
||||
offset+=1
|
||||
|
||||
|
||||
else:
|
||||
# Draw a normal quad between the 2 edges/faces
|
||||
|
||||
face.v.append( selVertBetween2Faces(\
|
||||
mesh.faces[v1loop[clamp(lenVloop, fIdx)]],\
|
||||
mesh.faces[v1loop[clamp(lenVloop, fIdx+1)]]) )
|
||||
|
||||
face.v.append( selVertBetween2Faces(\
|
||||
mesh.faces[v1loop[clamp(lenVloop, fIdx+1)]],\
|
||||
mesh.faces[v1loop[clamp(lenVloop, fIdx+2)]]) )
|
||||
|
||||
face.v.append( selVertBetween2Faces(\
|
||||
mesh.faces[v2loop[clamp(lenVloop - lenSupFaces, (fIdx - offset +1 ))]],\
|
||||
mesh.faces[v2loop[clamp(lenVloop - lenSupFaces, (fIdx - offset + 2))]]) )
|
||||
|
||||
face.v.append( selVertBetween2Faces(\
|
||||
mesh.faces[v2loop[clamp(lenVloop - lenSupFaces, (fIdx - offset))]],\
|
||||
mesh.faces[v2loop[clamp(lenVloop - lenSupFaces, fIdx - offset + 1)]]) )
|
||||
|
||||
mesh.faces.append(face)
|
||||
|
||||
fIdx +=1
|
||||
|
||||
return mesh
|
||||
|
||||
|
||||
|
||||
#=======================================================#
|
||||
# Takes a face and returns the number of selected verts #
|
||||
#=======================================================#
|
||||
def faceVSel(face):
|
||||
vSel = 0
|
||||
for v in face.v:
|
||||
if v.sel:
|
||||
vSel +=1
|
||||
return vSel
|
||||
|
||||
|
||||
|
||||
|
||||
#================================================================#
|
||||
# This function takes a face and returns its selected vert loop #
|
||||
# it returns a list of face indicies
|
||||
#================================================================#
|
||||
def vertLoop(mesh, startFaceIdx, fIgLs): # fIgLs is a list of faces to ignore.
|
||||
# Here we store the faces indicies that
|
||||
# are a part of the first vertex loop
|
||||
vertLoopLs = [startFaceIdx]
|
||||
|
||||
restart = 0
|
||||
while restart == 0:
|
||||
# this keeps the face loop going until its told to stop,
|
||||
# If the face loop does not find an adjacent face then the vert loop has been compleated
|
||||
restart = 1
|
||||
|
||||
# Get my selected verts for the active face/edge.
|
||||
selVerts = []
|
||||
for v in mesh.faces[vertLoopLs[-1]].v:
|
||||
selVerts.append(v)
|
||||
|
||||
fIdx = 0
|
||||
while fIdx < len(mesh.faces) and restart:
|
||||
# Not already added to the vert list
|
||||
if fIdx not in fIgLs + vertLoopLs:
|
||||
# Has 2 verts selected
|
||||
if faceVSel(mesh.faces[fIdx]) > 1:
|
||||
# Now we need to find if any of the selected verts
|
||||
# are shared with our active face. (are we next to ActiveFace)
|
||||
for v in mesh.faces[fIdx].v:
|
||||
if v in selVerts:
|
||||
vertLoopLs.append(fIdx)
|
||||
restart = 0 # restart the face loop.
|
||||
break
|
||||
# if eIdx == 0 then it means we searched and found no matches...
|
||||
# time for a new vert loop,
|
||||
while eIdx:
|
||||
eIdx = len(selEdges)
|
||||
while eIdx:
|
||||
eIdx-=1
|
||||
|
||||
# Check for edge attached at the head of the loop.
|
||||
if contextVertLoop[0] == selEdges[eIdx].v1:
|
||||
contextVertLoop.insert(0, selEdges.pop(eIdx).v2)
|
||||
elif contextVertLoop[0] == selEdges[eIdx].v2:
|
||||
contextVertLoop.insert(0, selEdges.pop(eIdx).v1)
|
||||
|
||||
fIdx +=1
|
||||
|
||||
return vertLoopLs
|
||||
|
||||
|
||||
|
||||
|
||||
#================================================================#
|
||||
# Now we work out the optimum order to 'skin' the 2 vert loops #
|
||||
# by measuring the total distance of all edges created, #
|
||||
# test this for every possible series of joins #
|
||||
# and find the shortest, Once this is done the #
|
||||
# shortest dist can be skinned. #
|
||||
# returns only the 2nd-reordered vert loop #
|
||||
#================================================================#
|
||||
def optimizeLoopOrded(mesh, v1loop, v2loop):
|
||||
bestSoFar = None
|
||||
|
||||
# Measure the dist, ii is just a counter
|
||||
for ii in range(len(v1loop)):
|
||||
|
||||
# Loop twice , Once for the forward test, and another for the revearsed
|
||||
for iii in [None, None]:
|
||||
dist = measureVloop(mesh, v1loop, v2loop, bestSoFar)
|
||||
# Initialize the Best distance recorded
|
||||
if bestSoFar == None or dist < bestSoFar:
|
||||
bestSoFar = dist
|
||||
bestv2Loop = v2loop[:]
|
||||
|
||||
# We might have got the vert loop backwards, try the other way
|
||||
v2loop.reverse()
|
||||
listRotate(v2loop)
|
||||
return bestv2Loop
|
||||
|
||||
|
||||
#================================================================#
|
||||
# Now we work out the optimum order to 'skin' the 2 vert loops #
|
||||
# by measuring the total distance of all edges created, #
|
||||
# test this for every possible series of joins #
|
||||
# and find the shortest, Once this is done the #
|
||||
# shortest dist can be skinned. #
|
||||
# returns only the 2nd-reordered vert loop #
|
||||
#================================================================#
|
||||
def optimizeLoopOrdedShortEdge(mesh, v1loop, v2loop, surplusFaces):
|
||||
bestSoFar = None
|
||||
|
||||
# Measure the dist, ii is just a counter
|
||||
for ii in range(len(v2loop)):
|
||||
|
||||
# Loop twice , Once for the forward test, and another for the revearsed
|
||||
for iii in [None, None]:
|
||||
dist = measureVloop(mesh, v1loop, v2loop, surplusFaces, bestSoFar)
|
||||
print 'dist', dist
|
||||
# Initialize the Best distance recorded
|
||||
if bestSoFar == None or dist < bestSoFar:
|
||||
bestSoFar = dist
|
||||
bestv2Loop = v2loop[:]
|
||||
|
||||
|
||||
# We might have got the vert loop backwards, try the other way
|
||||
v2loop.reverse()
|
||||
#v2loop = listRotate(v2loop)
|
||||
listRotate(v2loop)
|
||||
print 'best so far ', bestSoFar
|
||||
return bestv2Loop
|
||||
|
||||
|
||||
#==============================#
|
||||
# Find our vert loop list #
|
||||
#==============================#
|
||||
# Find a face with 2 verts selected,
|
||||
#this will be the first face in out vert loop
|
||||
def findVertLoop(mesh, fIgLs): # fIgLs is a list of faces to ignore.
|
||||
|
||||
startFaceIdx = None
|
||||
|
||||
fIdx = 0
|
||||
while fIdx < len(mesh.faces):
|
||||
if fIdx not in fIgLs:
|
||||
# Do we have an edge?
|
||||
if faceVSel(mesh.faces[fIdx]) > 1:
|
||||
# THIS IS THE STARTING FACE.
|
||||
startFaceIdx = fIdx
|
||||
break
|
||||
fIdx+=1
|
||||
|
||||
# Here we access the function that generates the real vert loop
|
||||
if startFaceIdx != None:
|
||||
return vertLoop(mesh, startFaceIdx, fIgLs)
|
||||
else:
|
||||
# We are out'a vert loops, return a None,
|
||||
return None
|
||||
|
||||
#===================================#
|
||||
# Get the average loc of a vertloop #
|
||||
# This is used when working out the #
|
||||
# order to loft an object #
|
||||
#===================================#
|
||||
def vLoopAverageLoc(mesh, vertLoop):
|
||||
locList = [] # List of vert locations
|
||||
|
||||
fIdx = 0
|
||||
while fIdx < len(mesh.faces):
|
||||
if fIdx in vertLoop:
|
||||
for v in mesh.faces[fIdx].v:
|
||||
if v.sel:
|
||||
locList.append(v.co)
|
||||
fIdx+=1
|
||||
|
||||
return averageLocation(locList)
|
||||
|
||||
|
||||
|
||||
#=================================================#
|
||||
# Vert loop group functions
|
||||
|
||||
def getAllVertLoops(mesh):
|
||||
# Make a chain of vert loops.
|
||||
fIgLs = [] # List of faces to ignore
|
||||
allVLoops = [findVertLoop(mesh, fIgLs)]
|
||||
while allVLoops[-1] != None:
|
||||
|
||||
# In future ignore all faces in this vert loop
|
||||
fIgLs += allVLoops[-1]
|
||||
|
||||
# Add the new vert loop to the list
|
||||
allVLoops.append( findVertLoop(mesh, fIgLs) )
|
||||
|
||||
return allVLoops[:-1] # Remove the last Value- None.
|
||||
|
||||
|
||||
def reorderCircularVLoops(mesh, allVLoops):
|
||||
# Now get a location for each vert loop.
|
||||
allVertLoopLocs = []
|
||||
for vLoop in allVLoops:
|
||||
allVertLoopLocs.append( vLoopAverageLoc(mesh, vLoop) )
|
||||
|
||||
# We need to find the longest distance between 2 vert loops so we can
|
||||
reorderedVLoopLocs = []
|
||||
|
||||
# Start with this one, then find the next closest.
|
||||
# in doing this make a new list called reorderedVloop
|
||||
currentVLoop = 0
|
||||
reorderedVloopIdx = [currentVLoop]
|
||||
newOrderVLoops = [allVLoops[0]] # This is a re-ordered allVLoops
|
||||
while len(reorderedVloopIdx) != len(allVLoops):
|
||||
bestSoFar = None
|
||||
bestVIdxSoFar = None
|
||||
for vLoopIdx in range(len(allVLoops)):
|
||||
if vLoopIdx not in reorderedVloopIdx + [currentVLoop]:
|
||||
if bestSoFar == None:
|
||||
bestSoFar = measure( allVertLoopLocs[vLoopIdx], allVertLoopLocs[currentVLoop] )
|
||||
bestVIdxSoFar = vLoopIdx
|
||||
# Chech for edge vert at the tail.
|
||||
elif contextVertLoop[-1] == selEdges[eIdx].v1:
|
||||
contextVertLoop.append(selEdges.pop(eIdx).v2)
|
||||
elif contextVertLoop[-1] == selEdges[eIdx].v2:
|
||||
contextVertLoop.append(selEdges.pop(eIdx).v1)
|
||||
else:
|
||||
newDist = measure( allVertLoopLocs[vLoopIdx], allVertLoopLocs[currentVLoop] )
|
||||
if newDist < bestSoFar:
|
||||
bestSoFar = newDist
|
||||
bestVIdxSoFar = vLoopIdx
|
||||
|
||||
reorderedVloopIdx.append(bestVIdxSoFar)
|
||||
reorderedVLoopLocs.append(allVertLoopLocs[bestVIdxSoFar])
|
||||
newOrderVLoops.append( allVLoops[bestVIdxSoFar] )
|
||||
|
||||
# Start looking for the next best fit
|
||||
currentVLoop = bestVIdxSoFar
|
||||
|
||||
# This is not the locicle place to put this but its convieneint.
|
||||
# Here we find the 2 vert loops that are most far apart
|
||||
# We use this to work out which 2 vert loops not to skin when making an open loft.
|
||||
vLoopIdx = 0
|
||||
# Longest measured so far - 0 dummy.
|
||||
bestSoFar = 0
|
||||
while vLoopIdx < len(reorderedVLoopLocs):
|
||||
|
||||
# Skin back to the start if needs be, becuase this is a crcular loft
|
||||
toSkin2 = vLoopIdx + 1
|
||||
if toSkin2 == len(reorderedVLoopLocs):
|
||||
toSkin2 = 0
|
||||
|
||||
newDist = measure( reorderedVLoopLocs[vLoopIdx], reorderedVLoopLocs[toSkin2] )
|
||||
|
||||
if newDist >= bestSoFar:
|
||||
bestSoFar = newDist
|
||||
vLoopIdxNotToSkin = vLoopIdx + 1
|
||||
# None found? Keep looking
|
||||
continue
|
||||
|
||||
vLoopIdx +=1
|
||||
# Once found we.
|
||||
break
|
||||
|
||||
# Is this a loop? if so then its forst and last vert must be teh same.
|
||||
if contextVertLoop[0].index == contextVertLoop[-1].index:
|
||||
contextVertLoop.pop() # remove double vert
|
||||
mainVertLoops.append(contextVertLoop)
|
||||
|
||||
# Build context vert loops
|
||||
return mainVertLoops
|
||||
|
||||
|
||||
def skin2EdgeLoops(eloop1, eloop2, me, ob, MODE):
|
||||
# Make sure e1 loops is bigger then e2
|
||||
if len(eloop1.edges) != len(eloop2.edges):
|
||||
if len(eloop1.edges) < len(eloop2.edges):
|
||||
eloop1, eloop2 = eloop2, eloop1
|
||||
|
||||
eloop1.backup() # were about to cull faces
|
||||
CULL_FACES = len(eloop1.edges) - len(eloop2.edges)
|
||||
eloop1.removeSmallest(CULL_FACES, len(eloop1.edges))
|
||||
else:
|
||||
CULL_FACES = 0
|
||||
# First make sure poly vert loops are in sync with eachother.
|
||||
|
||||
return newOrderVLoops, vLoopIdxNotToSkin
|
||||
# The vector allong which we are skinning.
|
||||
skinVector = eloop1.centre - eloop2.centre
|
||||
|
||||
loopDist = skinVector.length
|
||||
|
||||
|
||||
# IS THE LOOP FLIPPED, IF SO FLIP BACK.
|
||||
angleBetweenLoopNormals = Mathutils.AngleBetweenVecs(eloop1.normal, eloop2.normal)
|
||||
|
||||
if angleBetweenLoopNormals > 90:
|
||||
eloop2.reverse()
|
||||
|
||||
|
||||
bestEloopDist = BIG_NUM
|
||||
bestOffset = 0
|
||||
# Loop rotation offset to test.1
|
||||
eLoopIdxs = range(len(eloop1.edges))
|
||||
for offset in range(len(eloop1.edges)):
|
||||
totEloopDist = 0 # Measure this total distance for thsi loop.
|
||||
|
||||
offsetIndexLs = eLoopIdxs[offset:] + eLoopIdxs[:offset] # Make offset index list
|
||||
|
||||
# e1Idx is always from 0 to N, e2Idx is offset.
|
||||
for e1Idx, e2Idx in enumerate(offsetIndexLs):
|
||||
# Measure the vloop distance ===============
|
||||
totEloopDist += ((eloop1.edges[e1Idx].v1.co - eloop2.edges[e2Idx].v1.co).length / loopDist) #/ nangle1
|
||||
totEloopDist += ((eloop1.edges[e1Idx].v2.co - eloop2.edges[e2Idx].v2.co).length / loopDist) #/ nangle1
|
||||
|
||||
# Premeture break if where no better off
|
||||
if totEloopDist > bestEloopDist:
|
||||
break
|
||||
|
||||
if totEloopDist < bestEloopDist:
|
||||
bestOffset = offset
|
||||
bestEloopDist = totEloopDist
|
||||
|
||||
# Modify V2 LS for Best offset
|
||||
eloop2.edges = eloop2.edges[bestOffset:] + eloop2.edges[:bestOffset]
|
||||
|
||||
|
||||
|
||||
for loopIdx in range(len(eloop2.edges)):
|
||||
e1 = eloop1.edges[loopIdx]
|
||||
e2 = eloop2.edges[loopIdx]
|
||||
|
||||
# Remember the pairs for fan filling culled edges.
|
||||
e1.match = e2; e2.match = e1
|
||||
|
||||
# need some smart face flipping code here.
|
||||
f = NMesh.Face([e1.v1, e1.v2, e2.v2, e2.v1])
|
||||
|
||||
f.sel = 1
|
||||
me.faces.append(f)
|
||||
|
||||
# FAN FILL MISSING FACES.
|
||||
if CULL_FACES:
|
||||
# Culled edges will be in eloop1.
|
||||
FAN_FILLED_FACES = 0
|
||||
|
||||
contextEdge = eloop1.edges[0] # The larger of teh 2
|
||||
while FAN_FILLED_FACES < CULL_FACES:
|
||||
while contextEdge.next.removed == 0:
|
||||
contextEdge = contextEdge.next
|
||||
|
||||
vertFanPivot = contextEdge.match.v2
|
||||
|
||||
while contextEdge.next.removed == 1:
|
||||
|
||||
f = NMesh.Face([contextEdge.next.v1, contextEdge.next.v2, vertFanPivot] )
|
||||
|
||||
|
||||
f.sel = 1
|
||||
me.faces.append(f)
|
||||
|
||||
# Should we use another var?, this will work for now.
|
||||
contextEdge.next.removed = 1
|
||||
|
||||
contextEdge = contextEdge.next
|
||||
FAN_FILLED_FACES += 1
|
||||
|
||||
eloop1.restore() # Add culled back into the list.
|
||||
#if angleBetweenLoopNormals > 90:
|
||||
# eloop2.reverse()
|
||||
|
||||
|
||||
is_editmode = Window.EditMode()
|
||||
if is_editmode: Window.EditMode(0)
|
||||
def main():
|
||||
global CULL_METHOD
|
||||
|
||||
is_editmode = Window.EditMode()
|
||||
if is_editmode: Window.EditMode(0)
|
||||
ob = Scene.GetCurrent().getActiveObject()
|
||||
if ob == None or ob.getType() != 'Mesh':
|
||||
return
|
||||
|
||||
me = ob.getData()
|
||||
if not me.edges:
|
||||
Draw.PupMenu('Error, add edge data first')
|
||||
if is_editmode: Window.EditMode(1)
|
||||
return
|
||||
|
||||
# BAD BLENDER PYTHON API, NEED TO ENTER EXIT EDIT MODE FOR ADDING EDGE DATA.
|
||||
# ADD EDGE DATA HERE, Python API CANT DO IT YET, LOOSES SELECTION
|
||||
|
||||
selEdges = getSelectedEdges(me, ob)
|
||||
vertLoops = getVertLoops(selEdges) # list of lists of edges.
|
||||
|
||||
if len(vertLoops) > 2:
|
||||
choice = Draw.PupMenu('Loft '+str(len(vertLoops))+' edge loops%t|loop|segment')
|
||||
if choice == -1:
|
||||
if is_editmode: Window.EditMode(1)
|
||||
return
|
||||
elif len(vertLoops) < 2:
|
||||
Draw.PupMenu('Error, No Vertloops found%t|if you have a valid selection, go in and out of face edit mode to update the selection state.')
|
||||
if is_editmode: Window.EditMode(1)
|
||||
return
|
||||
else:
|
||||
choice = 2
|
||||
|
||||
|
||||
# The line below checks if any of the vert loops are differenyt in length.
|
||||
if False in [len(v) == len(vertLoops[0]) for v in vertLoops]:
|
||||
CULL_METHOD = Draw.PupMenu('Small to large edge loop distrobution method%t|remove edges evenly|remove smallest edges edges')
|
||||
if CULL_METHOD == -1:
|
||||
if is_editmode: Window.EditMode(1)
|
||||
return
|
||||
|
||||
if CULL_METHOD ==1: # RESET CULL_METHOD
|
||||
CULL_METHOD = 0 # shortest
|
||||
else:
|
||||
CULL_METHOD = 1 # even
|
||||
|
||||
|
||||
time1 = sys.time()
|
||||
# Convert to special edge data.
|
||||
edgeLoops = []
|
||||
for vloop in vertLoops:
|
||||
edgeLoops.append(edgeLoop(vloop))
|
||||
|
||||
|
||||
# VERT LOOP ORDERING CODE
|
||||
# Build a worm list - grow from Both ends
|
||||
edgeOrderedList = [edgeLoops.pop()]
|
||||
|
||||
# Find the closest.
|
||||
bestSoFar = BIG_NUM
|
||||
bestIdxSoFar = None
|
||||
for edLoopIdx, edLoop in enumerate(edgeLoops):
|
||||
l =(edgeOrderedList[-1].centre - edLoop.centre).length
|
||||
if l < bestSoFar:
|
||||
bestIdxSoFar = edLoopIdx
|
||||
bestSoFar = l
|
||||
|
||||
edgeOrderedList.append( edgeLoops.pop(bestIdxSoFar) )
|
||||
|
||||
# Now we have the 2 closest, append to either end-
|
||||
# Find the closest.
|
||||
while edgeLoops:
|
||||
bestSoFar = BIG_NUM
|
||||
bestIdxSoFar = None
|
||||
first_or_last = 0 # Zero is first
|
||||
for edLoopIdx, edLoop in enumerate(edgeLoops):
|
||||
l1 =(edgeOrderedList[-1].centre - edLoop.centre).length
|
||||
|
||||
if l1 < bestSoFar:
|
||||
bestIdxSoFar = edLoopIdx
|
||||
bestSoFar = l1
|
||||
first_or_last = 1 # last
|
||||
|
||||
l2 =(edgeOrderedList[0].centre - edLoop.centre).length
|
||||
if l2 < bestSoFar:
|
||||
bestIdxSoFar = edLoopIdx
|
||||
bestSoFar = l2
|
||||
first_or_last = 0 # last
|
||||
|
||||
if first_or_last: # add closest Last
|
||||
edgeOrderedList.append( edgeLoops.pop(bestIdxSoFar) )
|
||||
else: # Add closest First
|
||||
edgeOrderedList.insert(0, edgeLoops.pop(bestIdxSoFar) ) # First
|
||||
|
||||
for i in range(len(edgeOrderedList)-1):
|
||||
skin2EdgeLoops(edgeOrderedList[i], edgeOrderedList[i+1], me, ob, 0)
|
||||
if choice == 1 and len(edgeOrderedList) > 2: # Loop
|
||||
skin2EdgeLoops(edgeOrderedList[0], edgeOrderedList[-1], me, ob, 0)
|
||||
|
||||
me.update(1, 1, 0)
|
||||
if is_editmode: Window.EditMode(1)
|
||||
|
||||
# Get a mesh and raise errors if we cant
|
||||
mesh = None
|
||||
if choice == -1:
|
||||
pass
|
||||
elif len(Object.GetSelected()) > 0:
|
||||
if Object.GetSelected()[0].getType() == 'Mesh':
|
||||
mesh = Object.GetSelected()[0].getData()
|
||||
else:
|
||||
error('please select a mesh')
|
||||
else:
|
||||
error('no mesh object selected')
|
||||
|
||||
time1 = sys.time()
|
||||
if mesh != None:
|
||||
Window.WaitCursor(1)
|
||||
allVLoops = getAllVertLoops(mesh)
|
||||
|
||||
# Re order the vert loops
|
||||
allVLoops, vLoopIdxNotToSkin = reorderCircularVLoops(mesh, allVLoops)
|
||||
|
||||
vloopIdx = 0
|
||||
while vloopIdx < len(allVLoops):
|
||||
#print range(len(allVLoops) )
|
||||
#print vloopIdx
|
||||
#print allVLoops[vloopIdx]
|
||||
|
||||
# Skin back to the start if needs be, becuase this is a crcular loft
|
||||
toSkin2 = vloopIdx + 1
|
||||
if toSkin2 == len(allVLoops):
|
||||
toSkin2 = 0
|
||||
|
||||
# Circular loft or not?
|
||||
if arg[0] == 'B': # B for open
|
||||
if vloopIdx != vLoopIdxNotToSkin:
|
||||
mesh = skinVertLoops(mesh, allVLoops[vloopIdx], allVLoops[toSkin2])
|
||||
elif arg[0] == 'A': # A for closed
|
||||
mesh = skinVertLoops(mesh, allVLoops[vloopIdx], allVLoops[toSkin2])
|
||||
|
||||
vloopIdx +=1
|
||||
|
||||
mesh.update(1,(mesh.edges != []),0)
|
||||
|
||||
if is_editmode: Window.EditMode(1)
|
||||
Window.WaitCursor(0)
|
||||
print "skinning time: %.2f" % (sys.time() - time1)
|
||||
main()
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
""" Registration info for Blender menus:
|
||||
Name: 'Texture Baker'
|
||||
Blender: 237
|
||||
Blender: 236
|
||||
Group: 'UV'
|
||||
Tooltip: 'Procedural to uvmapped texture baker'
|
||||
"""
|
||||
@ -11,10 +11,11 @@ __author__ = "Jean-Michel Soler (jms)"
|
||||
__url__ = ("blender", "elysiun",
|
||||
"Official Page, http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_mesh3d2uv2d_en.htm",
|
||||
"Communicate problems and errors, http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender")
|
||||
__version__ = "0.2.8 2005/7/20"
|
||||
__version__ = "0.3.0 2005/10/09"
|
||||
|
||||
__bpydoc__ = """\
|
||||
Texture Baker "bakes" Blender procedural materials (including textures): it saves them as 2d uv-mapped images.
|
||||
This script "bakes" Blender procedural materials (including textures): it saves
|
||||
them as 2d uv-mapped images.
|
||||
|
||||
This script saves an uv texture layout of the chosen mesh, that can be used as
|
||||
an uv map for it. It is a way to export procedurals from Blender as normal
|
||||
@ -23,21 +24,22 @@ with the mesh in games and other 3d applications.
|
||||
|
||||
Usage:
|
||||
|
||||
a) Enter face mode and define uv coordinates for your mesh (do not forget to choose a development shape);<br>
|
||||
b) Define its materials and textures;<br>
|
||||
a) Enter face mode and define uv coordinates for your mesh;<br>
|
||||
b) Define its materials and textures ;
|
||||
c) Run this script and check the console.
|
||||
|
||||
Global variables:
|
||||
Global variables
|
||||
|
||||
a) FRAME (integer): the last frame of the animation, autodocumented.<br>
|
||||
b) LIMIT (integer): 0 or 1, uvcoords may exceed limits 0.0 to 1.0, this variable obliges the script to do a complete framing of the uvcoord.
|
||||
a) FRAME integer, the last frame of the animation, autodocumented .
|
||||
b) LIMIT integer, 0 or 1, uvcoords may exceed limits 0.0 to 1.0 , this variable
|
||||
obliges the script to do a complete framing of the uvcoord .
|
||||
|
||||
Notes:<br>
|
||||
This script was based on a suggestion by Martin (Theeth) Poirier.
|
||||
This script was based on a suggestion by Martin (Theeth) Poirier;<br>
|
||||
"""
|
||||
|
||||
#---------------------------------------------
|
||||
# Last release : 0.2.8 , 2005/07/20 , 17h10
|
||||
# Last release : 0.3.0 , 2005/10/09 , 23h23
|
||||
#---------------------------------------------
|
||||
#---------------------------------------------
|
||||
# (c) jm soler 07/2004 : 'Procedural Texture Baker'
|
||||
@ -47,6 +49,14 @@ Notes:<br>
|
||||
#
|
||||
# Released under Blender Artistic Licence
|
||||
#
|
||||
#
|
||||
# 0.3.0
|
||||
# TAILLEIMAGE variable
|
||||
#
|
||||
# 0.2.9
|
||||
# -- little probleme with the KEEPRENDERWINDOW variable .
|
||||
# removed . script seems to works correctly now .
|
||||
#
|
||||
# 0.2.8
|
||||
# -- added the forgotten image property in face
|
||||
# data. a little longer but better.
|
||||
@ -201,6 +211,8 @@ DEBUG=1
|
||||
RENDERLAYER=20
|
||||
SCENELAYERS=[]
|
||||
|
||||
|
||||
|
||||
helpmsg = """
|
||||
Texture Baker:
|
||||
|
||||
@ -250,6 +262,7 @@ def RenameImage(RDIR, MYDIR, FILENAME, name):
|
||||
"""
|
||||
newfname = RDIR + MYDIR + name
|
||||
if newfname.find('.png', -4) < 0 : newfname += '.png'
|
||||
|
||||
if not Blender.sys.exists(newfname):
|
||||
os.rename(FILENAME, newfname)
|
||||
else:
|
||||
@ -290,13 +303,13 @@ def SAVE_image (rc, name, FRAME, result):
|
||||
rc.startFrame(NEWFRAME)
|
||||
rc.endFrame(NEWFRAME)
|
||||
rc.renderAnim()
|
||||
if result!=2 and not KEEPRENDERWINDOW:
|
||||
if result!=2 :
|
||||
Blender.Scene.Render.CloseRenderWindow()
|
||||
FILENAME = "%04d" % NEWFRAME
|
||||
FILENAME = FILENAME.replace (' ', '0')
|
||||
FILENAME = RDIR + MYDIR + FILENAME + '.png'
|
||||
RenameImage(RDIR, MYDIR, FILENAME, name)
|
||||
|
||||
|
||||
rc.endFrame(OLDEFRAME)
|
||||
rc.startFrame(OLDSFRAME)
|
||||
rc.setRenderPath(RENDERDIR)
|
||||
@ -346,14 +359,24 @@ def SHOOT (XYlimit, frame, obj, name, FRAME, result):
|
||||
OLDy = context.imageSizeY()
|
||||
OLDx = context.imageSizeX()
|
||||
|
||||
tres = Draw.PupMenu('TEXTURE OUT RESOLUTION : %t | 256 %x1 | 512 %x2 | 768 %x3 | 1024 %x4 | 2048 %x5 ')
|
||||
TAILLEIMAGE='TEXTURE OUT RESOLUTION : %t |'
|
||||
TAILLEIMAGE+='256 %x1 |'
|
||||
TAILLEIMAGE+='512 %x2 |'
|
||||
TAILLEIMAGE+='768 %x3 |'
|
||||
TAILLEIMAGE+='1024 %x4 |'
|
||||
TAILLEIMAGE+='2048 %x5 '
|
||||
#TAILLEIMAGE+='| 4096 %x6 '
|
||||
tres = Draw.PupMenu(TAILLEIMAGE)
|
||||
|
||||
if (tres) == 1: res = 256
|
||||
elif (tres) == 2: res = 512
|
||||
elif (tres) == 3: res = 768
|
||||
elif (tres) == 4: res = 1024
|
||||
elif (tres) == 5: res = 2048
|
||||
# elif (tres) == 6: res = 4096
|
||||
else: res = 512
|
||||
#...
|
||||
|
||||
|
||||
SCENELAYERS=SC.layers
|
||||
SC.layers = [20]
|
||||
@ -419,7 +442,7 @@ def Mesh2UVCoord (LIMIT):
|
||||
"""
|
||||
global PUTRAW, FRAME, SCENELAYERS
|
||||
|
||||
try:
|
||||
try :
|
||||
MESH3D = Object.GetSelected()[0]
|
||||
if MESH3D.getType() == 'Mesh':
|
||||
MESH = MESH3D.getData()
|
||||
@ -444,7 +467,7 @@ def Mesh2UVCoord (LIMIT):
|
||||
v1.co[2] = 0.0
|
||||
MESH2.verts.append(v1)
|
||||
f1.v.append(MESH2.verts[len(MESH2.verts) - 1])
|
||||
|
||||
|
||||
MESH2.faces.append(f1)
|
||||
f1.uv = f.uv[:]
|
||||
f1.col = f.col[:]
|
||||
@ -464,6 +487,7 @@ def Mesh2UVCoord (LIMIT):
|
||||
NewOBJECT.setLocation (OBJPOS, OBJPOS, 0.0)
|
||||
NewOBJECT.setEuler (0.0, 0.0, 0.0)
|
||||
|
||||
|
||||
MESH2.removeAllKeys()
|
||||
MESH2.update()
|
||||
MESH2.insertKey (1, 'absolute')
|
||||
@ -471,7 +495,7 @@ def Mesh2UVCoord (LIMIT):
|
||||
|
||||
imagename = 'uvtext'
|
||||
|
||||
name = "CHANGE IMAGE NAME ? %t | Replace it | No replacing | Script help"
|
||||
name = "CHANGE IMAGE NAME ? %t | Replace it | No replace | Script help"
|
||||
result = Draw.PupMenu(name)
|
||||
|
||||
if result == 1:
|
||||
@ -501,18 +525,17 @@ def Mesh2UVCoord (LIMIT):
|
||||
Blender.Redraw()
|
||||
|
||||
else:
|
||||
Blender.ShowHelp('tex2uvbaker.py')
|
||||
#Draw.PupMenu("Ready%t|Please check console for instructions")
|
||||
if DEBUG: print helpmsg
|
||||
Draw.PupMenu("Ready%t|Please check console for instructions")
|
||||
print helpmsg
|
||||
|
||||
else:
|
||||
name = "ERROR: active object is not a mesh or has no UV coordinates"
|
||||
name = "Error%t|Active object is not a mesh or has no UV coordinates"
|
||||
result = Draw.PupMenu(name)
|
||||
print 'problem : no object selected or not mesh'
|
||||
|
||||
except:
|
||||
name = "ERROR: active object is not a mesh or has no UV coordinates"
|
||||
name = "Error%t|Active object is not a mesh or has no UV coordinates"
|
||||
result = Draw.PupMenu(name)
|
||||
print 'problem : no object selected or not mesh'
|
||||
|
||||
Mesh2UVCoord(LIMIT)
|
||||
Mesh2UVCoord(LIMIT)
|
||||
|
@ -11,7 +11,7 @@ __author__ = "Jean-Michel Soler (jms)"
|
||||
__url__ = ("blender", "elysiun",
|
||||
"Script's homepage, http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_uvpainting.htm",
|
||||
"Communicate problems and errors, http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender")
|
||||
__version__ = "0.5 05/2004"
|
||||
__version__ = "0.8 08/2005"
|
||||
|
||||
__bpydoc__ = """\
|
||||
This script "paints" uv-mappings with the model's vertex colors.
|
||||
@ -33,6 +33,29 @@ Notes:<br>
|
||||
the "Make" VColors button in the edit mesh buttons win, the current light setup
|
||||
is saved as vertex colors for the model;<br>
|
||||
Check the script's homepage for example images.
|
||||
|
||||
Short keys Documentation
|
||||
|
||||
KEYS
|
||||
M : dipslay GUI Menu
|
||||
D : Set/Unset Documentation
|
||||
S : Save current window content
|
||||
in a tga file
|
||||
Q or ESC : Exit
|
||||
T : Set/Unset Transparency
|
||||
L : Set/Unset lines
|
||||
E : Set/Unset outline
|
||||
B : Set lines color to Black
|
||||
W : Set lines color to white
|
||||
ARROW : displace model on
|
||||
UP/DOWN/LEFT/RIGHT side
|
||||
PADPLUS : increase ZOOM
|
||||
PADMINUS : decrease ZOOM
|
||||
HOME : cancel display modifs
|
||||
|
||||
Mouse button
|
||||
RIGHTMOUSE : same as arrows
|
||||
|
||||
"""
|
||||
|
||||
# $Id$
|
||||
@ -99,18 +122,87 @@ def exist(path):
|
||||
return 0
|
||||
return 1
|
||||
|
||||
loc0= Blender.sys.dirname(Blender.Get ("filename"))
|
||||
loc2=loc0+Blender.sys.dirsep+'test00.tga'
|
||||
loc0= Blender.Get ("filename").replace('\\','/')
|
||||
loc0=loc0[:loc0.rfind('/')]
|
||||
|
||||
loc2=loc0+'/'+'test00.tga'
|
||||
|
||||
|
||||
mouse_x,mouse_y=0,0
|
||||
mouse_xr=1
|
||||
mouse_yr=1
|
||||
POS=[0,0]
|
||||
ANC=[0,0]
|
||||
XY=[0,0]
|
||||
size=[]
|
||||
sel=0
|
||||
X,Y=0,0
|
||||
TRANSP,EMPTY,DOCU=0,0,0
|
||||
MENU, SAVE =1,0
|
||||
|
||||
glCr=glRasterPos2d
|
||||
glCl3=glColor3f
|
||||
glCl4=glColor4f
|
||||
glRct=glRectf
|
||||
|
||||
LC=1.0
|
||||
|
||||
xlimit=0
|
||||
selmatlist=[]
|
||||
LIM=[0.0,0.0,0.0,0.0]
|
||||
NOLIM=1
|
||||
if not NOLIM : LIM=[-1.0,1.0,-1.0,1.0]
|
||||
|
||||
def triangle(a,b,c):
|
||||
TR=0.8
|
||||
|
||||
def Doc(size):
|
||||
S0,S1=40,50
|
||||
|
||||
a=[S0,size[3]-S1, .8,.8,.8]
|
||||
b=[S0*7,size[3]-S1, .8,0.8,0.8]
|
||||
c=[S0*7,size[3]-S1*7, 0.8,0.8,0.8]
|
||||
d=[S0,size[3]-S1*7, 0.8,0.8,0.8]
|
||||
Tcarre(a,b,c,d,0.8)
|
||||
Lcarre(a,b,c,d,0.0)
|
||||
DOC=[' ',
|
||||
'Documentation',
|
||||
' ',
|
||||
'KEYS ',
|
||||
'M : dipslay GUI Menu',
|
||||
'D : Set/Unset Documentation',
|
||||
'S : Save current window content',
|
||||
' in a tga file',
|
||||
'Q or ESC : Exit',
|
||||
'T : Set/Unset Transparency',
|
||||
'L : Set/Unset lines',
|
||||
'E : Set/Unset outline',
|
||||
'B : Set lines color to Black ',
|
||||
'W : Set lines color to white',
|
||||
'ARROW : displace model on ',
|
||||
' UP/DOWN/LEFT/RIGHT side' ,
|
||||
'PADPLUS : increase ZOOM ',
|
||||
'PADMINUS : decrease ZOOM ',
|
||||
'HOME : cancel display modifs',
|
||||
' ',
|
||||
'Mouse button',
|
||||
'RIGHTMOUSE : same as arrows',
|
||||
]
|
||||
glColor3f(0.0,0.0,0.0)
|
||||
for D in DOC :
|
||||
glRasterPos2f(S0+8, size[3]-S1-13*DOC.index(D))
|
||||
Text(D)
|
||||
|
||||
def Ttriangle(a,b,c):
|
||||
glBegin(GL_TRIANGLES);
|
||||
glColor4f(a[2],a[3],a[4],TR)
|
||||
glVertex2f(a[0],a[1]);
|
||||
glColor4f(b[2],b[3],b[4],TR)
|
||||
glVertex2f(b[0],b[1]);
|
||||
glColor4f(c[2],c[3],c[4],TR)
|
||||
glVertex2f(c[0],c[1]);
|
||||
glEnd();
|
||||
|
||||
def Ftriangle(a,b,c):
|
||||
glBegin(GL_TRIANGLES);
|
||||
glColor3f(a[2],a[3],a[4])
|
||||
glVertex2f(a[0],a[1]);
|
||||
@ -120,33 +212,46 @@ def triangle(a,b,c):
|
||||
glVertex2f(c[0],c[1]);
|
||||
glEnd();
|
||||
|
||||
def Ltriangle(a,b,c):
|
||||
glBegin(GL_LINES);
|
||||
glColor3f(1.0,1.0,1.0)
|
||||
glVertex2f(a[0],a[1]);
|
||||
glVertex2f(b[0],b[1]);
|
||||
glVertex2f(c[0],c[1]);
|
||||
glEnd();
|
||||
def Ltriangle(a,b,c,LC=0.5):
|
||||
TL=[a,b,c,a]
|
||||
for v in [0,1,2] :
|
||||
glBegin(GL_LINES);
|
||||
glColor4f(LC,LC,LC,TR+0.2)
|
||||
glVertex2f(TL[v][0],TL[v][1]);
|
||||
glVertex2f(TL[v+1][0],TL[v+1][1]);
|
||||
glEnd();
|
||||
|
||||
def carre(a,b,c,d):
|
||||
triangle(a,b,c)
|
||||
triangle(a,c,d)
|
||||
|
||||
def Lcarre(a,b,c,d):
|
||||
glBegin(GL_LINES);
|
||||
glColor3f(1.0,1.0,1.0)
|
||||
glVertex2f(a[0],a[1]);
|
||||
glVertex2f(b[0],b[1]);
|
||||
glVertex2f(c[0],c[1]);
|
||||
glVertex2f(d[0],d[1]);
|
||||
glEnd();
|
||||
def Tcarre(a,b,c,d,LC=1.0):
|
||||
Ttriangle(a,b,c)
|
||||
Ttriangle(a,c,d)
|
||||
|
||||
def Fcarre(a,b,c,d,LC=1.0):
|
||||
Ftriangle(a,b,c)
|
||||
Ftriangle(a,c,d)
|
||||
|
||||
def Lcarre(a,b,c,d,LC=0.5):
|
||||
TL=[a,b,c,d,a]
|
||||
for v in [0,1,2,3] :
|
||||
glBegin(GL_LINES);
|
||||
glColor4f(LC,LC,LC,TR+0.2)
|
||||
glVertex2f(TL[v][0],TL[v][1]);
|
||||
glVertex2f(TL[v+1][0],TL[v+1][1]);
|
||||
glEnd();
|
||||
|
||||
|
||||
def transface(f,x,y):
|
||||
global xlimit
|
||||
def transface(f,x,y,u=0.0, v=0.0):
|
||||
global xlimit, LIM
|
||||
global mouse_xr,sel, ANC, X,Y
|
||||
global mouse_yr, POS, XY,size
|
||||
global mouse_x, mouse_y
|
||||
|
||||
|
||||
mouse_x=mouse_xr-size[0]
|
||||
mouse_y=mouse_yr-size[1]
|
||||
|
||||
if sel==1:
|
||||
POS=[mouse_x-ANC[0],mouse_y-ANC[1]]
|
||||
u,v=POS
|
||||
|
||||
a=[0,0,0.0, 0.0,0.0,0.0]
|
||||
b=[0,0,0.0, 0.0,0.0,0.0]
|
||||
@ -154,8 +259,8 @@ def transface(f,x,y):
|
||||
d=[0,0,0.0, 0.0,0.0,0.0]
|
||||
|
||||
if len(f.v)>=3:
|
||||
a[0]=int(f.uv[0][0]*x)
|
||||
a[1]=int(f.uv[0][1]*y)
|
||||
a[0]=int((f.uv[0][0]-LIM[1])*x+u)
|
||||
a[1]=int((f.uv[0][1]-LIM[3])*y+v)
|
||||
|
||||
if a[0]>xlimit:
|
||||
xlimit=a[0]
|
||||
@ -164,8 +269,8 @@ def transface(f,x,y):
|
||||
a[3]=f.col[0].g/255.0
|
||||
a[4]=f.col[0].b/255.0
|
||||
|
||||
c[0]=int(f.uv[2][0]*x)
|
||||
c[1]=int(f.uv[2][1]*y)
|
||||
c[0]=int((f.uv[2][0]-LIM[1])*x+u)
|
||||
c[1]=int((f.uv[2][1]-LIM[3])*y+v)
|
||||
|
||||
if c[0]>xlimit:
|
||||
xlimit=c[0]
|
||||
@ -175,8 +280,8 @@ def transface(f,x,y):
|
||||
c[4]=f.col[2].b/255.0
|
||||
|
||||
|
||||
b[0]=int(f.uv[1][0]*x)
|
||||
b[1]=int(f.uv[1][1]*y)
|
||||
b[0]=int((f.uv[1][0]-LIM[1])*x+u)
|
||||
b[1]=int((f.uv[1][1]-LIM[3])*y+v)
|
||||
|
||||
if b[0]>xlimit:
|
||||
xlimit=b[0]
|
||||
@ -187,8 +292,8 @@ def transface(f,x,y):
|
||||
|
||||
|
||||
if len(f.v)==4:
|
||||
d[0]=int(f.uv[3][0]*x)
|
||||
d[1]=int(f.uv[3][1]*y)
|
||||
d[0]=int((f.uv[3][0]-LIM[1])*x+u)
|
||||
d[1]=int((f.uv[3][1]-LIM[3])*y+v)
|
||||
|
||||
if d[0]>xlimit:
|
||||
xlimit=d[0]
|
||||
@ -214,44 +319,53 @@ def extract_faces(me,MENU):
|
||||
return listf
|
||||
|
||||
def affiche_mesh(ME,x,y):
|
||||
global LINE,xlimit,MMENU,XLIMIT,xwin,xlimit
|
||||
|
||||
global LINE,xlimit,MMENU,XLIMIT,xwin,xlimit,LC
|
||||
global LIM, EMPTY,TRANSP
|
||||
if not NOLIM : LIM=[-1.0,1.0,-1.0,1.0]
|
||||
|
||||
if ME.getType()=='Mesh':
|
||||
me=GetRaw(ME.getData().name)
|
||||
|
||||
me=ME.getData()
|
||||
if MMENU.val==1:
|
||||
se=me.faces
|
||||
|
||||
elif MMENU.val==3:
|
||||
se=me.getSelectedFaces()
|
||||
|
||||
se=[s for s in me.faces if s in me.getSelectedFaces() or s.sel]
|
||||
elif MMENU.val==2:
|
||||
se=extract_faces(me,2)
|
||||
|
||||
se=extract_faces(me,2)
|
||||
if not NOLIM :
|
||||
for s in se:
|
||||
for u in s.uv:
|
||||
if u[0] >LIM[0] : LIM[0]=u[0]
|
||||
if u[0] <LIM[1] : LIM[1]=u[0]
|
||||
if u[1] >LIM[2] : LIM[2]=u[1]
|
||||
if u[1] <LIM[3] : LIM[3]=u[1]
|
||||
xlimit=0
|
||||
for f in se:
|
||||
a,b,c,d=transface(f,x,y)
|
||||
if len(f.v)==4:
|
||||
triangle(a,b,c)
|
||||
triangle(a,c,d)
|
||||
elif len(f.v)==3:
|
||||
triangle(a,b,c)
|
||||
if not EMPTY and not TRANSP:
|
||||
if len(f.v)==4:
|
||||
Ftriangle(a,b,c)
|
||||
Ftriangle(a,c,d)
|
||||
elif len(f.v)==3:
|
||||
Ftriangle(a,b,c)
|
||||
elif not EMPTY :
|
||||
if len(f.v)==4:
|
||||
Ttriangle(a,b,c)
|
||||
Ttriangle(a,c,d)
|
||||
elif len(f.v)==3:
|
||||
Ttriangle(a,b,c)
|
||||
|
||||
if LINE.val==1:
|
||||
if LINE.val==1 or EMPTY:
|
||||
for f in se:
|
||||
a,b,c,d=transface(f,x,y)
|
||||
if len(f.v)==4:
|
||||
Lcarre(a,b,c,d)
|
||||
Lcarre(a,b,c,d,LC)
|
||||
elif len(f.v)==3:
|
||||
Ltriangle(a,b,c)
|
||||
|
||||
Ltriangle(a,b,c,LC)
|
||||
if XLIMIT.val==0:
|
||||
Lcarre([1,1],[1,y-2],[xlimit+2,y-2],[xlimit+2,1])
|
||||
else:
|
||||
Lcarre([1,1],[1,y-2],[xwin-2,y-2],[xwin-2,1])
|
||||
|
||||
|
||||
|
||||
|
||||
def write_tgafile(loc2,bitmap,width,height,profondeur):
|
||||
|
||||
f=open(loc2,'wb')
|
||||
@ -286,10 +400,13 @@ def write_tgafile(loc2,bitmap,width,height,profondeur):
|
||||
|
||||
|
||||
def save(x0,y0,dx,dy):
|
||||
global SAVE
|
||||
im = Buffer(GL_BYTE,[dx*(dy+1),4])
|
||||
glReadPixels(x0,y0,dx,dy,GL_RGBA, GL_BYTE,im);
|
||||
print len(im), dx*dy, dx, dy, len(im)/dy
|
||||
write_tgafile(loc2,im,dx,dy+1,4)
|
||||
SAVE=0
|
||||
Blender.Redraw()
|
||||
|
||||
def DOCMat_list(TMATList,ME):
|
||||
me=Blender.NMesh.GetRaw(ME.getData().name)
|
||||
@ -342,9 +459,13 @@ TEXT=Create(loc2)
|
||||
# uvpaint4
|
||||
# ----------
|
||||
TMENU="MODE MENU %t|All %x1|Material %x2|Selected %x3"
|
||||
# ----------
|
||||
# uvpaint4
|
||||
# ----------
|
||||
# coming soon : "|vertex group %x4", perhaps in uvpainter v0.5
|
||||
LCOLOR= Create(64)
|
||||
SAVE=0
|
||||
|
||||
# coming soon : "|Bone %x4", perhaps in uvpainter v0.5
|
||||
|
||||
MMENU=Create(3)
|
||||
TDOCMat = Create(0)
|
||||
# ----------
|
||||
@ -370,13 +491,14 @@ n0=32
|
||||
|
||||
def draw():
|
||||
global NSIZE,LINE,x0,y0,y,x,TEXT,MMENU,TDOCMat
|
||||
global XLIMIT,selmatlist,xwin
|
||||
global XLIMIT,selmatlist,xwin, LCOLOR, SAVE
|
||||
global mouse_xr,sel, ANC, X,Y, TRANSP, DOCU
|
||||
global mouse_yr, POS, XY,size, TRANSP,EMPTY
|
||||
global MENU, SAVE
|
||||
|
||||
size=Buffer(GL_FLOAT, 4)
|
||||
glGetFloatv(GL_SCISSOR_BOX, size)
|
||||
size= size.list
|
||||
|
||||
for s in [0,1,2,3]: size[s]=int(size[s])
|
||||
size=[int(s) for s in size ]
|
||||
|
||||
n0=32
|
||||
x0=size[0]
|
||||
@ -390,78 +512,138 @@ def draw():
|
||||
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT)
|
||||
|
||||
glShadeModel(GL_SMOOTH)
|
||||
#transparence
|
||||
if TRANSP :
|
||||
glEnable(GL_BLEND)
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
|
||||
|
||||
SelecMESH=Blender.Object.GetSelected()
|
||||
if SelecMESH!=[]:
|
||||
if SelecMESH[0].getType()=='Mesh':
|
||||
affiche_mesh(SelecMESH[0],int(y*NSIZE.val),int(y*NSIZE.val-n0-2))
|
||||
if SelecMESH!=[] and SelecMESH[0].getType()=='Mesh':
|
||||
affiche_mesh(SelecMESH[0],int(y*NSIZE.val),int(y*NSIZE.val-2))
|
||||
|
||||
glColor3f(0.0,0.0,0.0)
|
||||
glRectf(4,size[3],555,size[3]-32 )
|
||||
if MENU:
|
||||
glColor3f(0.0,0.0,0.0)
|
||||
glRectf(4,size[3],555,size[3]-32 )
|
||||
glColor3f(1.0,1.0,1.0)
|
||||
|
||||
glRasterPos2f(8, size[3]-13)
|
||||
Text("uvpainter v0.8")
|
||||
|
||||
glRasterPos2f(8, size[3]-28)
|
||||
Text("Jm Soler, 08/2005")
|
||||
|
||||
glColor3f(1.0,1.0,1.0)
|
||||
Button("ReDraw" ,16 ,290-118+61 ,size[3]-30 ,60 ,13)
|
||||
Button("Exit" ,1 ,250-122+63 ,size[3]-30 ,38 ,13)
|
||||
Button("Save" ,6 ,250-16+61 ,size[3]-30 ,40 ,13)
|
||||
|
||||
glRasterPos2f(8, size[3]-13)
|
||||
Text("uvpainter v0.5")
|
||||
|
||||
glRasterPos2f(8, size[3]-28)
|
||||
Text("Jm Soler, 05/2004")
|
||||
NSIZE= Slider("Sc:",4 ,290-118+61 ,size[3]-15 , 102, 13, NSIZE.val, 0.1,5.0,0,"SIZE.")
|
||||
LINE=Toggle("line", 5 ,250-122+63 ,size[3]-15 , 38, 13, LINE.val, "Draw lines")
|
||||
|
||||
Button("ReDraw" ,16 ,290-118+61 ,size[3]-30 ,60 ,13)
|
||||
Button("Exit" ,1 ,250-122+63 ,size[3]-30 ,38 ,13)
|
||||
Button("Save" ,6 ,250-16+61 ,size[3]-30 ,40 ,13)
|
||||
glRasterPos2f(250-130 ,size[3]-13,)
|
||||
Text("Mode")
|
||||
|
||||
NSIZE= Slider("Sc:",4 ,290-118+61 ,size[3]-15 , 102, 13, NSIZE.val, 0.1,1.5,0,"SIZE.")
|
||||
LINE=Toggle("line", 5 ,250-122+63 ,size[3]-15 , 38, 13, LINE.val, "Draw lines")
|
||||
LCOLOR=Number("", 50, 250-77,size[3]-15,18,13,LCOLOR.val,1,64,'Line color, 64-lighter, 1-darker.')
|
||||
|
||||
glRasterPos2f(250-130 ,size[3]-13,)
|
||||
Text("Mode")
|
||||
MMENU= Menu(TMENU ,2 ,250-130, size[3]-30, 63, 13, MMENU.val, "MODE menu.")
|
||||
|
||||
MMENU= Menu(TMENU ,2 ,250-130, size[3]-30, 63, 13, MMENU.val, "MODE menu.")
|
||||
if MMENU.val==1 or MMENU.val==3:
|
||||
glRasterPos2f( 250-16+61+42+80,size[3]-13)
|
||||
if XLIMIT.val:
|
||||
xl=xwin
|
||||
else:
|
||||
xl=xlimit
|
||||
|
||||
if MMENU.val==1 or MMENU.val==3:
|
||||
glRasterPos2f( 250-16+61+42+80,size[3]-13)
|
||||
if XLIMIT.val:
|
||||
xl=xwin
|
||||
else:
|
||||
xl=xlimit
|
||||
Text("x :"+"%d"%(xl+2))
|
||||
|
||||
Text("x :"+"%d"%(xl+2))
|
||||
glRasterPos2f(250-16+61+42+65*2,size[3]-13)
|
||||
Text("y :"+"%d"%(y-n0+1))
|
||||
|
||||
glRasterPos2f(250-16+61+42+65*2,size[3]-13)
|
||||
Text("y :"+"%d"%(y-n0+1))
|
||||
TEXT=String("to:", 7 , 278+61 ,size[3]-28 , 213, 13, TEXT.val, 256, "Draw lines")
|
||||
if XLIMIT.val==1:
|
||||
limit='winlimit'
|
||||
else:
|
||||
limit='maxXlimit'
|
||||
XLIMIT=Toggle(limit, 9 , 250-16+61+42 ,size[3]-15 , 60, 13, XLIMIT.val, "to save picture from x max uv limit, or x window max limit")
|
||||
|
||||
TEXT=String("to:", 7 , 278+61 ,size[3]-28 , 213, 13, TEXT.val, 256, "Draw lines")
|
||||
if XLIMIT.val==1:
|
||||
limit='winlimit'
|
||||
else:
|
||||
limit='maxXlimit'
|
||||
XLIMIT=Toggle(limit, 9 , 250-16+61+42 ,size[3]-15 , 60, 13, XLIMIT.val, "to save picture from x max uv limit, or x window max limit")
|
||||
if MMENU.val==2:
|
||||
TDOCMat=Toggle("doc" ,24,250-130+35 ,size[3]-13 , 28, 13, TDOCMat.val)
|
||||
if TDOCMat.val==1:
|
||||
SELMat_list()
|
||||
for t in range(TMATList[0]):
|
||||
glCl3(TMATList[1][t][0],
|
||||
TMATList[1][t][1],
|
||||
TMATList[1][t][2])
|
||||
glRct((293-16+61)+t*20,
|
||||
size[3]-13,
|
||||
(293-16+61)+t*20+20,
|
||||
size[3]-30,)
|
||||
TMATList[2][t]=Toggle("%s"%t , 32+t ,(293-16+61)+t*20 ,size[3]-13 ,20 , 13,TMATList[2][t].val)
|
||||
|
||||
if MMENU.val==2:
|
||||
TDOCMat=Toggle("doc" ,24,250-130+35 ,size[3]-13 , 28, 13, TDOCMat.val)
|
||||
if TDOCMat.val==1:
|
||||
SELMat_list()
|
||||
for t in range(TMATList[0]):
|
||||
glCl3(TMATList[1][t][0],
|
||||
TMATList[1][t][1],
|
||||
TMATList[1][t][2])
|
||||
glRct((293-16+61)+t*20,
|
||||
size[3]-13,
|
||||
(293-16+61)+t*20+20,
|
||||
size[3]-30,)
|
||||
TMATList[2][t]=Toggle("%s"%t , 32+t ,(293-16+61)+t*20 ,size[3]-13 ,20 , 13,TMATList[2][t].val)
|
||||
#else:
|
||||
# save()
|
||||
|
||||
|
||||
if DOCU:
|
||||
Doc(size)
|
||||
|
||||
def event(evt, val):
|
||||
global mouse_x, x, mouse_y, y, LC
|
||||
global LCOLOR, DOCU, MENU, SAVE
|
||||
global mouse_xr,sel, ANC, X,Y ,NSIZE
|
||||
global mouse_yr, POS, XY,size, TRANSP,EMPTY
|
||||
|
||||
def event(evt, val):
|
||||
if (evt== QKEY and not val): Exit()
|
||||
if (evt== QKEY or evt== ESCKEY and not val):
|
||||
Exit()
|
||||
elif (evt== TKEY and not val):
|
||||
TRANSP=abs(TRANSP-1)
|
||||
elif (evt== EKEY and not val):
|
||||
EMPTY=abs(EMPTY-1)
|
||||
elif (evt== MKEY and not val):
|
||||
MENU=abs(MENU-1)
|
||||
elif (evt== SKEY and not val):
|
||||
SAVE=abs(MENU-1)
|
||||
elif (evt== WKEY and not val):
|
||||
LC=1.0
|
||||
LCOLOR.val=64
|
||||
elif (evt== BKEY and not val):
|
||||
LC=0.0
|
||||
LCOLOR.val=1
|
||||
elif (evt==LEFTARROWKEY and not val) :
|
||||
POS[0]-=10
|
||||
elif (evt==RIGHTARROWKEY and not val) :
|
||||
POS[0]+=10
|
||||
elif (evt==UPARROWKEY and not val) :
|
||||
POS[1]+=10
|
||||
elif (evt==DOWNARROWKEY and not val) :
|
||||
POS[1]-=10
|
||||
elif (evt==PADMINUS and not val) :
|
||||
NSIZE.val-=0.1
|
||||
elif (evt==PADPLUSKEY and not val) :
|
||||
NSIZE.val+=0.1
|
||||
elif (evt==LKEY and not val) :
|
||||
LINE.val=abs(LINE.val-1)
|
||||
elif (evt==HOMEKEY and not val) :
|
||||
NSIZE.val=1.0
|
||||
POS=[0,0]
|
||||
elif (evt==DKEY and not val) :
|
||||
DOCU=abs(DOCU-1)
|
||||
elif (evt == MOUSEX): mouse_xr = val
|
||||
elif (evt == MOUSEY): mouse_yr = val
|
||||
|
||||
elif (evt == RIGHTMOUSE and val):
|
||||
if (sel==0 ) :
|
||||
ANC=[(mouse_xr-size[0])-POS[0],(mouse_yr-size[1])-POS[1]]
|
||||
sel=1
|
||||
elif (evt == RIGHTMOUSE and not val):
|
||||
sel=0
|
||||
ANC=0,0
|
||||
Redraw(1)
|
||||
|
||||
|
||||
def bevent(evt):
|
||||
global LINE,NSIZE,n0,x0,y0,y,TEXT, loc2
|
||||
global TMATList, selmatlist, TDOCMat,XLIMIT
|
||||
global xlimit
|
||||
global xlimit,LCOLOR,LC,SAVE
|
||||
|
||||
if (evt== 1):
|
||||
Exit()
|
||||
@ -474,11 +656,11 @@ def bevent(evt):
|
||||
|
||||
elif (evt== 6):
|
||||
if XLIMIT.val==1:
|
||||
xi=xwin
|
||||
xi=xwin
|
||||
save(x0,y0,xi+2,int(y-n0))
|
||||
else:
|
||||
xi=xlimit
|
||||
|
||||
save(x0,y0,xi+2,int(y*NSIZE.val-n0))
|
||||
xi=xlimit
|
||||
save(x0,y0,xi+2,int(y*NSIZE.val)-n0)
|
||||
|
||||
elif (evt== 7):
|
||||
if exist(TEXT.val):
|
||||
@ -487,7 +669,10 @@ def bevent(evt):
|
||||
TEXT.val=loc2
|
||||
|
||||
elif (evt== 24) or (evt in [32,33,34,35,36,37,38,39,40,41,42,43,44]):
|
||||
SELMat_list()
|
||||
SELMat_list()
|
||||
|
||||
elif (evt== 50):
|
||||
LC=float(LCOLOR.val)/64.0
|
||||
|
||||
|
||||
Blender.Redraw()
|
@ -322,28 +322,6 @@ def write(filename):
|
||||
Blender.Draw.PupMenu("Wings Export error|Unable to generate Edge Table for mesh")
|
||||
return
|
||||
|
||||
|
||||
# if 0:
|
||||
# import Tkinter, tkMessageBox
|
||||
# sys.argv=['wings.pyo','wings.pyc'] # ?
|
||||
#
|
||||
# #Tkinter.NoDefaultRoot()
|
||||
# win1 = Tkinter.Tk()
|
||||
# ans = tkMessageBox.showerror("Error", message)
|
||||
# win1.pack()
|
||||
# print ans
|
||||
# if ans:
|
||||
# win1.quit()
|
||||
# win1.mainloop()
|
||||
#
|
||||
# else:
|
||||
# from Tkinter import Label
|
||||
# sys.argv = 'wings.py'
|
||||
# widget = Label(None, text=message)
|
||||
# #widget.title("Error")
|
||||
# widget.pack()
|
||||
# widget.mainloop()
|
||||
|
||||
data = generate_data(objname, edge_table, mesh)
|
||||
dsize = len(data)
|
||||
Blender.Window.DrawProgressBar(0.98, "Compressing Data")
|
||||
|
@ -423,33 +423,6 @@ static PyObject *Buffer_repr(PyObject *self)
|
||||
return repr;
|
||||
}
|
||||
|
||||
/* Not a macro so that buffer dimensions are checked.
|
||||
* XXX There are other places where buffers are used, so a new macro to handle
|
||||
* all such cases may be a good idea. */
|
||||
static PyObject *Method_DrawPixels (PyObject *self, PyObject *args)
|
||||
{
|
||||
int bgl_var1, bgl_var2, bgl_var3, bgl_var4;
|
||||
Buffer *bgl_buffer5;
|
||||
int i, bufsize;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "i" "i" "i" "i" "O!",
|
||||
&bgl_var1, &bgl_var2, &bgl_var3, &bgl_var4, &buffer_Type, &bgl_buffer5))
|
||||
return NULL;
|
||||
|
||||
bufsize = 1;
|
||||
for (i = 0; i < bgl_buffer5->ndimensions; i++)
|
||||
bufsize *= bgl_buffer5->dimensions[i];
|
||||
|
||||
if (bgl_var1*bgl_var2 > bufsize)
|
||||
return EXPP_ReturnPyObjError(PyExc_AttributeError,
|
||||
"pixel buffer size can't be smaller than drawing rect area");
|
||||
|
||||
glDrawPixels (bgl_var1, bgl_var2, bgl_var3, bgl_var4,
|
||||
(bgl_buffer5)->buf.asvoid);
|
||||
|
||||
return EXPP_incr_ret(Py_None);
|
||||
}
|
||||
|
||||
|
||||
BGL_Wrap(2, Accum, void, (GLenum, GLfloat))
|
||||
BGL_Wrap(2, AlphaFunc, void, (GLenum, GLclampf))
|
||||
@ -511,7 +484,7 @@ BGL_Wrap(1, DepthMask, void, (GLboolean))
|
||||
BGL_Wrap(2, DepthRange, void, (GLclampd, GLclampd))
|
||||
BGL_Wrap(1, Disable, void, (GLenum))
|
||||
BGL_Wrap(1, DrawBuffer, void, (GLenum))
|
||||
/*BGL_Wrap(5, DrawPixels, void, (GLsizei, GLsizei, GLenum, GLenum, GLvoidP))*/
|
||||
BGL_Wrap(5, DrawPixels, void, (GLsizei, GLsizei, GLenum, GLenum, GLvoidP))
|
||||
BGL_Wrap(1, EdgeFlag, void, (GLboolean))
|
||||
BGL_Wrap(1, EdgeFlagv, void, (GLbooleanP))
|
||||
BGL_Wrap(1, Enable, void, (GLenum))
|
||||
|
Loading…
Reference in New Issue
Block a user