=bmesh= merge from trunk at r36153
This commit is contained in:
@@ -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")
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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")))
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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='')
|
||||
]
|
||||
|
||||
@@ -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])
|
||||
|
||||
306
release/scripts/modules/console_python.py
Normal file
306
release/scripts/modules/console_python.py
Normal 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'}
|
||||
78
release/scripts/modules/console_shell.py
Normal file
78
release/scripts/modules/console_shell.py
Normal 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'}
|
||||
@@ -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)
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
69
release/scripts/modules/mesh_utils.py
Normal file
69
release/scripts/modules/mesh_utils.py
Normal 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]
|
||||
@@ -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 = ""
|
||||
|
||||
|
||||
@@ -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'")
|
||||
|
||||
Reference in New Issue
Block a user