Module nif_common
[hide private]
[frames] | no frames]

Source Code for Module nif_common

   1  """Common functions for the Blender nif import and export scripts.""" 
   2   
   3  __version__ = "2.5.0" 
   4  __requiredpyffiversion__ = "2.0.4" 
   5  __requiredblenderversion__ = "245" 
   6   
   7  # ***** BEGIN LICENSE BLOCK ***** 
   8  #  
   9  # BSD License 
  10  #  
  11  # Copyright (c) 2005-2009, NIF File Format Library and Tools 
  12  # All rights reserved. 
  13  #  
  14  # Redistribution and use in source and binary forms, with or without 
  15  # modification, are permitted provided that the following conditions 
  16  # are met: 
  17  # 1. Redistributions of source code must retain the above copyright 
  18  #    notice, this list of conditions and the following disclaimer. 
  19  # 2. Redistributions in binary form must reproduce the above copyright 
  20  #    notice, this list of conditions and the following disclaimer in the 
  21  #    documentation and/or other materials provided with the distribution. 
  22  # 3. The name of the NIF File Format Library and Tools project may not be 
  23  #    used to endorse or promote products derived from this software 
  24  #    without specific prior written permission. 
  25  #  
  26  # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 
  27  # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
  28  # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
  29  # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 
  30  # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
  31  # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
  32  # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
  33  # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
  34  # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 
  35  # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
  36  # 
  37  # ***** END LICENCE BLOCK ***** 
  38   
  39  # utility functions 
  40       
41 -def cmp_versions(version1, version2):
42 """Compare version strings.""" 43 def version_intlist(version): 44 """Convert version string to list of integers.""" 45 return [int(x) for x in version.__str__().split(".")]
46 return cmp(version_intlist(version1), version_intlist(version2)) 47 48 # things to do on import and export 49 50 # check Blender version 51 52 import Blender 53 __blenderversion__ = Blender.Get('version') 54 55 if cmp_versions(__blenderversion__, __requiredblenderversion__) == -1: 56 print("""-------------------------- 57 ERROR\nThis script requires Blender %s or higher. 58 It seems that you have an older version installed (%s). 59 Get a newer version at http://www.blender.org/ 60 --------------------------"""%(__requiredblenderversion__, __blenderversion__)) 61 Blender.Draw.PupMenu("ERROR%t|Blender outdated, check console for details") 62 raise ImportError 63 64 # check if PyFFI is installed and import NifFormat 65 66 try: 67 from pyffi import __version__ as __pyffiversion__ 68 except ImportError: 69 print("""-------------------------- 70 ERROR\nThis script requires the Python File Format Interface (PyFFI). 71 Make sure that PyFFI resides in your Python path or in your Blender scripts folder. 72 If you do not have it: http://pyffi.sourceforge.net/ 73 --------------------------""") 74 Blender.Draw.PupMenu("ERROR%t|PyFFI not found, check console for details") 75 raise 76 77 # check PyFFI version 78 79 if cmp_versions(__pyffiversion__, __requiredpyffiversion__) == -1: 80 print("""-------------------------- 81 ERROR\nThis script requires Python File Format Interface %s or higher. 82 It seems that you have an older version installed (%s). 83 Get a newer version at http://pyffi.sourceforge.net/ 84 --------------------------"""%(__requiredpyffiversion__, __pyffiversion__)) 85 Blender.Draw.PupMenu("ERROR%t|PyFFI outdated, check console for details") 86 raise ImportError 87 88 # import PyFFI format classes 89 90 from pyffi.formats.nif import NifFormat 91 from pyffi.formats.egm import EgmFormat 92 93 # other imports 94 95 from Blender import Draw, Registry 96 import logging 97 import sys 98 import os 99
100 -def init_loggers():
101 """Set up loggers.""" 102 niftoolslogger = logging.getLogger("niftools") 103 niftoolslogger.setLevel(logging.WARNING) 104 pyffilogger = logging.getLogger("pyffi") 105 pyffilogger.setLevel(logging.WARNING) 106 loghandler = logging.StreamHandler() 107 loghandler.setLevel(logging.DEBUG) 108 logformatter = logging.Formatter("%(name)s:%(levelname)s:%(message)s") 109 loghandler.setFormatter(logformatter) 110 niftoolslogger.addHandler(loghandler) 111 pyffilogger.addHandler(loghandler)
112 113 # set up the loggers: call it as a function to avoid polluting namespace 114 init_loggers() 115
116 -class NifImportExport:
117 """Abstract base class for import and export. Contains utility functions 118 that are commonly used in both import and export.""" 119 120 EXTRA_SHADER_TEXTURES = [ 121 "EnvironmentMapIndex", 122 "NormalMapIndex", 123 "SpecularIntensityIndex", 124 "EnvironmentIntensityIndex", 125 "LightCubeMapIndex", 126 "ShadowTextureIndex"] 127 """Names (ordered by default index) of shader texture slots for 128 Sid Meier's Railroads and similar games. 129 """ 130 131 USED_EXTRA_SHADER_TEXTURES = { 132 "Sid Meier's Railroads": (3, 0, 4, 1, 5, 2), 133 "Civilization IV": (3, 0, 1, 2)} 134 """The default ordering of the extra data blocks for different games.""" 135 136 progress_bar = 0 137 """Level of the progress bar.""" 138
139 - def msg_progress(self, message, progbar=None):
140 """Message wrapper for the Blender progress bar.""" 141 # update progress bar level 142 if progbar is None: 143 if self.progress_bar > 0.89: 144 # reset progress bar 145 self.progress_bar = 0 146 Blender.Window.DrawProgressBar(0, message) 147 self.progress_bar += 0.1 148 else: 149 self.progress_bar = progbar 150 # draw the progress bar 151 Blender.Window.DrawProgressBar(self.progress_bar, message)
152
153 - def get_bone_name_for_blender(self, name):
154 """Convert a bone name to a name that can be used by Blender: turns 155 'Bip01 R xxx' into 'Bip01 xxx.R', and similar for L. 156 157 @param name: The bone name as in the nif file. 158 @type name: C{str} 159 @return: Bone name in Blender convention. 160 @rtype: C{str} 161 """ 162 if name.startswith("Bip01 L "): 163 return "Bip01 " + name[8:] + ".L" 164 elif name.startswith("Bip01 R "): 165 return "Bip01 " + name[8:] + ".R" 166 return name
167
168 - def get_bone_name_for_nif(self, name):
169 """Convert a bone name to a name that can be used by the nif file: 170 turns 'Bip01 xxx.R' into 'Bip01 R xxx', and similar for L. 171 172 @param name: The bone name as in Blender. 173 @type name: C{str} 174 @return: Bone name in nif convention. 175 @rtype: C{str} 176 """ 177 if name.startswith("Bip01 "): 178 if name.endswith(".L"): 179 return "Bip01 L " + name[6:-2] 180 elif name.endswith(".R"): 181 return "Bip01 R " + name[6:-2] 182 return name
183
184 - def get_extend_from_flags(self, flags):
185 if flags & 6 == 4: # 0b100 186 return Blender.IpoCurve.ExtendTypes.CONST 187 elif flags & 6 == 0: # 0b000 188 return Blender.IpoCurve.ExtendTypes.CYCLIC 189 190 self.logger.warning( 191 "Unsupported cycle mode in nif, using clamped.") 192 return Blender.IpoCurve.ExtendTypes.CONST
193
194 - def get_flags_from_extend(self, extend):
195 if extend == Blender.IpoCurve.ExtendTypes.CONST: 196 return 4 # 0b100 197 elif extend == Blender.IpoCurve.ExtendTypes.CYCLIC: 198 return 0 199 200 self.logger.warning( 201 "Unsupported extend type in blend, using clamped.") 202 return 4
203
204 -class NifConfig:
205 """Class which handles configuration of nif import and export in Blender. 206 207 Important: keep every instance of this class in a global variable 208 (otherwise gui elements might go out of skope which will crash 209 Blender).""" 210 # class global constants 211 WELCOME_MESSAGE = 'Blender NIF Scripts %s (running on Blender %s, PyFFI %s)'%(__version__, __blenderversion__, __pyffiversion__) 212 CONFIG_NAME = "nifscripts" # name of the config file 213 TARGET_IMPORT = 0 # config target value when importing 214 TARGET_EXPORT = 1 # config target value when exporting 215 # GUI stuff 216 XORIGIN = 50 # x coordinate of origin 217 XCOLUMNSKIP = 390 # width of a column 218 XCOLUMNSEP = 10 # width of the column separator 219 YORIGIN = -40 # y coordinate of origin relative to Blender.Window.GetAreaSize()[1] 220 YLINESKIP = 20 # height of a line 221 YLINESEP = 10 # height of a line separator 222 # the DEFAULTS dict defines the valid config variables, default values, 223 # and their type 224 # IMPORTANT: don't start dictionary keys with an underscore 225 # the Registry module doesn't like that, apparently 226 DEFAULTS = dict( 227 IMPORT_FILE = Blender.sys.join( 228 Blender.sys.dirname(Blender.sys.progname), "import.nif"), 229 EXPORT_FILE = Blender.sys.join( 230 Blender.sys.dirname(Blender.sys.progname), "export.nif"), 231 IMPORT_REALIGN_BONES = 1, # 0 = no, 1 = tail, 2 = tail+rotation 232 IMPORT_ANIMATION = True, 233 IMPORT_SCALE_CORRECTION = 0.1, 234 EXPORT_SCALE_CORRECTION = 10.0, # 1/import scale correction 235 IMPORT_TEXTURE_PATH = [], 236 EXPORT_FLATTENSKIN = False, 237 EXPORT_VERSION = 'Oblivion', 238 EPSILON = 0.005, # used for checking equality with floats 239 LOG_LEVEL = logging.WARNING, # log level 240 IMPORT_SKELETON = 0, # 0 = normal import, 1 = import file as skeleton, 2 = import mesh and attach to skeleton 241 IMPORT_KEYFRAMEFILE = '', # keyframe file for animations 242 IMPORT_EGMFILE = '', # FaceGen EGM file for morphs 243 IMPORT_EGMANIM = True, # create FaceGen EGM animation curves 244 IMPORT_EGMANIMSCALE = 1.0, # scale of FaceGen EGM animation curves 245 EXPORT_ANIMATION = 0, # export everything (1=geometry only, 2=animation only) 246 EXPORT_ANIMSEQUENCENAME = '', # sequence name of the kf file 247 EXPORT_FORCEDDS = True, # force dds extension on texture files 248 EXPORT_SKINPARTITION = True, # generate skin partition 249 EXPORT_BONESPERVERTEX = 4, 250 EXPORT_BONESPERPARTITION = 18, 251 EXPORT_PADBONES = False, 252 EXPORT_STRIPIFY = True, 253 EXPORT_STITCHSTRIPS = False, 254 EXPORT_SMOOTHOBJECTSEAMS = True, 255 IMPORT_MERGESKELETONROOTS = True, 256 IMPORT_SENDGEOMETRIESTOBINDPOS = True, 257 IMPORT_SENDDETACHEDGEOMETRIESTONODEPOS = True, 258 IMPORT_SENDBONESTOBINDPOS = True, 259 IMPORT_APPLYSKINDEFORM = False, 260 IMPORT_EXTRANODES = True, 261 EXPORT_BHKLISTSHAPE = False, 262 EXPORT_OB_BSXFLAGS = 2, 263 EXPORT_OB_MASS = 10.0, 264 EXPORT_OB_SOLID = True, 265 EXPORT_OB_MOTIONSYSTEM = 7, # MO_SYS_FIXED 266 EXPORT_OB_UNKNOWNBYTE1 = 1, 267 EXPORT_OB_UNKNOWNBYTE2 = 1, 268 EXPORT_OB_QUALITYTYPE = 1, # MO_QUAL_FIXED 269 EXPORT_OB_WIND = 0, 270 EXPORT_OB_LAYER = 1, # static 271 EXPORT_OB_MATERIAL = 9, # wood 272 EXPORT_OB_MALLEABLECONSTRAINT = False, # use malleable constraint for ragdoll and hinge 273 EXPORT_OB_PRN = "NONE", # determines bone where to attach weapon 274 EXPORT_FO3_SF_ZBUF = True, # use these shader flags? 275 EXPORT_FO3_SF_SMAP = False, 276 EXPORT_FO3_SF_SFRU = False, 277 EXPORT_FO3_SF_WINDOW_ENVMAP = False, 278 EXPORT_FO3_SF_EMPT = True, 279 EXPORT_FO3_SF_UN31 = True, 280 EXPORT_FO3_FADENODE = False, 281 EXPORT_FO3_SHADER_TYPE = 1, # shader_default 282 EXPORT_FO3_BODYPARTS = True, 283 EXPORT_MW_NIFXNIFKF = False, 284 EXPORT_EXTRA_SHADER_TEXTURES = True, 285 PROFILE = '', # name of file where Python profiler dumps the profile; set to empty string to turn off profiling 286 IMPORT_EXPORTEMBEDDEDTEXTURES = False, 287 EXPORT_OPTIMIZE_MATERIALS = True, 288 IMPORT_COMBINESHAPES = True) 289
290 - def __init__(self):
291 """Initialize and load configuration.""" 292 # clears the console window 293 if sys.platform in ('linux-i386','linux2'): 294 os.system("clear") 295 elif sys.platform in ('win32','dos','ms-dos'): 296 os.system("cls") 297 298 # print scripts info 299 print self.WELCOME_MESSAGE 300 301 # initialize all instance variables 302 self.guiElements = {} # dictionary of gui elements (buttons, strings, sliders, ...) 303 self.guiEvents = [] # list of events 304 self.guiEventIds = {} # dictionary of event ids 305 self.config = {} # configuration dictionary 306 self.target = None # import or export 307 self.callback = None # function to call when config gui is done 308 self.texpathIndex = 0 309 self.texpathCurrent = '' 310 311 # reset GUI coordinates 312 self.xPos = self.XORIGIN 313 self.yPos = self.YORIGIN + Blender.Window.GetAreaSize()[1] 314 315 # load configuration 316 self.load()
317
318 - def run(self, target, filename, callback):
319 """Run the config gui.""" 320 self.target = target # import or export 321 self.callback = callback # function to call when config gui is done 322 323 # save file name 324 # (the key where to store the file name depends 325 # on the target) 326 if self.target == self.TARGET_IMPORT: 327 self.config["IMPORT_FILE"] = filename 328 elif self.target == self.TARGET_EXPORT: 329 self.config["EXPORT_FILE"] = filename 330 self.save() 331 332 # prepare and run gui 333 self.texpathIndex = 0 334 self.updateTexpathCurrent() 335 Draw.Register(self.guiDraw, self.guiEvent, self.guiButtonEvent)
336
337 - def save(self):
338 """Save and validate configuration to Blender registry.""" 339 Registry.SetKey(self.CONFIG_NAME, self.config, True) 340 self.load() # for validation
341
342 - def load(self):
343 """Load the configuration stored in the Blender registry and checks 344 configuration for incompatible values. 345 """ 346 # copy defaults 347 self.config = dict(**self.DEFAULTS) 348 # read configuration 349 savedconfig = Blender.Registry.GetKey(self.CONFIG_NAME, True) 350 # port config keys from old versions to current version 351 try: 352 self.config["IMPORT_TEXTURE_PATH"] = savedconfig["TEXTURE_SEARCH_PATH"] 353 except: 354 pass 355 try: 356 self.config["IMPORT_FILE"] = Blender.sys.join( 357 savedconfig["NIF_IMPORT_PATH"], savedconfig["NIF_IMPORT_FILE"]) 358 except: 359 pass 360 try: 361 self.config["EXPORT_FILE"] = savedconfig["NIF_EXPORT_FILE"] 362 except: 363 pass 364 try: 365 self.config["IMPORT_REALIGN_BONES"] = savedconfig["REALIGN_BONES"] 366 except: 367 pass 368 try: 369 if self.config["IMPORT_REALIGN_BONES"] == True: 370 self.config["IMPORT_REALIGN_BONES"] = 1 371 elif self.config["IMPORT_REALIGN_BONES"] == False: 372 self.config["IMPORT_REALIGN_BONES"] = 0 373 except: 374 pass 375 try: 376 if savedconfig["IMPORT_SKELETON"] == True: 377 self.config["IMPORT_SKELETON"] = 1 378 elif savedconfig["IMPORT_SKELETON"] == False: 379 self.config["IMPORT_SKELETON"] = 0 380 except: 381 pass 382 # merge configuration with defaults 383 if savedconfig: 384 for key, val in self.DEFAULTS.iteritems(): 385 try: 386 savedval = savedconfig[key] 387 except KeyError: 388 pass 389 else: 390 if isinstance(savedval, val.__class__): 391 self.config[key] = savedval 392 # store configuration 393 Blender.Registry.SetKey(self.CONFIG_NAME, self.config, True) 394 # special case: set log level here 395 self.updateLogLevel("LOG_LEVEL", self.config["LOG_LEVEL"])
396
397 - def eventId(self, event_name):
398 """Return event id from event name, and register event if it is new.""" 399 try: 400 event_id = self.guiEventIds[event_name] 401 except KeyError: 402 event_id = len(self.guiEvents) 403 self.guiEventIds[event_name] = event_id 404 self.guiEvents.append(event_name) 405 if event_id >= 16383: 406 raise RuntimeError("Maximum number of events exceeded") 407 return event_id
408
409 - def drawYSep(self):
410 """Vertical skip.""" 411 self.yPos -= self.YLINESEP
412
413 - def drawNextColumn(self):
414 """Start a new column.""" 415 self.xPos += self.XCOLUMNSKIP + self.XCOLUMNSEP 416 self.yPos = self.YORIGIN + Blender.Window.GetAreaSize()[1]
417
418 - def drawSlider( 419 self, text, event_name, min_val, max_val, callback, val = None, 420 num_items = 1, item = 0):
421 """Draw a slider.""" 422 if val is None: 423 val = self.config[event_name] 424 width = self.XCOLUMNSKIP//num_items 425 self.guiElements[event_name] = Draw.Slider( 426 text, 427 self.eventId(event_name), 428 self.xPos + item*width, self.yPos, width, self.YLINESKIP, 429 val, min_val, max_val, 430 0, # realtime 431 "", # tooltip, 432 callback) 433 if item + 1 == num_items: 434 self.yPos -= self.YLINESKIP
435
436 - def drawLabel(self, text, event_name, num_items = 1, item = 0):
437 """Draw a line of text.""" 438 width = self.XCOLUMNSKIP//num_items 439 self.guiElements[event_name] = Draw.Label( 440 text, 441 self.xPos + item*width, self.yPos, width, self.YLINESKIP) 442 if item + 1 == num_items: 443 self.yPos -= self.YLINESKIP
444
445 - def drawList(self, text, event_name_prefix, val):
446 """Create elements to select a list of things. 447 448 Registers events PREFIX_ITEM, PREFIX_PREV, PREFIX_NEXT, PREFIX_REMOVE 449 and PREFIX_ADD.""" 450 self.guiElements["%s_ITEM"%event_name_prefix] = Draw.String( 451 text, 452 self.eventId("%s_ITEM"%event_name_prefix), 453 self.xPos, self.yPos, self.XCOLUMNSKIP-90, self.YLINESKIP, 454 val, 255) 455 self.guiElements["%s_PREV"%event_name_prefix] = Draw.PushButton( 456 '<', 457 self.eventId("%s_PREV"%event_name_prefix), 458 self.xPos+self.XCOLUMNSKIP-90, self.yPos, 20, self.YLINESKIP) 459 self.guiElements["%s_NEXT"%event_name_prefix] = Draw.PushButton( 460 '>', 461 self.eventId("%s_NEXT"%event_name_prefix), 462 self.xPos+self.XCOLUMNSKIP-70, self.yPos, 20, self.YLINESKIP) 463 self.guiElements["%s_REMOVE"%event_name_prefix] = Draw.PushButton( 464 'X', 465 self.eventId("%s_REMOVE"%event_name_prefix), 466 self.xPos+self.XCOLUMNSKIP-50, self.yPos, 20, self.YLINESKIP) 467 self.guiElements["%s_ADD"%event_name_prefix] = Draw.PushButton( 468 '...', 469 self.eventId("%s_ADD"%event_name_prefix), 470 self.xPos+self.XCOLUMNSKIP-30, self.yPos, 30, self.YLINESKIP) 471 self.yPos -= self.YLINESKIP
472
473 - def drawToggle(self, text, event_name, val = None, num_items = 1, item = 0):
474 """Draw a toggle button.""" 475 if val == None: 476 val = self.config[event_name] 477 width = self.XCOLUMNSKIP//num_items 478 self.guiElements[event_name] = Draw.Toggle( 479 text, 480 self.eventId(event_name), 481 self.xPos + item*width, self.yPos, width, self.YLINESKIP, 482 val) 483 if item + 1 == num_items: 484 self.yPos -= self.YLINESKIP
485
486 - def drawPushButton(self, text, event_name, num_items = 1, item = 0):
487 """Draw a push button.""" 488 width = self.XCOLUMNSKIP//num_items 489 self.guiElements[event_name] = Draw.PushButton( 490 text, 491 self.eventId(event_name), 492 self.xPos + item*width, self.yPos, width, self.YLINESKIP) 493 if item + 1 == num_items: 494 self.yPos -= self.YLINESKIP
495
496 - def drawNumber( 497 self, text, event_name, min_val, max_val, callback, val = None, 498 num_items = 1, item = 0):
499 """Draw an input widget for numbers.""" 500 if val is None: 501 val = self.config[event_name] 502 width = self.XCOLUMNSKIP//num_items 503 self.guiElements[event_name] = Draw.Number( 504 text, 505 self.eventId(event_name), 506 self.xPos + item*width, self.yPos, width, self.YLINESKIP, 507 val, 508 min_val, max_val, 509 "", # tooltip 510 callback) 511 if item + 1 == num_items: 512 self.yPos -= self.YLINESKIP
513
514 - def drawFileBrowse(self, text, event_name_prefix, val = None):
515 """Create elements to select a file. 516 517 Registers events PREFIX_ITEM, PREFIX_REMOVE, PREFIX_ADD.""" 518 if val is None: 519 val = self.config[event_name_prefix] 520 self.guiElements["%s_ITEM"%event_name_prefix] = Draw.String( 521 text, 522 self.eventId("%s_ITEM"%event_name_prefix), 523 self.xPos, self.yPos, self.XCOLUMNSKIP-50, self.YLINESKIP, 524 val, 255) 525 self.guiElements["%s_REMOVE"%event_name_prefix] = Draw.PushButton( 526 'X', 527 self.eventId("%s_REMOVE"%event_name_prefix), 528 self.xPos+self.XCOLUMNSKIP-50, self.yPos, 20, self.YLINESKIP) 529 self.guiElements["%s_ADD"%event_name_prefix] = Draw.PushButton( 530 '...', 531 self.eventId("%s_ADD"%event_name_prefix), 532 self.xPos+self.XCOLUMNSKIP-30, self.yPos, 30, self.YLINESKIP) 533 self.yPos -= self.YLINESKIP
534
535 - def drawString(self, text, event_name, max_length, callback, val = None, 536 num_items = 1, item = 0):
537 """Create elements to input a string.""" 538 if val is None: 539 val = self.config[event_name] 540 width = self.XCOLUMNSKIP//num_items 541 self.guiElements[event_name] = Draw.String( 542 text, 543 self.eventId(event_name), 544 self.xPos + item*width, self.yPos, width, self.YLINESKIP, 545 val, 546 max_length, 547 "", # tooltip 548 callback) 549 if item + 1 == num_items: 550 self.yPos -= self.YLINESKIP
551
552 - def guiDraw(self):
553 """Draw config GUI.""" 554 # reset position 555 self.xPos = self.XORIGIN 556 self.yPos = self.YORIGIN + Blender.Window.GetAreaSize()[1] 557 558 # common options 559 self.drawLabel( 560 text = self.WELCOME_MESSAGE, 561 event_name = "LABEL_WELCOME_MESSAGE") 562 self.drawYSep() 563 564 self.drawNumber( 565 text = "Log Level", 566 event_name = "LOG_LEVEL", 567 min_val = 0, max_val = 99, 568 callback = self.updateLogLevel, 569 num_items = 4, item = 0) 570 self.drawPushButton( 571 text = "Warn", 572 event_name = "LOG_LEVEL_WARN", 573 num_items = 4, item = 1) 574 self.drawPushButton( 575 text = "Info", 576 event_name = "LOG_LEVEL_INFO", 577 num_items = 4, item = 2) 578 self.drawPushButton( 579 text = "Debug", 580 event_name = "LOG_LEVEL_DEBUG", 581 num_items = 4, item = 3) 582 self.drawYSep() 583 584 self.drawSlider( 585 text = "Scale Correction: ", 586 event_name = "SCALE_CORRECTION", 587 val = self.config["EXPORT_SCALE_CORRECTION"], 588 min_val = 0.01, max_val = 100.0, 589 callback = self.updateScale) 590 self.drawYSep() 591 592 # import-only options 593 if self.target == self.TARGET_IMPORT: 594 self.drawLabel( 595 text = "Texture Search Paths:", 596 event_name = "TEXPATH_TEXT") 597 self.drawList( 598 text = "", 599 event_name_prefix = "TEXPATH", 600 val = self.texpathCurrent) 601 self.drawYSep() 602 603 self.drawToggle( 604 text = "Import Animation", 605 event_name = "IMPORT_ANIMATION") 606 self.drawYSep() 607 608 self.drawToggle( 609 text = "Import Extra Nodes", 610 event_name = "IMPORT_EXTRANODES") 611 self.drawYSep() 612 613 self.drawToggle( 614 text = "Import Skeleton Only + Parent Selected", 615 event_name = "IMPORT_SKELETON_1", 616 val = (self.config["IMPORT_SKELETON"] == 1)) 617 self.drawToggle( 618 text = "Import Geometry Only + Parent To Selected Armature", 619 event_name = "IMPORT_SKELETON_2", 620 val = (self.config["IMPORT_SKELETON"] == 2)) 621 self.drawYSep() 622 623 self.drawToggle( 624 text = "Save Embedded Textures As DDS", 625 event_name = "IMPORT_EXPORTEMBEDDEDTEXTURES") 626 self.drawYSep() 627 628 self.drawToggle( 629 text = "Combine Multi-Material Shapes Into Single Mesh", 630 event_name = "IMPORT_COMBINESHAPES") 631 self.drawYSep() 632 633 self.drawLabel( 634 text = "Keyframe File:", 635 event_name = "IMPORT_KEYFRAMEFILE_TEXT") 636 self.drawFileBrowse( 637 text = "", 638 event_name_prefix = "IMPORT_KEYFRAMEFILE") 639 self.drawYSep() 640 641 self.drawLabel( 642 text = "FaceGen EGM File:", 643 event_name = "IMPORT_EGMFILE_TEXT") 644 self.drawFileBrowse( 645 text = "", 646 event_name_prefix = "IMPORT_EGMFILE") 647 self.drawToggle( 648 text="Animate", 649 event_name="IMPORT_EGMANIM", 650 num_items=2, item=0) 651 self.drawSlider( 652 text="Scale: ", 653 event_name="IMPORT_EGMANIMSCALE", 654 val=self.config["IMPORT_EGMANIMSCALE"], 655 min_val=0.01, max_val=100.0, 656 callback=self.updateEgmAnimScale, 657 num_items=2, item=1) 658 self.drawYSep() 659 660 self.drawPushButton( 661 text = "Restore Default Settings", 662 event_name = "IMPORT_SETTINGS_DEFAULT") 663 self.drawYSep() 664 665 self.drawLabel( 666 text = "... and if skinning fails with default settings:", 667 event_name = "IMPORT_SETTINGS_SKINNING_TEXT") 668 self.drawPushButton( 669 text = "Use The Force Luke", 670 event_name = "IMPORT_SETTINGS_SKINNING") 671 self.drawYSep() 672 673 # export-only options 674 if self.target == self.TARGET_EXPORT: 675 self.drawToggle( 676 text = "Export Geometry + Animation (.nif)", 677 event_name = "EXPORT_ANIMATION_0", 678 val = ((self.config["EXPORT_ANIMATION"] == 0) 679 or self.config["EXPORT_MW_NIFXNIFKF"])) 680 self.drawToggle( 681 text = "Export Geometry Only (.nif)", 682 event_name = "EXPORT_ANIMATION_1", 683 val = ((self.config["EXPORT_ANIMATION"] == 1) 684 or self.config["EXPORT_MW_NIFXNIFKF"])) 685 self.drawToggle( 686 text = "Export Animation Only (.kf)", 687 event_name = "EXPORT_ANIMATION_2", 688 val = ((self.config["EXPORT_ANIMATION"] == 2) 689 or self.config["EXPORT_MW_NIFXNIFKF"])) 690 self.drawYSep() 691 692 self.drawString( 693 text = "Anim Seq Name: ", 694 event_name = "EXPORT_ANIMSEQUENCENAME", 695 max_length = 128, 696 callback = self.updateAnimSequenceName) 697 self.drawYSep() 698 699 self.drawToggle( 700 text = "Force DDS Extension", 701 event_name = "EXPORT_FORCEDDS") 702 self.drawYSep() 703 704 self.drawToggle( 705 text = "Stripify Geometries", 706 event_name = "EXPORT_STRIPIFY", 707 num_items = 2, item = 0) 708 self.drawToggle( 709 text = "Stitch Strips", 710 event_name = "EXPORT_STITCHSTRIPS", 711 num_items = 2, item = 1) 712 self.drawYSep() 713 714 self.drawToggle( 715 text = "Smoothen Inter-Object Seams", 716 event_name = "EXPORT_SMOOTHOBJECTSEAMS") 717 self.drawYSep() 718 719 self.drawToggle( 720 text = "Flatten Skin", 721 event_name = "EXPORT_FLATTENSKIN") 722 self.drawToggle( 723 text = "Export Skin Partition", 724 event_name = "EXPORT_SKINPARTITION", 725 num_items = 3, item = 0) 726 self.drawToggle( 727 text = "Pad & Sort Bones", 728 event_name = "EXPORT_PADBONES", 729 num_items = 3, item = 1) 730 self.drawNumber( 731 text = "Max Bones", 732 event_name = "EXPORT_BONESPERPARTITION", 733 min_val = 4, max_val = 18, 734 callback = self.updateBonesPerPartition, 735 num_items = 3, item = 2) 736 self.drawYSep() 737 738 self.drawToggle( 739 text = "Combine Materials to Increase Performance", 740 event_name = "EXPORT_OPTIMIZE_MATERIALS") 741 self.drawYSep() 742 743 games_list = sorted(filter(lambda x: x != '?', NifFormat.games.keys())) 744 versions_list = sorted(NifFormat.versions.keys(), key=lambda x: NifFormat.versions[x]) 745 V = self.xPos 746 H = HH = self.yPos 747 j = 0 748 MAXJ = 7 749 for i, game in enumerate(games_list): 750 if j >= MAXJ: 751 H = HH 752 j = 0 753 V += 150 754 state = (self.config["EXPORT_VERSION"] == game) 755 self.guiElements["GAME_%s"%game.upper()] = Draw.Toggle(game, self.eventId("GAME_%s"%game), V, H-j*20, 150, 20, state) 756 j += 1 757 j = 0 758 V += 160 759 for i, version in enumerate(versions_list): 760 if j >= MAXJ: 761 H = HH 762 j = 0 763 V += 70 764 state = (self.config["EXPORT_VERSION"] == version) 765 self.guiElements["VERSION_%s"%version] = Draw.Toggle(version, self.eventId("VERSION_%s"%version), V, H-j*20, 70, 20, state) 766 j += 1 767 self.yPos -= 20*min(MAXJ, max(len(NifFormat.versions), len(NifFormat.games))) 768 self.drawYSep() 769 770 if self.config["EXPORT_VERSION"] in games_list: 771 self.guiElements["EXPORT_RESET"] = Draw.PushButton( 772 "Restore Default Settings For Selected Game", 773 self.eventId("GAME_%s"%self.config["EXPORT_VERSION"]), 774 self.xPos, self.yPos, self.XCOLUMNSKIP, self.YLINESKIP) 775 self.yPos -= self.YLINESKIP 776 self.drawYSep() 777 778 self.drawPushButton( 779 text = "Ok", 780 event_name = "OK", 781 num_items = 3, item = 0) 782 # (item 1 is whitespace) 783 self.drawPushButton( 784 text = "Cancel", 785 event_name = "CANCEL", 786 num_items = 3, item = 2) 787 788 # advanced import settings 789 if self.target == self.TARGET_IMPORT: 790 self.drawNextColumn() 791 792 self.drawToggle( 793 text = "Realign Bone Tail Only", 794 event_name = "IMPORT_REALIGN_BONES_1", 795 val = (self.config["IMPORT_REALIGN_BONES"] == 1), 796 num_items = 2, item = 0) 797 self.drawToggle( 798 text = "Realign Bone Tail + Roll", 799 event_name = "IMPORT_REALIGN_BONES_2", 800 val = (self.config["IMPORT_REALIGN_BONES"] == 2), 801 num_items = 2, item = 1) 802 self.drawToggle( 803 text="Merge Skeleton Roots", 804 event_name="IMPORT_MERGESKELETONROOTS") 805 self.drawToggle( 806 text="Send Geometries To Bind Position", 807 event_name="IMPORT_SENDGEOMETRIESTOBINDPOS") 808 self.drawToggle( 809 text="Send Detached Geometries To Node Position", 810 event_name="IMPORT_SENDDETACHEDGEOMETRIESTONODEPOS") 811 self.drawToggle( 812 text="Send Bones To Bind Position", 813 event_name="IMPORT_SENDBONESTOBINDPOS") 814 self.drawToggle( 815 text = "Apply Skin Deformation", 816 event_name = "IMPORT_APPLYSKINDEFORM") 817 self.drawYSep() 818 819 # export-only options for oblivion/fallout 3 820 821 if (self.target == self.TARGET_EXPORT 822 and self.config["EXPORT_VERSION"] in ("Oblivion", "Fallout 3")): 823 self.drawNextColumn() 824 825 self.drawLabel( 826 text = "Collision Options", 827 event_name = "EXPORT_OB_COLLISIONHTML") 828 self.drawPushButton( 829 text = "Static", 830 event_name = "EXPORT_OB_RIGIDBODY_STATIC", 831 num_items = 5, item = 0) 832 self.drawPushButton( 833 text = "Anim Static", 834 event_name = "EXPORT_OB_RIGIDBODY_ANIMATED", 835 num_items = 5, item = 1) 836 self.drawPushButton( 837 text = "Clutter", 838 event_name = "EXPORT_OB_RIGIDBODY_CLUTTER", 839 num_items = 5, item = 2) 840 self.drawPushButton( 841 text = "Weapon", 842 event_name = "EXPORT_OB_RIGIDBODY_WEAPON", 843 num_items = 5, item = 3) 844 self.drawPushButton( 845 text = "Creature", 846 event_name = "EXPORT_OB_RIGIDBODY_CREATURE", 847 num_items = 5, item = 4) 848 self.drawToggle( 849 text = "Stone", 850 event_name = "EXPORT_OB_MATERIAL_STONE", 851 val = self.config["EXPORT_OB_MATERIAL"] == 0, 852 num_items = 6, item = 0) 853 self.drawToggle( 854 text = "Cloth", 855 event_name = "EXPORT_OB_MATERIAL_CLOTH", 856 val = self.config["EXPORT_OB_MATERIAL"] == 1, 857 num_items = 6, item = 1) 858 self.drawToggle( 859 text = "Glass", 860 event_name = "EXPORT_OB_MATERIAL_GLASS", 861 val = self.config["EXPORT_OB_MATERIAL"] == 3, 862 num_items = 6, item = 2) 863 self.drawToggle( 864 text = "Metal", 865 event_name = "EXPORT_OB_MATERIAL_METAL", 866 val = self.config["EXPORT_OB_MATERIAL"] == 5, 867 num_items = 6, item = 3) 868 self.drawToggle( 869 text = "Skin", 870 event_name = "EXPORT_OB_MATERIAL_SKIN", 871 val = self.config["EXPORT_OB_MATERIAL"] == 7, 872 num_items = 6, item = 4) 873 self.drawToggle( 874 text = "Wood", 875 event_name = "EXPORT_OB_MATERIAL_WOOD", 876 val = self.config["EXPORT_OB_MATERIAL"] == 9, 877 num_items = 6, item = 5) 878 self.drawNumber( 879 text = "Material: ", 880 event_name = "EXPORT_OB_MATERIAL", 881 min_val = 0, max_val = 30, 882 callback = self.updateObMaterial) 883 self.drawNumber( 884 text = "BSX Flags: ", 885 event_name = "EXPORT_OB_BSXFLAGS", 886 min_val = 0, max_val = 63, 887 callback = self.updateObBSXFlags, 888 num_items = 2, item = 0) 889 self.drawSlider( 890 text = "Mass: ", 891 event_name = "EXPORT_OB_MASS", 892 min_val = 0.1, max_val = 1500.0, 893 callback = self.updateObMass, 894 num_items = 2, item = 1) 895 self.drawNumber( 896 text = "Layer: ", 897 event_name = "EXPORT_OB_LAYER", 898 min_val = 0, max_val = 57, 899 callback = self.updateObLayer, 900 num_items = 3, item = 0) 901 self.drawNumber( 902 text = "Motion System: ", 903 event_name = "EXPORT_OB_MOTIONSYSTEM", 904 min_val = 0, max_val = 9, 905 callback = self.updateObMotionSystem, 906 num_items = 3, item = 1) 907 self.drawNumber( 908 text = "Quality Type: ", 909 event_name = "EXPORT_OB_QUALITYTYPE", 910 min_val = 0, max_val = 8, 911 callback = self.updateObQualityType, 912 num_items = 3, item = 2) 913 self.drawNumber( 914 text = "Unk Byte 1: ", 915 event_name = "EXPORT_OB_UNKNOWNBYTE1", 916 min_val = 1, max_val = 2, 917 callback = self.updateObUnknownByte1, 918 num_items = 3, item = 0) 919 self.drawNumber( 920 text = "Unk Byte 2: ", 921 event_name = "EXPORT_OB_UNKNOWNBYTE2", 922 min_val = 1, max_val = 2, 923 callback = self.updateObUnknownByte2, 924 num_items = 3, item = 1) 925 self.drawNumber( 926 text = "Wind: ", 927 event_name = "EXPORT_OB_WIND", 928 min_val = 0, max_val = 1, 929 callback = self.updateObWind, 930 num_items = 3, item = 2) 931 self.drawToggle( 932 text = "Solid", 933 event_name = "EXPORT_OB_SOLID", 934 num_items = 2, item = 0) 935 self.drawToggle( 936 text = "Hollow", 937 event_name = "EXPORT_OB_HOLLOW", 938 val = not self.config["EXPORT_OB_SOLID"], 939 num_items = 2, item = 1) 940 self.drawYSep() 941 942 self.drawToggle( 943 text = "Use bhkListShape", 944 event_name = "EXPORT_BHKLISTSHAPE", 945 num_items = 2, item = 0) 946 self.drawToggle( 947 text = "Use bhkMalleableConstraint", 948 event_name = "EXPORT_OB_MALLEABLECONSTRAINT", 949 num_items = 2, item = 1) 950 self.drawYSep() 951 952 self.drawLabel( 953 text = "Weapon Body Location", 954 event_name = "LABEL_WEAPON_LOCATION") 955 self.drawToggle( 956 text = "None", 957 val = self.config["EXPORT_OB_PRN"] == "NONE", 958 event_name = "EXPORT_OB_PRN_NONE", 959 num_items = 7, item = 0) 960 self.drawToggle( 961 text = "Back", 962 val = self.config["EXPORT_OB_PRN"] == "BACK", 963 event_name = "EXPORT_OB_PRN_BACK", 964 num_items = 7, item = 1) 965 self.drawToggle( 966 text = "Side", 967 val = self.config["EXPORT_OB_PRN"] == "SIDE", 968 event_name = "EXPORT_OB_PRN_SIDE", 969 num_items = 7, item = 2) 970 self.drawToggle( 971 text = "Quiver", 972 val = self.config["EXPORT_OB_PRN"] == "QUIVER", 973 event_name = "EXPORT_OB_PRN_QUIVER", 974 num_items = 7, item = 3) 975 self.drawToggle( 976 text = "Shield", 977 val = self.config["EXPORT_OB_PRN"] == "SHIELD", 978 event_name = "EXPORT_OB_PRN_SHIELD", 979 num_items = 7, item = 4) 980 self.drawToggle( 981 text = "Helm", 982 val = self.config["EXPORT_OB_PRN"] == "HELM", 983 event_name = "EXPORT_OB_PRN_HELM", 984 num_items = 7, item = 5) 985 self.drawToggle( 986 text = "Ring", 987 val = self.config["EXPORT_OB_PRN"] == "RING", 988 event_name = "EXPORT_OB_PRN_RING", 989 num_items = 7, item = 6) 990 self.drawYSep() 991 992 # export-only options for morrowind 993 if (self.target == self.TARGET_EXPORT 994 and self.config["EXPORT_VERSION"] == "Morrowind"): 995 self.drawNextColumn() 996 997 self.drawToggle( 998 text = "Export nif + xnif + kf", 999 event_name = "EXPORT_MW_NIFXNIFKF") 1000 1001 # export-only options for civ4 and rrt 1002 if (self.target == self.TARGET_EXPORT 1003 and (self.config["EXPORT_VERSION"] 1004 in NifImportExport.USED_EXTRA_SHADER_TEXTURES)): 1005 self.drawNextColumn() 1006 1007 self.drawToggle( 1008 text = "Export Extra Shader Textures", 1009 event_name = "EXPORT_EXTRA_SHADER_TEXTURES") 1010 1011 # export-only options for fallout 3 1012 if (self.target == self.TARGET_EXPORT 1013 and self.config["EXPORT_VERSION"] == "Fallout 3"): 1014 self.drawNextColumn() 1015 1016 self.drawLabel( 1017 text = "Shader Options", 1018 event_name = "LABEL_FO3_SHADER_OPTIONS") 1019 self.drawPushButton( 1020 text = "Default", 1021 event_name = "EXPORT_FO3_SHADER_OPTION_DEFAULT", 1022 num_items = 3, item = 0) 1023 self.drawPushButton( 1024 text = "Skin", 1025 event_name = "EXPORT_FO3_SHADER_OPTION_SKIN", 1026 num_items = 3, item = 1) 1027 self.drawPushButton( 1028 text = "Cloth", 1029 event_name = "EXPORT_FO3_SHADER_OPTION_CLOTH", 1030 num_items = 3, item = 2) 1031 self.drawToggle( 1032 text = "Default Type", 1033 val = self.config["EXPORT_FO3_SHADER_TYPE"] == 1, 1034 event_name = "EXPORT_FO3_SHADER_TYPE_DEFAULT", 1035 num_items = 2, item = 0) 1036 self.drawToggle( 1037 text = "Skin Type", 1038 val = self.config["EXPORT_FO3_SHADER_TYPE"] == 14, 1039 event_name = "EXPORT_FO3_SHADER_TYPE_SKIN", 1040 num_items = 2, item = 1) 1041 self.drawToggle( 1042 text = "Z Buffer", 1043 event_name = "EXPORT_FO3_SF_ZBUF", 1044 num_items = 3, item = 0) 1045 self.drawToggle( 1046 text = "Shadow Map", 1047 event_name = "EXPORT_FO3_SF_SMAP", 1048 num_items = 3, item = 1) 1049 self.drawToggle( 1050 text = "Shadow Frustum", 1051 event_name = "EXPORT_FO3_SF_SFRU", 1052 num_items = 3, item = 2) 1053 self.drawToggle( 1054 text = "Window Envmap", 1055 event_name = "EXPORT_FO3_SF_WINDOW_ENVMAP", 1056 num_items = 3, item = 0) 1057 self.drawToggle( 1058 text = "Empty", 1059 event_name = "EXPORT_FO3_SF_EMPT", 1060 num_items = 3, item = 1) 1061 self.drawToggle( 1062 text = "Unknown 31", 1063 event_name = "EXPORT_FO3_SF_UN31", 1064 num_items = 3, item = 2) 1065 self.drawYSep() 1066 1067 self.drawToggle( 1068 text = "Use BSFadeNode Root", 1069 event_name = "EXPORT_FO3_FADENODE") 1070 self.drawYSep() 1071 1072 self.drawToggle( 1073 text = "Export Dismember Body Parts", 1074 event_name = "EXPORT_FO3_BODYPARTS") 1075 self.drawYSep()
1076 1077 # is this needed? 1078 #Draw.Redraw(1) 1079
1080 - def guiButtonEvent(self, evt):
1081 """Event handler for buttons.""" 1082 try: 1083 evName = self.guiEvents[evt] 1084 except IndexError: 1085 evName = None 1086 1087 if evName == "OK": 1088 self.save() 1089 self.guiExit() 1090 elif evName == "CANCEL": 1091 self.callback = None 1092 self.guiExit() 1093 elif evName == "TEXPATH_ADD": 1094 # browse and add texture search path 1095 Blender.Window.FileSelector(self.addTexturePath, "Add Texture Search Path") 1096 elif evName == "TEXPATH_NEXT": 1097 if self.texpathIndex < (len(self.config["IMPORT_TEXTURE_PATH"])-1): 1098 self.texpathIndex += 1 1099 self.updateTexpathCurrent() 1100 elif evName == "TEXPATH_PREV": 1101 if self.texpathIndex > 0: 1102 self.texpathIndex -= 1 1103 self.updateTexpathCurrent() 1104 elif evName == "TEXPATH_REMOVE": 1105 if self.texpathIndex < len(self.config["IMPORT_TEXTURE_PATH"]): 1106 del self.config["IMPORT_TEXTURE_PATH"][self.texpathIndex] 1107 if self.texpathIndex > 0: 1108 self.texpathIndex -= 1 1109 self.updateTexpathCurrent() 1110 1111 elif evName == "IMPORT_KEYFRAMEFILE_ADD": 1112 kffile = self.config["IMPORT_KEYFRAMEFILE"] 1113 if not kffile: 1114 kffile = Blender.sys.dirname(self.config["IMPORT_FILE"]) 1115 # browse and add keyframe file 1116 Blender.Window.FileSelector( 1117 self.selectKeyframeFile, "Select Keyframe File", kffile) 1118 self.config["IMPORT_ANIMATION"] = True 1119 elif evName == "IMPORT_KEYFRAMEFILE_REMOVE": 1120 self.config["IMPORT_KEYFRAMEFILE"] = '' 1121 self.config["IMPORT_ANIMATION"] = False 1122 1123 elif evName == "IMPORT_EGMFILE_ADD": 1124 egmfile = self.config["IMPORT_EGMFILE"] 1125 if not egmfile: 1126 egmfile = self.config["IMPORT_FILE"][:-3] + "egm" 1127 # browse and add egm file 1128 Blender.Window.FileSelector( 1129 self.selectEgmFile, "Select FaceGen EGM File", egmfile) 1130 elif evName == "IMPORT_EGMFILE_REMOVE": 1131 self.config["IMPORT_EGMFILE"] = '' 1132 1133 elif evName == "IMPORT_REALIGN_BONES_1": 1134 if self.config["IMPORT_REALIGN_BONES"] == 1: 1135 self.config["IMPORT_REALIGN_BONES"] = 0 1136 else: 1137 self.config["IMPORT_REALIGN_BONES"] = 1 1138 elif evName == "IMPORT_REALIGN_BONES_2": 1139 if self.config["IMPORT_REALIGN_BONES"] == 2: 1140 self.config["IMPORT_REALIGN_BONES"] = 0 1141 else: 1142 self.config["IMPORT_REALIGN_BONES"] = 2 1143 elif evName == "IMPORT_ANIMATION": 1144 self.config["IMPORT_ANIMATION"] = not self.config["IMPORT_ANIMATION"] 1145 elif evName == "IMPORT_SKELETON_1": 1146 if self.config["IMPORT_SKELETON"] == 1: 1147 self.config["IMPORT_SKELETON"] = 0 1148 else: 1149 self.config["IMPORT_SKELETON"] = 1 1150 elif evName == "IMPORT_SKELETON_2": 1151 if self.config["IMPORT_SKELETON"] == 2: 1152 self.config["IMPORT_SKELETON"] = 0 1153 else: 1154 self.config["IMPORT_SKELETON"] = 2 1155 elif evName == "IMPORT_MERGESKELETONROOTS": 1156 self.config["IMPORT_MERGESKELETONROOTS"] = not self.config["IMPORT_MERGESKELETONROOTS"] 1157 elif evName == "IMPORT_SENDGEOMETRIESTOBINDPOS": 1158 self.config["IMPORT_SENDGEOMETRIESTOBINDPOS"] = not self.config["IMPORT_SENDGEOMETRIESTOBINDPOS"] 1159 elif evName == "IMPORT_SENDDETACHEDGEOMETRIESTONODEPOS": 1160 self.config["IMPORT_SENDDETACHEDGEOMETRIESTONODEPOS"] = not self.config["IMPORT_SENDDETACHEDGEOMETRIESTONODEPOS"] 1161 elif evName == "IMPORT_SENDBONESTOBINDPOS": 1162 self.config["IMPORT_SENDBONESTOBINDPOS"] = not self.config["IMPORT_SENDBONESTOBINDPOS"] 1163 elif evName == "IMPORT_APPLYSKINDEFORM": 1164 self.config["IMPORT_APPLYSKINDEFORM"] = not self.config["IMPORT_APPLYSKINDEFORM"] 1165 elif evName == "IMPORT_EXTRANODES": 1166 self.config["IMPORT_EXTRANODES"] = not self.config["IMPORT_EXTRANODES"] 1167 elif evName == "IMPORT_EXPORTEMBEDDEDTEXTURES": 1168 self.config["IMPORT_EXPORTEMBEDDEDTEXTURES"] = not self.config["IMPORT_EXPORTEMBEDDEDTEXTURES"] 1169 elif evName == "IMPORT_COMBINESHAPES": 1170 self.config["IMPORT_COMBINESHAPES"] = not self.config["IMPORT_COMBINESHAPES"] 1171 elif evName == "IMPORT_EGMANIM": 1172 self.config["IMPORT_EGMANIM"] = not self.config["IMPORT_EGMANIM"] 1173 elif evName == "IMPORT_SETTINGS_DEFAULT": 1174 self.config["IMPORT_ANIMATION"] = True 1175 self.config["IMPORT_SKELETON"] = 0 1176 self.config["IMPORT_EXPORTEMBEDDEDTEXTURES"] = False 1177 self.config["IMPORT_COMBINESHAPES"] = True 1178 self.config["IMPORT_REALIGN_BONES"] = 1 1179 self.config["IMPORT_MERGESKELETONROOTS"] = True 1180 self.config["IMPORT_SENDGEOMETRIESTOBINDPOS"] = True 1181 self.config["IMPORT_SENDDETACHEDGEOMETRIESTONODEPOS"] = True 1182 self.config["IMPORT_SENDBONESTOBINDPOS"] = True 1183 self.config["IMPORT_APPLYSKINDEFORM"] = False 1184 self.config["IMPORT_EXTRANODES"] = True 1185 self.config["IMPORT_EGMFILE"] = '' 1186 self.config["IMPORT_EGMANIM"] = True 1187 self.config["IMPORT_EGMANIMSCALE"] = 1.0 1188 elif evName == "IMPORT_SETTINGS_SKINNING": 1189 self.config["IMPORT_ANIMATION"] = True 1190 self.config["IMPORT_SKELETON"] = 0 1191 self.config["IMPORT_EXPORTEMBEDDEDTEXTURES"] = False 1192 self.config["IMPORT_COMBINESHAPES"] = True 1193 self.config["IMPORT_REALIGN_BONES"] = 1 1194 self.config["IMPORT_MERGESKELETONROOTS"] = True 1195 self.config["IMPORT_SENDGEOMETRIESTOBINDPOS"] = False 1196 self.config["IMPORT_SENDDETACHEDGEOMETRIESTONODEPOS"] = False 1197 self.config["IMPORT_SENDBONESTOBINDPOS"] = False 1198 self.config["IMPORT_APPLYSKINDEFORM"] = True 1199 self.config["IMPORT_EXTRANODES"] = True 1200 elif evName[:5] == "GAME_": 1201 self.config["EXPORT_VERSION"] = evName[5:] 1202 # settings that usually make sense, fail-safe 1203 self.config["EXPORT_FORCEDDS"] = True 1204 self.config["EXPORT_SMOOTHOBJECTSEAMS"] = True 1205 self.config["EXPORT_STRIPIFY"] = False 1206 self.config["EXPORT_STITCHSTRIPS"] = False 1207 self.config["EXPORT_ANIMATION"] = 1 1208 self.config["EXPORT_FLATTENSKIN"] = False 1209 self.config["EXPORT_SKINPARTITION"] = False 1210 self.config["EXPORT_BONESPERPARTITION"] = 4 1211 self.config["EXPORT_PADBONES"] = False 1212 self.config["EXPORT_OB_SOLID"] = True 1213 self.config["EXPORT_MW_NIFXNIFKF"] = False 1214 self.config["EXPORT_EXTRA_SHADER_TEXTURES"] = True 1215 # set default settings per game 1216 if self.config["EXPORT_VERSION"] == "Morrowind": 1217 pass # fail-safe settings work 1218 if self.config["EXPORT_VERSION"] == "Freedom Force vs. the 3rd Reich": 1219 self.config["EXPORT_SKINPARTITION"] = True 1220 self.config["EXPORT_PADBONES"] = True 1221 elif self.config["EXPORT_VERSION"] == "Civilization IV": 1222 self.config["EXPORT_STRIPIFY"] = True 1223 self.config["EXPORT_STITCHSTRIPS"] = True 1224 self.config["EXPORT_BONESPERPARTITION"] = 18 1225 self.config["EXPORT_SKINPARTITION"] = True 1226 elif self.config["EXPORT_VERSION"] in ("Oblivion", "Fallout 3"): 1227 self.config["EXPORT_STRIPIFY"] = True 1228 self.config["EXPORT_STITCHSTRIPS"] = True 1229 self.config["EXPORT_FLATTENSKIN"] = True 1230 self.config["EXPORT_BONESPERPARTITION"] = 18 1231 self.config["EXPORT_SKINPARTITION"] = True 1232 # oblivion specific settings 1233 self.config["EXPORT_BHKLISTSHAPE"] = False 1234 self.config["EXPORT_OB_MATERIAL"] = 9 # wood 1235 self.config["EXPORT_OB_MALLEABLECONSTRAINT"] = False 1236 # rigid body: static 1237 self.config["EXPORT_OB_BSXFLAGS"] = 2 1238 self.config["EXPORT_OB_MASS"] = 1000.0 1239 self.config["EXPORT_OB_MOTIONSYSTEM"] = 7 # MO_SYS_FIXED 1240 self.config["EXPORT_OB_UNKNOWNBYTE1"] = 1 1241 self.config["EXPORT_OB_UNKNOWNBYTE2"] = 1 1242 self.config["EXPORT_OB_QUALITYTYPE"] = 1 # MO_QUAL_FIXED 1243 self.config["EXPORT_OB_WIND"] = 0 1244 self.config["EXPORT_OB_LAYER"] = 1 # static 1245 # shader options 1246 self.config["EXPORT_FO3_SHADER_TYPE"] = 1 1247 self.config["EXPORT_FO3_SF_ZBUF"] = True 1248 self.config["EXPORT_FO3_SF_SMAP"] = False 1249 self.config["EXPORT_FO3_SF_SFRU"] = False 1250 self.config["EXPORT_FO3_SF_WINDOW_ENVMAP"] = False 1251 self.config["EXPORT_FO3_SF_EMPT"] = True 1252 self.config["EXPORT_FO3_SF_UN31"] = True 1253 # body parts 1254 self.config["EXPORT_FO3_BODYPARTS"] = True 1255 elif evName[:8] == "VERSION_": 1256 self.config["EXPORT_VERSION"] = evName[8:] 1257 elif evName == "EXPORT_FLATTENSKIN": 1258 self.config["EXPORT_FLATTENSKIN"] = not self.config["EXPORT_FLATTENSKIN"] 1259 if self.config["EXPORT_FLATTENSKIN"]: # if skin is flattened 1260 self.config["EXPORT_ANIMATION"] = 1 # force geometry only 1261 elif evName == "EXPORT_FORCEDDS": 1262 self.config["EXPORT_FORCEDDS"] = not self.config["EXPORT_FORCEDDS"] 1263 elif evName == "EXPORT_STRIPIFY": 1264 self.config["EXPORT_STRIPIFY"] = not self.config["EXPORT_STRIPIFY"] 1265 elif evName == "EXPORT_STITCHSTRIPS": 1266 self.config["EXPORT_STITCHSTRIPS"] = not self.config["EXPORT_STITCHSTRIPS"] 1267 elif evName == "EXPORT_SMOOTHOBJECTSEAMS": 1268 self.config["EXPORT_SMOOTHOBJECTSEAMS"] = not self.config["EXPORT_SMOOTHOBJECTSEAMS"] 1269 elif evName[:17] == "EXPORT_ANIMATION_": 1270 value = int(evName[17:]) 1271 self.config["EXPORT_ANIMATION"] = value 1272 if value == 0 or value == 2: # if animation is exported 1273 self.config["EXPORT_FLATTENSKIN"] = False # disable flattening skin 1274 elif value == 1: 1275 # enable flattening skin for 'geometry only' exports 1276 # in oblivion and fallout 3 1277 if self.config["EXPORT_VERSION"] in ("Oblivion", "Fallout 3"): 1278 self.config["EXPORT_FLATTENSKIN"] = True 1279 elif evName == "EXPORT_SKINPARTITION": 1280 self.config["EXPORT_SKINPARTITION"] = not self.config["EXPORT_SKINPARTITION"] 1281 elif evName == "EXPORT_PADBONES": 1282 self.config["EXPORT_PADBONES"] = not self.config["EXPORT_PADBONES"] 1283 if self.config["EXPORT_PADBONES"]: # bones are padded 1284 self.config["EXPORT_BONESPERPARTITION"] = 4 # force 4 bones per partition 1285 elif evName == "EXPORT_BHKLISTSHAPE": 1286 self.config["EXPORT_BHKLISTSHAPE"] = not self.config["EXPORT_BHKLISTSHAPE"] 1287 elif evName == "EXPORT_OB_MALLEABLECONSTRAINT": 1288 self.config["EXPORT_OB_MALLEABLECONSTRAINT"] = not self.config["EXPORT_OB_MALLEABLECONSTRAINT"] 1289 elif evName == "EXPORT_OB_SOLID": 1290 self.config["EXPORT_OB_SOLID"] = True 1291 elif evName == "EXPORT_OB_HOLLOW": 1292 self.config["EXPORT_OB_SOLID"] = False 1293 elif evName == "EXPORT_OB_RIGIDBODY_STATIC": 1294 self.config["EXPORT_OB_MATERIAL"] = 0 # stone 1295 self.config["EXPORT_OB_BSXFLAGS"] = 2 # havok 1296 self.config["EXPORT_OB_MASS"] = 10.0 1297 self.config["EXPORT_OB_MOTIONSYSTEM"] = 7 # MO_SYS_FIXED 1298 self.config["EXPORT_OB_UNKNOWNBYTE1"] = 1 1299 self.config["EXPORT_OB_UNKNOWNBYTE2"] = 1 1300 self.config["EXPORT_OB_QUALITYTYPE"] = 1 # MO_QUAL_FIXED 1301 self.config["EXPORT_OB_WIND"] = 0 1302 self.config["EXPORT_OB_LAYER"] = 1 # static 1303 self.config["EXPORT_OB_SOLID"] = True 1304 self.config["EXPORT_OB_PRN"] = "NONE" 1305 elif evName == "EXPORT_OB_RIGIDBODY_ANIMATED": # see fencedoor01.nif 1306 self.config["EXPORT_OB_MATERIAL"] = 0 # stone 1307 self.config["EXPORT_OB_BSXFLAGS"] = 11 # havok + anim + unknown 1308 self.config["EXPORT_OB_MASS"] = 10.0 1309 self.config["EXPORT_OB_MOTIONSYSTEM"] = 6 # MO_SYS_KEYFRAMED 1310 self.config["EXPORT_OB_UNKNOWNBYTE1"] = 2 1311 self.config["EXPORT_OB_UNKNOWNBYTE2"] = 2 1312 self.config["EXPORT_OB_QUALITYTYPE"] = 2 # MO_QUAL_KEYFRAMED 1313 self.config["EXPORT_OB_WIND"] = 0 1314 self.config["EXPORT_OB_LAYER"] = 2 # OL_ANIM_STATIC 1315 self.config["EXPORT_OB_SOLID"] = True 1316 self.config["EXPORT_OB_PRN"] = "NONE" 1317 elif evName == "EXPORT_OB_RIGIDBODY_CLUTTER": 1318 self.config["EXPORT_OB_BSXFLAGS"] = 3 # anim + havok 1319 self.config["EXPORT_OB_MASS"] = 10.0 # typical 1320 self.config["EXPORT_OB_MOTIONSYSTEM"] = 4 # MO_SYS_BOX 1321 self.config["EXPORT_OB_UNKNOWNBYTE1"] = 2 1322 self.config["EXPORT_OB_UNKNOWNBYTE2"] = 2 1323 self.config["EXPORT_OB_QUALITYTYPE"] = 3 # MO_QUAL_DEBRIS 1324 self.config["EXPORT_OB_WIND"] = 0 1325 self.config["EXPORT_OB_LAYER"] = 4 # clutter 1326 self.config["EXPORT_OB_SOLID"] = True 1327 self.config["EXPORT_OB_PRN"] = "NONE" 1328 elif evName == "EXPORT_OB_RIGIDBODY_WEAPON": 1329 self.config["EXPORT_OB_MATERIAL"] = 5 # metal 1330 self.config["EXPORT_OB_BSXFLAGS"] = 3 # anim + havok 1331 self.config["EXPORT_OB_MASS"] = 25.0 # typical 1332 self.config["EXPORT_OB_MOTIONSYSTEM"] = 4 # MO_SYS_BOX 1333 self.config["EXPORT_OB_UNKNOWNBYTE1"] = 2 1334 self.config["EXPORT_OB_UNKNOWNBYTE2"] = 2 1335 self.config["EXPORT_OB_QUALITYTYPE"] = 3 # MO_QUAL_DEBRIS 1336 self.config["EXPORT_OB_WIND"] = 0 1337 self.config["EXPORT_OB_LAYER"] = 5 # weapin 1338 self.config["EXPORT_OB_SOLID"] = True 1339 self.config["EXPORT_OB_PRN"] = "SIDE" 1340 elif evName == "EXPORT_OB_RIGIDBODY_CREATURE": 1341 self.config["EXPORT_OB_MATERIAL"] = 7 # skin 1342 self.config["EXPORT_OB_BSXFLAGS"] = 7 # anim + havok + skeleton 1343 self.config["EXPORT_OB_MASS"] = 600.0 # single person's weight in Oblivion 1344 self.config["EXPORT_OB_MOTIONSYSTEM"] = 6 # MO_SYS_KEYFRAMED 1345 self.config["EXPORT_OB_UNKNOWNBYTE1"] = 2 1346 self.config["EXPORT_OB_UNKNOWNBYTE2"] = 2 1347 self.config["EXPORT_OB_QUALITYTYPE"] = 2 # MO_QUAL_KEYFRAMED 1348 self.config["EXPORT_OB_WIND"] = 0 1349 self.config["EXPORT_OB_LAYER"] = 8 # biped 1350 self.config["EXPORT_OB_SOLID"] = True 1351 self.config["EXPORT_OB_PRN"] = "NONE" 1352 elif evName == "EXPORT_OB_MATERIAL_STONE": 1353 self.config["EXPORT_OB_MATERIAL"] = 0 1354 elif evName == "EXPORT_OB_MATERIAL_CLOTH": 1355 self.config["EXPORT_OB_MATERIAL"] = 1 1356 elif evName == "EXPORT_OB_MATERIAL_GLASS": 1357 self.config["EXPORT_OB_MATERIAL"] = 3 1358 elif evName == "EXPORT_OB_MATERIAL_METAL": 1359 self.config["EXPORT_OB_MATERIAL"] = 5 1360 elif evName == "EXPORT_OB_MATERIAL_SKIN": 1361 self.config["EXPORT_OB_MATERIAL"] = 7 1362 elif evName == "EXPORT_OB_MATERIAL_WOOD": 1363 self.config["EXPORT_OB_MATERIAL"] = 9 1364 elif evName[:14] == "EXPORT_OB_PRN_": 1365 self.config["EXPORT_OB_PRN"] = evName[14:] 1366 elif evName == "EXPORT_OPTIMIZE_MATERIALS": 1367 self.config["EXPORT_OPTIMIZE_MATERIALS"] = not self.config["EXPORT_OPTIMIZE_MATERIALS"] 1368 elif evName == "LOG_LEVEL_WARN": 1369 self.updateLogLevel(evName, logging.WARNING) 1370 elif evName == "LOG_LEVEL_INFO": 1371 self.updateLogLevel(evName, logging.INFO) 1372 elif evName == "LOG_LEVEL_DEBUG": 1373 self.updateLogLevel(evName, logging.DEBUG) 1374 elif evName == "EXPORT_FO3_FADENODE": 1375 self.config["EXPORT_FO3_FADENODE"] = not self.config["EXPORT_FO3_FADENODE"] 1376 elif evName.startswith("EXPORT_FO3_SF_"): 1377 self.config[evName] = not self.config[evName] 1378 elif evName == "EXPORT_FO3_SHADER_TYPE_DEFAULT": 1379 self.config["EXPORT_FO3_SHADER_TYPE"] = 1 1380 elif evName == "EXPORT_FO3_SHADER_TYPE_SKIN": 1381 self.config["EXPORT_FO3_SHADER_TYPE"] = 14 1382 elif evName == "EXPORT_FO3_SHADER_OPTION_DEFAULT": 1383 self.config["EXPORT_FO3_SHADER_TYPE"] = 1 1384 self.config["EXPORT_FO3_SF_ZBUF"] = True 1385 self.config["EXPORT_FO3_SF_SMAP"] = False 1386 self.config["EXPORT_FO3_SF_SFRU"] = False 1387 self.config["EXPORT_FO3_SF_WINDOW_ENVMAP"] = False 1388 self.config["EXPORT_FO3_SF_EMPT"] = True 1389 self.config["EXPORT_FO3_SF_UN31"] = True 1390 elif evName == "EXPORT_FO3_SHADER_OPTION_SKIN": 1391 self.config["EXPORT_FO3_SHADER_TYPE"] = 14 1392 self.config["EXPORT_FO3_SF_ZBUF"] = True 1393 self.config["EXPORT_FO3_SF_SMAP"] = True 1394 self.config["EXPORT_FO3_SF_SFRU"] = False 1395 self.config["EXPORT_FO3_SF_WINDOW_ENVMAP"] = True 1396 self.config["EXPORT_FO3_SF_EMPT"] = True 1397 self.config["EXPORT_FO3_SF_UN31"] = True 1398 elif evName == "EXPORT_FO3_SHADER_OPTION_CLOTH": 1399 self.config["EXPORT_FO3_SHADER_TYPE"] = 1 1400 self.config["EXPORT_FO3_SF_ZBUF"] = True 1401 self.config["EXPORT_FO3_SF_SMAP"] = True 1402 self.config["EXPORT_FO3_SF_SFRU"] = False 1403 self.config["EXPORT_FO3_SF_WINDOW_ENVMAP"] = False 1404 self.config["EXPORT_FO3_SF_EMPT"] = True 1405 self.config["EXPORT_FO3_SF_UN31"] = True 1406 elif evName == "EXPORT_FO3_BODYPARTS": 1407 self.config["EXPORT_FO3_BODYPARTS"] = not self.config["EXPORT_FO3_BODYPARTS"] 1408 elif evName == "EXPORT_MW_NIFXNIFKF": 1409 self.config["EXPORT_MW_NIFXNIFKF"] = not self.config["EXPORT_MW_NIFXNIFKF"] 1410 elif evName == "EXPORT_EXTRA_SHADER_TEXTURES": 1411 self.config["EXPORT_EXTRA_SHADER_TEXTURES"] = not self.config["EXPORT_EXTRA_SHADER_TEXTURES"] 1412 Draw.Redraw(1)
1413
1414 - def guiEvent(self, evt, val):
1415 """Event handler for GUI elements.""" 1416 1417 if evt == Draw.ESCKEY: 1418 self.callback = None 1419 self.guiExit() 1420 1421 Draw.Redraw(1)
1422
1423 - def guiExit(self):
1424 """Close config GUI and call callback function.""" 1425 Draw.Exit() 1426 if not self.callback: return # no callback 1427 # pass on control to callback function 1428 if not self.config["PROFILE"]: 1429 # without profiling 1430 self.callback(**self.config) 1431 else: 1432 # with profiling 1433 import cProfile 1434 import pstats 1435 prof = cProfile.Profile() 1436 prof.runctx('self.callback(**self.config)', locals(), globals()) 1437 prof.dump_stats(self.config["PROFILE"]) 1438 stats = pstats.Stats(self.config["PROFILE"]) 1439 stats.strip_dirs() 1440 stats.sort_stats('cumulative') 1441 stats.print_stats()
1442
1443 - def addTexturePath(self, texture_path):
1444 texture_path = Blender.sys.dirname(texture_path) 1445 if texture_path == '' or not Blender.sys.exists(texture_path): 1446 Draw.PupMenu('No path selected or path does not exist%t|Ok') 1447 else: 1448 if texture_path not in self.config["IMPORT_TEXTURE_PATH"]: 1449 self.config["IMPORT_TEXTURE_PATH"].append(texture_path) 1450 self.texpathIndex = self.config["IMPORT_TEXTURE_PATH"].index(texture_path) 1451 self.updateTexpathCurrent()
1452
1453 - def updateTexpathCurrent(self):
1454 """Update self.texpathCurrent string.""" 1455 if self.config["IMPORT_TEXTURE_PATH"]: 1456 self.texpathCurrent = self.config["IMPORT_TEXTURE_PATH"][self.texpathIndex] 1457 else: 1458 self.texpathCurrent = ''
1459
1460 - def selectKeyframeFile(self, keyframefile):
1461 if keyframefile == '' or not Blender.sys.exists(keyframefile): 1462 Draw.PupMenu('No file selected or file does not exist%t|Ok') 1463 else: 1464 self.config["IMPORT_KEYFRAMEFILE"] = keyframefile
1465
1466 - def selectEgmFile(self, egmfile):
1467 if egmfile == '' or not Blender.sys.exists(egmfile): 1468 Draw.PupMenu('No file selected or file does not exist%t|Ok') 1469 else: 1470 self.config["IMPORT_EGMFILE"] = egmfile
1471
1472 - def updateLogLevel(self, evt, val):
1473 self.config["LOG_LEVEL"] = val 1474 logging.getLogger("niftools").setLevel(val) 1475 logging.getLogger("pyffi").setLevel(val)
1476
1477 - def updateScale(self, evt, val):
1478 self.config["EXPORT_SCALE_CORRECTION"] = val 1479 self.config["IMPORT_SCALE_CORRECTION"] = 1.0 / self.config["EXPORT_SCALE_CORRECTION"]
1480
1481 - def updateBonesPerPartition(self, evt, val):
1482 self.config["EXPORT_BONESPERPARTITION"] = val 1483 self.config["EXPORT_PADBONES"] = False
1484
1485 - def updateObBSXFlags(self, evt, val):
1486 self.config["EXPORT_OB_BSXFLAGS"] = val
1487
1488 - def updateObMaterial(self, evt, val):
1489 self.config["EXPORT_OB_MATERIAL"] = val
1490
1491 - def updateObLayer(self, evt, val):
1492 self.config["EXPORT_OB_LAYER"] = val
1493
1494 - def updateObMass(self, evt, val):
1495 self.config["EXPORT_OB_MASS"] = val
1496
1497 - def updateObMotionSystem(self, evt, val):
1498 self.config["EXPORT_OB_MOTIONSYSTEM"] = val
1499
1500 - def updateObQualityType(self, evt, val):
1501 self.config["EXPORT_OB_QUALITYTYPE"] = val
1502
1503 - def updateObUnknownByte1(self, evt, val):
1504 self.config["EXPORT_OB_UNKNOWNBYTE1"] = val
1505
1506 - def updateObUnknownByte2(self, evt, val):
1507 self.config["EXPORT_OB_UNKNOWNBYTE2"] = val
1508
1509 - def updateObWind(self, evt, val):
1510 self.config["EXPORT_OB_WIND"] = val
1511
1512 - def updateAnimSequenceName(self, evt, val):
1513 self.config["EXPORT_ANIMSEQUENCENAME"] = val
1514
1515 - def updateEgmAnimScale(self, evt, val):
1516 self.config["IMPORT_EGMANIMSCALE"] = val
1517