=bmesh= merge from trunk at r36153

This commit is contained in:
Joseph Eagar
2011-04-15 01:19:13 +00:00
1589 changed files with 83673 additions and 48300 deletions

View File

@@ -97,10 +97,17 @@ def modules(module_cache):
break
if body_info:
mod = ModuleType(mod_name)
mod.bl_info = ast.literal_eval(body.value)
mod.__file__ = mod_path
mod.__time__ = os.path.getmtime(mod_path)
try:
mod = ModuleType(mod_name)
mod.bl_info = ast.literal_eval(body.value)
mod.__file__ = mod_path
mod.__time__ = os.path.getmtime(mod_path)
except:
print("AST error in module %s" % mod_name)
import traceback
traceback.print_exc()
raise
return mod
else:
return None
@@ -239,7 +246,6 @@ def disable(module_name, default_set=True):
:type module_name: string
"""
import sys
import traceback
import bpy_types as _bpy_types
mod = sys.modules.get(module_name)
@@ -252,6 +258,7 @@ def disable(module_name, default_set=True):
try:
mod.unregister()
except:
import traceback
traceback.print_exc()
else:
print("addon_utils.disable", module_name, "not loaded")

View File

@@ -28,6 +28,12 @@ The main function to use is: update_data_paths(...)
IS_TESTING = False
def drepr(string):
# is there a less crappy way to do this in python?, re.escape also escapes
# single quotes strings so cant use it.
return '"%s"' % repr(string)[1:-1].replace("\"", "\\\"").replace("\\'", "'")
class DataPathBuilder(object):
__slots__ = ("data_path", )
""" Dummy class used to parse fcurve and driver data paths.
@@ -40,7 +46,12 @@ class DataPathBuilder(object):
return DataPathBuilder(self.data_path + (str_value, ))
def __getitem__(self, key):
str_value = '["%s"]' % key
if type(key) is int:
str_value = '[%d]' % key
elif type(key) is str:
str_value = '[%s]' % drepr(key)
else:
raise Exception("unsupported accessor %r of type %r (internal error)" % (key, type(key)))
return DataPathBuilder(self.data_path + (str_value, ))
def resolve(self, real_base, rna_update_from_map=None):
@@ -170,6 +181,15 @@ def update_data_paths(rna_update):
continue
for fcurve in anim_data.drivers:
data_path = fcurve.data_path
data_path_new = find_path_new(anim_data_base, data_path, rna_update_dict, rna_update_from_map)
# print(data_path_new)
if data_path_new != data_path:
if not IS_TESTING:
fcurve.data_path = data_path_new
fcurve.driver.is_valid = True # reset to allow this to work again
print("driver-fcurve (%s): %s -> %s" % (id_data.name, data_path, data_path_new))
for var in fcurve.driver.variables:
if var.type == 'SINGLE_PROP':
for tar in var.targets:

View File

@@ -18,6 +18,10 @@
# <pep8 compliant>
"""
Give access to blender data and utility functions.
"""
# internal blender C module
import _bpy
from _bpy import types, props, app
@@ -37,18 +41,6 @@ import sys as _sys
def _main():
## security issue, dont allow the $CWD in the path.
## note: this removes "" but not "." which are the same, security
## people need to explain how this is even a fix.
# _sys.path[:] = filter(None, _sys.path)
# because of how the console works. we need our own help() pager func.
# replace the bold function because it adds crazy chars
import pydoc
pydoc.getpager = lambda: pydoc.plainpager
pydoc.Helper.getline = lambda self, prompt: None
pydoc.TextDoc.use_bold = lambda self, text: text
# Possibly temp. addons path
from os.path import join, dirname, normpath
_sys.path.append(normpath(join(dirname(__file__), "..", "..", "addons", "modules")))

View File

@@ -23,10 +23,7 @@ This module contains utility functions specific to blender but
not assosiated with blenders internal data.
"""
from _bpy import register_class
from _bpy import unregister_class
from _bpy import blend_paths
from _bpy import register_class, unregister_class, blend_paths, resource_path
from _bpy import script_paths as _bpy_script_paths
from _bpy import user_resource as _user_resource
@@ -34,26 +31,30 @@ import bpy as _bpy
import os as _os
import sys as _sys
import addon_utils
import addon_utils as _addon_utils
def _test_import(module_name, loaded_modules):
import traceback
import time
use_time = _bpy.app.debug
if module_name in loaded_modules:
return None
if "." in module_name:
print("Ignoring '%s', can't import files containing multiple periods." % module_name)
return None
t = time.time()
if use_time:
import time
t = time.time()
try:
mod = __import__(module_name)
except:
import traceback
traceback.print_exc()
return None
if _bpy.app.debug:
if use_time:
print("time %s %.4f" % (module_name, time.time() - t))
loaded_modules.add(mod.__name__) # should match mod.__name__ too
@@ -99,10 +100,11 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
:arg refresh_scripts: only load scripts which are not already loaded as modules.
:type refresh_scripts: bool
"""
import traceback
import time
use_time = _bpy.app.debug
t_main = time.time()
if use_time:
import time
t_main = time.time()
loaded_modules = set()
@@ -116,7 +118,7 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
# note that they will only actually reload of the modification time changes.
# this `wont` work for packages so... its not perfect.
for module_name in [ext.module for ext in _bpy.context.user_preferences.addons]:
addon_utils.disable(module_name, default_set=False)
_addon_utils.disable(module_name, default_set=False)
def register_module_call(mod):
register = getattr(mod, "register", None)
@@ -124,6 +126,7 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
try:
register()
except:
import traceback
traceback.print_exc()
else:
print("\nWarning! '%s' has no register function, this is now a requirement for registerable scripts." % mod.__file__)
@@ -134,6 +137,7 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
try:
unregister()
except:
import traceback
traceback.print_exc()
def test_reload(mod):
@@ -147,6 +151,7 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
try:
return imp.reload(mod)
except:
import traceback
traceback.print_exc()
def test_register(mod):
@@ -177,10 +182,8 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
_global_loaded_modules[:] = []
user_path = user_script_path()
for base_path in script_paths():
for path_subdir in ("", "ui", "op", "io", "keyingsets", "modules"):
for path_subdir in ("startup", "modules"):
path = _os.path.join(base_path, path_subdir)
if _os.path.isdir(path):
_sys_path_ensure(path)
@@ -189,14 +192,11 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
if path_subdir == "modules":
continue
if user_path != base_path and path_subdir == "":
continue # avoid loading 2.4x scripts
for mod in modules_from_path(path, loaded_modules):
test_register(mod)
# deal with addons seperately
addon_utils.reset_all(reload_scripts)
# deal with addons separately
_addon_utils.reset_all(reload_scripts)
# run the active integration preset
filepath = preset_find(_bpy.context.user_preferences.inputs.active_keyconfig, "keyconfig")
@@ -207,7 +207,7 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
import gc
print("gc.collect() -> %d" % gc.collect())
if _bpy.app.debug:
if use_time:
print("Python Script Load Time %.4f" % (time.time() - t_main))
@@ -347,12 +347,13 @@ def keyconfig_set(filepath):
print("loading preset:", filepath)
keyconfigs = _bpy.context.window_manager.keyconfigs
kc_orig = keyconfigs.active
keyconfigs_old = keyconfigs[:]
try:
exec(compile(open(filepath).read(), filepath, 'exec'), {"__file__": filepath})
file = open(filepath)
exec(compile(file.read(), filepath, 'exec'), {"__file__": filepath})
file.close()
except:
import traceback
traceback.print_exc()
@@ -412,48 +413,47 @@ def _bpy_module_classes(module, is_registered=False):
typemap_list = _bpy_types.TypeMap.get(module, ())
i = 0
while i < len(typemap_list):
cls_weakref, path, line = typemap_list[i]
cls_weakref = typemap_list[i]
cls = cls_weakref()
if cls is None:
del typemap_list[i]
else:
if is_registered == cls.is_registered:
yield (cls, path, line)
yield cls
i += 1
def register_module(module, verbose=False):
import traceback
if verbose:
print("bpy.utils.register_module(%r): ..." % module)
for cls, path, line in _bpy_module_classes(module, is_registered=False):
cls = None
for cls in _bpy_module_classes(module, is_registered=False):
if verbose:
print(" %s of %s:%s" % (cls, path, line))
print(" %r" % cls)
try:
register_class(cls)
except:
print("bpy.utils.register_module(): failed to registering class '%s.%s'" % (cls.__module__, cls.__name__))
print("\t", path, "line", line)
print("bpy.utils.register_module(): failed to registering class %r" % cls)
import traceback
traceback.print_exc()
if verbose:
print("done.\n")
if "cls" not in locals():
if cls is None:
raise Exception("register_module(%r): defines no classes" % module)
def unregister_module(module, verbose=False):
import traceback
if verbose:
print("bpy.utils.unregister_module(%r): ..." % module)
for cls, path, line in _bpy_module_classes(module, is_registered=True):
for cls in _bpy_module_classes(module, is_registered=True):
if verbose:
print(" %s of %s:%s" % (cls, path, line))
print(" %r" % cls)
try:
unregister_class(cls)
except:
print("bpy.utils.unregister_module(): failed to unregistering class '%s.%s'" % (cls.__module__, cls.__name__))
print("\t", path, "line", line)
print("bpy.utils.unregister_module(): failed to unregistering class %r" % cls)
import traceback
traceback.print_exc()
if verbose:
print("done.\n")

View File

@@ -26,6 +26,8 @@ StructRNA = bpy_types.Struct.__bases__[0]
StructMetaPropGroup = _bpy.StructMetaPropGroup
# StructRNA = bpy_types.Struct
bpy_types.BlendDataLibraries.load = _bpy._library_load
class Context(StructRNA):
__slots__ = ()
@@ -567,18 +569,15 @@ TypeMap = {}
class RNAMeta(type):
def __new__(cls, name, bases, classdict, **args):
result = type.__new__(cls, name, bases, classdict)
if bases and bases[0] != StructRNA:
import traceback
import weakref
if bases and bases[0] is not StructRNA:
from _weakref import ref as ref
module = result.__module__
# first part of packages only
if "." in module:
module = module[:module.index(".")]
sf = traceback.extract_stack(limit=2)[0]
TypeMap.setdefault(module, []).append((weakref.ref(result), sf[0], sf[1]))
TypeMap.setdefault(module, []).append(ref(result))
return result
@@ -586,7 +585,20 @@ class RNAMeta(type):
def is_registered(cls):
return "bl_rna" in cls.__dict__
import collections
class OrderedDictMini(dict):
def __init__(self, *args):
self.order = []
dict.__init__(self, args)
def __setitem__(self, key, val):
dict.__setitem__(self, key, val)
if key not in self.order:
self.order.append(key)
def __delitem__(self, key):
dict.__delitem__(self, key)
self.order.remove(key)
class RNAMetaPropGroup(RNAMeta, StructMetaPropGroup):
@@ -594,13 +606,12 @@ class RNAMetaPropGroup(RNAMeta, StructMetaPropGroup):
class OrderedMeta(RNAMeta):
def __init__(cls, name, bases, attributes):
super(OrderedMeta, cls).__init__(name, bases, attributes)
cls.order = list(attributes.keys())
if attributes.__class__ is OrderedDictMini:
cls.order = attributes.order
def __prepare__(name, bases, **kwargs):
return collections.OrderedDict()
return OrderedDictMini() # collections.OrderedDict()
# Only defined so operators members can be used by accessing self.order
@@ -669,6 +680,9 @@ class _GenericUI:
if draw_funcs is None:
def draw_ls(self, context):
# ensure menus always get default context
operator_context_default = self.layout.operator_context
for func in draw_ls._draw_funcs:
# so bad menu functions dont stop the entire menu from drawing.
try:
@@ -677,6 +691,8 @@ class _GenericUI:
import traceback
traceback.print_exc()
self.layout.operator_context = operator_context_default
draw_funcs = draw_ls._draw_funcs = [cls.draw]
cls.draw = draw_ls

View File

@@ -160,9 +160,9 @@ if __name__ == "__main__":
from bpyml_test import *
draw = [
ui() [
split() [
column() [
ui()[
split()[
column()[
prop(data='context.scene.render', property='use_stamp_time', text='Time'),
prop(data='context.scene.render', property='use_stamp_date', text='Date'),
prop(data='context.scene.render', property='use_stamp_render_time', text='RenderTime'),
@@ -173,7 +173,7 @@ if __name__ == "__main__":
prop(data='context.scene.render', property='use_stamp_marker', text='Marker'),
prop(data='context.scene.render', property='use_stamp_sequencer_strip', text='Seq. Strip')
],
column() [
column()[
active(expr='context.scene.render.use_stamp'),
prop(data='context.scene.render', property='stamp_foreground', slider=True),
prop(data='context.scene.render', property='stamp_background', slider=True),
@@ -181,9 +181,9 @@ if __name__ == "__main__":
prop(data='context.scene.render', property='stamp_font_size', text='Font Size')
]
],
split(percentage=0.2) [
split(percentage=0.2)[
prop(data='context.scene.render', property='use_stamp_note', text='Note'),
row() [
row()[
active(expr='context.scene.render.use_stamp_note'),
prop(data='context.scene.render', property='stamp_note_text', text='')
]

View File

@@ -65,7 +65,7 @@ def _parse_rna_args(base, py_node):
def _call_recursive(context, base, py_node):
prop = base.bl_rna.properties.get(py_node[TAG])
# prop = base.bl_rna.properties.get(py_node[TAG])
if py_node[TAG] in base.bl_rna.properties:
value = py_node[ARGS].get("expr")
if value:
@@ -73,7 +73,7 @@ def _call_recursive(context, base, py_node):
setattr(base, py_node[TAG], value)
else:
value = py_node[ARGS]['value'] # have to have this
setattr(base, name, value)
setattr(base, py_node[TAG], value)
else:
args = _parse_rna_args(base, py_node)
func_new = getattr(base, py_node[TAG])

View File

@@ -0,0 +1,306 @@
# ##### BEGIN GPL LICENSE BLOCK #####
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
import sys
import bpy
language_id = 'python'
# store our own __main__ module, not 100% needed
# but python expects this in some places
_BPY_MAIN_OWN = True
def add_scrollback(text, text_type):
for l in text.split('\n'):
bpy.ops.console.scrollback_append(text=l.replace('\t', ' '),
type=text_type)
def replace_help(namespace):
def _help(*args):
# because of how the console works. we need our own help() pager func.
# replace the bold function because it adds crazy chars
import pydoc
pydoc.getpager = lambda: pydoc.plainpager
pydoc.Helper.getline = lambda self, prompt: None
pydoc.TextDoc.use_bold = lambda self, text: text
pydoc.help(*args)
namespace["help"] = _help
def get_console(console_id):
'''
helper function for console operators
currently each text datablock gets its own
console - code.InteractiveConsole()
...which is stored in this function.
console_id can be any hashable type
'''
from code import InteractiveConsole
consoles = getattr(get_console, "consoles", None)
hash_next = hash(bpy.context.window_manager)
if consoles is None:
consoles = get_console.consoles = {}
get_console.consoles_namespace_hash = hash_next
else:
# check if clearning the namespace is needed to avoid a memory leak.
# the window manager is normally loaded with new blend files
# so this is a reasonable way to deal with namespace clearing.
# bpy.data hashing is reset by undo so cant be used.
hash_prev = getattr(get_console, "consoles_namespace_hash", 0)
if hash_prev != hash_next:
get_console.consoles_namespace_hash = hash_next
consoles.clear()
console_data = consoles.get(console_id)
if console_data:
console, stdout, stderr = console_data
# XXX, bug in python 3.1.2 ? (worked in 3.1.1)
# seems there is no way to clear StringIO objects for writing, have to make new ones each time.
import io
stdout = io.StringIO()
stderr = io.StringIO()
else:
if _BPY_MAIN_OWN:
import types
bpy_main_mod = types.ModuleType("__main__")
namespace = bpy_main_mod.__dict__
else:
namespace = {}
namespace["__builtins__"] = sys.modules["builtins"]
namespace["bpy"] = bpy
namespace["C"] = bpy.context
replace_help(namespace)
console = InteractiveConsole(locals=namespace, filename="<blender_console>")
console.push("from mathutils import *")
console.push("from math import *")
if _BPY_MAIN_OWN:
console._bpy_main_mod = bpy_main_mod
import io
stdout = io.StringIO()
stderr = io.StringIO()
consoles[console_id] = console, stdout, stderr
return console, stdout, stderr
# Both prompts must be the same length
PROMPT = '>>> '
PROMPT_MULTI = '... '
def execute(context):
sc = context.space_data
try:
line_object = sc.history[-1]
except:
return {'CANCELLED'}
console, stdout, stderr = get_console(hash(context.region))
# redirect output
sys.stdout = stdout
sys.stderr = stderr
# dont allow the stdin to be used, can lock blender.
stdin_backup = sys.stdin
sys.stdin = None
if _BPY_MAIN_OWN:
main_mod_back = sys.modules["__main__"]
sys.modules["__main__"] = console._bpy_main_mod
# incase exception happens
line = "" # incase of encodingf error
is_multiline = False
try:
line = line_object.body
# run the console, "\n" executes a multiline statement
line_exec = line if line.strip() else "\n"
is_multiline = console.push(line_exec)
except:
# unlikely, but this can happen with unicode errors for example.
import traceback
stderr.write(traceback.format_exc())
if _BPY_MAIN_OWN:
sys.modules["__main__"] = main_mod_back
stdout.seek(0)
stderr.seek(0)
output = stdout.read()
output_err = stderr.read()
# cleanup
sys.stdout = sys.__stdout__
sys.stderr = sys.__stderr__
sys.last_traceback = None
# So we can reuse, clear all data
stdout.truncate(0)
stderr.truncate(0)
# special exception. its possible the command loaded a new user interface
if hash(sc) != hash(context.space_data):
return
bpy.ops.console.scrollback_append(text=sc.prompt + line, type='INPUT')
if is_multiline:
sc.prompt = PROMPT_MULTI
else:
sc.prompt = PROMPT
# insert a new blank line
bpy.ops.console.history_append(text="", current_character=0,
remove_duplicates=True)
# Insert the output into the editor
# not quite correct because the order might have changed,
# but ok 99% of the time.
if output:
add_scrollback(output, 'OUTPUT')
if output_err:
add_scrollback(output_err, 'ERROR')
# restore the stdin
sys.stdin = stdin_backup
# execute any hooks
for func, args in execute.hooks:
func(*args)
return {'FINISHED'}
execute.hooks = []
def autocomplete(context):
from console import intellisense
sc = context.space_data
console = get_console(hash(context.region))[0]
if not console:
return {'CANCELLED'}
# dont allow the stdin to be used, can lock blender.
# note: unlikely stdin would be used for autocomp. but its possible.
stdin_backup = sys.stdin
sys.stdin = None
scrollback = ""
scrollback_error = ""
if _BPY_MAIN_OWN:
main_mod_back = sys.modules["__main__"]
sys.modules["__main__"] = console._bpy_main_mod
try:
current_line = sc.history[-1]
line = current_line.body
# This function isnt aware of the text editor or being an operator
# just does the autocomp then copy its results back
result = intellisense.expand(
line=line,
cursor=current_line.current_character,
namespace=console.locals,
private=bpy.app.debug)
line_new = result[0]
current_line.body, current_line.current_character, scrollback = result
del result
# update sel. setting body should really do this!
ofs = len(line_new) - len(line)
sc.select_start += ofs
sc.select_end += ofs
except:
# unlikely, but this can happen with unicode errors for example.
# or if the api attribute access its self causes an error.
import traceback
scrollback_error = traceback.format_exc()
if _BPY_MAIN_OWN:
sys.modules["__main__"] = main_mod_back
# Separate automplete output by command prompts
if scrollback != '':
bpy.ops.console.scrollback_append(text=sc.prompt + current_line.body, type='INPUT')
# Now we need to copy back the line from blender back into the
# text editor. This will change when we dont use the text editor
# anymore
if scrollback:
add_scrollback(scrollback, 'INFO')
if scrollback_error:
add_scrollback(scrollback_error, 'ERROR')
# restore the stdin
sys.stdin = stdin_backup
context.area.tag_redraw()
return {'FINISHED'}
def banner(context):
sc = context.space_data
version_string = sys.version.strip().replace('\n', ' ')
add_scrollback("PYTHON INTERACTIVE CONSOLE %s" % version_string, 'OUTPUT')
add_scrollback("", 'OUTPUT')
add_scrollback("Command History: Up/Down Arrow", 'OUTPUT')
add_scrollback("Cursor: Left/Right Home/End", 'OUTPUT')
add_scrollback("Remove: Backspace/Delete", 'OUTPUT')
add_scrollback("Execute: Enter", 'OUTPUT')
add_scrollback("Autocomplete: Ctrl+Space", 'OUTPUT')
add_scrollback("Ctrl +/- Wheel: Zoom", 'OUTPUT')
add_scrollback("Builtin Modules: bpy, bpy.data, bpy.ops, bpy.props, bpy.types, bpy.context, bpy.utils, bgl, blf, mathutils", 'OUTPUT')
add_scrollback("Convenience Imports: from mathutils import *; from math import *", 'OUTPUT')
add_scrollback("", 'OUTPUT')
# add_scrollback(" WARNING!!! Blender 2.5 API is subject to change, see API reference for more info.", 'ERROR')
# add_scrollback("", 'OUTPUT')
sc.prompt = PROMPT
return {'FINISHED'}

View File

@@ -0,0 +1,78 @@
# ##### BEGIN GPL LICENSE BLOCK #####
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
import os
import bpy
language_id = 'shell'
def add_scrollback(text, text_type):
for l in text.split('\n'):
bpy.ops.console.scrollback_append(text=l.replace('\t', ' '),
type=text_type)
def shell_run(text):
import subprocess
val, output = subprocess.getstatusoutput(text)
if not val:
style = 'OUTPUT'
else:
style = 'ERROR'
add_scrollback(output, style)
PROMPT = '$ '
def execute(context):
sc = context.space_data
try:
line = sc.history[-1].body
except:
return {'CANCELLED'}
bpy.ops.console.scrollback_append(text=sc.prompt + line, type='INPUT')
shell_run(line)
# insert a new blank line
bpy.ops.console.history_append(text="", current_character=0,
remove_duplicates=True)
sc.prompt = os.getcwd() + PROMPT
return {'FINISHED'}
def autocomplete(context):
# sc = context.space_data
# TODO
return {'CANCELLED'}
def banner(context):
sc = context.space_data
shell_run("bash --version")
sc.prompt = os.getcwd() + PROMPT
return {'FINISHED'}

View File

@@ -23,5 +23,5 @@ def image_load(filepath, dirpath, place_holder=False, recursive=False, convert_c
import bpy
try:
return bpy.data.images.load(filepath)
except SystemError:
except RuntimeError:
return bpy.data.images.new("Untitled", 128, 128)

View File

@@ -19,13 +19,17 @@
# <pep8 compliant>
import bpy
from bpy.props import *
from bpy.props import StringProperty, BoolProperty
class ExportHelper:
filepath = StringProperty(name="File Path", description="Filepath used for exporting the file", maxlen=1024, default="", subtype='FILE_PATH')
check_existing = BoolProperty(name="Check Existing", description="Check and warn on overwriting existing files", default=True, options={'HIDDEN'})
# subclasses can override with decorator
# True == use ext, False == no ext, None == do nothing.
check_extension = True
def invoke(self, context, event):
import os
if not self.filepath:
@@ -41,12 +45,18 @@ class ExportHelper:
return {'RUNNING_MODAL'}
def check(self, context):
filepath = bpy.path.ensure_ext(self.filepath, self.filename_ext)
check_extension = self.check_extension
if check_extension is None:
return False
filepath = bpy.path.ensure_ext(self.filepath, self.filename_ext if check_extension else "")
if filepath != self.filepath:
self.filepath = filepath
return True
else:
return False
return False
class ImportHelper:
@@ -81,14 +91,14 @@ def create_derived_objects(scene, ob):
return False, None
if ob.dupli_type != 'NONE':
ob.create_dupli_list(scene)
ob.dupli_list_create(scene)
return True, [(dob.object, dob.matrix) for dob in ob.dupli_list]
else:
return False, [(ob, ob.matrix_world)]
def free_derived_objects(ob):
ob.free_dupli_list()
ob.dupli_list_clear()
def unpack_list(list_of_tuples):

View File

@@ -43,7 +43,7 @@ import bpy
# Append the specified property name on the the existing path
def path_add_property(path, prop):
if len(path):
if path:
return path + "." + prop
else:
return prop
@@ -52,16 +52,21 @@ def path_add_property(path, prop):
# Poll Callbacks
# selected objects
# selected objects (active object must be in object mode)
def RKS_POLL_selected_objects(ksi, context):
return context.active_object or len(context.selected_objects)
ob = context.active_object
if ob:
return ob.mode == 'OBJECT'
else:
return bool(context.selected_objects)
# selected bones
def RKS_POLL_selected_bones(ksi, context):
# we must be in Pose Mode, and there must be some bones selected
if (context.active_object) and (context.active_object.mode == 'POSE'):
if context.active_pose_bone or len(context.selected_pose_bones):
ob = context.active_object
if ob and ob.mode == 'POSE':
if context.active_pose_bone or context.selected_pose_bones:
return True
# nothing selected
@@ -78,13 +83,20 @@ def RKS_POLL_selected_items(ksi, context):
# all selected objects or pose bones, depending on which we've got
def RKS_ITER_selected_item(ksi, context, ks):
if (context.active_object) and (context.active_object.mode == 'POSE'):
ob = context.active_object
if ob and ob.mode == 'POSE':
for bone in context.selected_pose_bones:
ksi.generate(context, ks, bone)
else:
for ob in context.selected_objects:
ksi.generate(context, ks, ob)
# all select objects only
def RKS_ITER_selected_objects(ksi, context, ks):
for ob in context.selected_objects:
ksi.generate(context, ks, ob)
###########################
# Generate Callbacks

View File

@@ -0,0 +1,69 @@
# ##### BEGIN GPL LICENSE BLOCK #####
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
def mesh_linked_faces(mesh):
'''
Splits the mesh into connected parts,
these parts are returned as lists of faces.
used for seperating cubes from other mesh elements in the 1 mesh
'''
# Build vert face connectivity
vert_faces = [[] for i in range(len(mesh.vertices))]
for f in mesh.faces:
for v in f.vertices:
vert_faces[v].append(f)
# sort faces into connectivity groups
face_groups = [[f] for f in mesh.faces]
face_mapping = list(range(len(mesh.faces))) # map old, new face location
# Now clump faces iterativly
ok = True
while ok:
ok = False
for i, f in enumerate(mesh.faces):
mapped_index = face_mapping[f.index]
mapped_group = face_groups[mapped_index]
for v in f.vertices:
for nxt_f in vert_faces[v]:
if nxt_f != f:
nxt_mapped_index = face_mapping[nxt_f.index]
# We are not a part of the same group
if mapped_index != nxt_mapped_index:
ok = True
# Assign mapping to this group so they all map to this group
for grp_f in face_groups[nxt_mapped_index]:
face_mapping[grp_f.index] = mapped_index
# Move faces into this group
mapped_group.extend(face_groups[nxt_mapped_index])
# remove reference to the list
face_groups[nxt_mapped_index] = None
# return all face groups that are not null
# this is all the faces that are connected in their own lists.
return [fg for fg in face_groups if fg]

View File

@@ -152,6 +152,14 @@ class InfoStructRNA:
functions.append((identifier, attr))
return functions
def get_py_c_functions(self):
import types
functions = []
for identifier, attr in self._get_py_visible_attrs():
if type(attr) in (types.BuiltinMethodType, types.BuiltinFunctionType):
functions.append((identifier, attr))
return functions
def __str__(self):
txt = ""
@@ -199,7 +207,7 @@ class InfoPropertyRNA:
self.fixed_type = None
if self.type == "enum":
self.enum_items[:] = rna_prop.items.keys()
self.enum_items[:] = rna_prop.enum_items.keys()
self.is_enum_flag = rna_prop.is_enum_flag
else:
self.is_enum_flag = False
@@ -245,7 +253,7 @@ class InfoPropertyRNA:
return "%s=%s" % (self.identifier, default)
return self.identifier
def get_type_description(self, as_ret=False, as_arg=False, class_fmt="%s"):
def get_type_description(self, as_ret=False, as_arg=False, class_fmt="%s", collection_id="Collection"):
type_str = ""
if self.fixed_type is None:
type_str += self.type
@@ -269,9 +277,9 @@ class InfoPropertyRNA:
else:
if self.type == "collection":
if self.collection_type:
collection_str = (class_fmt % self.collection_type.identifier) + " collection of "
collection_str = (class_fmt % self.collection_type.identifier) + (" %s of " % collection_id)
else:
collection_str = "Collection of "
collection_str = "%s of " % collection_id
else:
collection_str = ""

View File

@@ -51,8 +51,8 @@ def textWrap(text, length=70):
def write_sysinfo(op):
output_filename = "system-info.txt"
if output_filename in bpy.data.texts.keys():
output = bpy.data.texts[output_filename]
output = bpy.data.texts.get(output_filename)
if output:
output.clear()
else:
output = bpy.data.texts.new(name=output_filename)
@@ -94,16 +94,19 @@ def write_sysinfo(op):
output.write('autosave: {}\n'.format(bpy.utils.user_resource('AUTOSAVE')))
output.write('tempdir: {}\n'.format(bpy.app.tempdir))
output.write('\nOpenGL\n')
output.write(lilies)
output.write('renderer:\t{}\n'.format(bgl.glGetString(bgl.GL_RENDERER)))
output.write('vendor:\t\t{}\n'.format(bgl.glGetString(bgl.GL_VENDOR)))
output.write('version:\t{}\n'.format(bgl.glGetString(bgl.GL_VERSION)))
output.write('extensions:\n')
if bpy.app.background:
output.write('\nOpenGL: missing, background mode\n')
else:
output.write('\nOpenGL\n')
output.write(lilies)
output.write('renderer:\t{}\n'.format(bgl.glGetString(bgl.GL_RENDERER)))
output.write('vendor:\t\t{}\n'.format(bgl.glGetString(bgl.GL_VENDOR)))
output.write('version:\t{}\n'.format(bgl.glGetString(bgl.GL_VERSION)))
output.write('extensions:\n')
glext = bgl.glGetString(bgl.GL_EXTENSIONS)
glext = textWrap(glext, 70)
for l in glext:
output.write('\t\t{}\n'.format(l))
glext = bgl.glGetString(bgl.GL_EXTENSIONS)
glext = textWrap(glext, 70)
for l in glext:
output.write('\t\t{}\n'.format(l))
op.report({'INFO'}, "System information generated in 'system-info.txt'")