diff options
author | Campbell Barton <ideasman42@gmail.com> | 2011-11-18 09:06:53 +0400 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2011-11-18 09:06:53 +0400 |
commit | 5600d214f1f2f05e98fd6f4d5f86bdff01e8b3f8 (patch) | |
tree | dc35ebf81c9d424e9136e754d71e86146273d9d2 | |
parent | 8a8566c8949f851cda3644073d1bff60b43b5abd (diff) | |
parent | c6c6a3578beae28a6c6c0164757ebbb694e7f816 (diff) |
svn merge ^/trunk/blender -r41939:41954
-rw-r--r-- | SConstruct | 5 | ||||
-rw-r--r-- | build_files/scons/tools/btools.py | 4 | ||||
-rw-r--r-- | doc/python_api/rst/info_gotcha.rst | 121 | ||||
-rw-r--r-- | release/scripts/modules/addon_utils.py | 11 | ||||
-rw-r--r-- | release/scripts/startup/bl_ui/__init__.py | 10 | ||||
-rw-r--r-- | release/scripts/startup/bl_ui/space_userpref.py | 18 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/fcurve.c | 8 | ||||
-rw-r--r-- | source/blender/blenlib/intern/DLRB_tree.c | 2 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_anim.c | 19 | ||||
-rw-r--r-- | source/blender/makesrna/RNA_types.h | 9 | ||||
-rw-r--r-- | source/blender/makesrna/intern/makesrna.c | 12 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_actuator.c | 86 | ||||
-rw-r--r-- | source/blender/python/BPY_extern.h | 2 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_driver.c | 35 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_driver.h | 2 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_rna.c | 107 | ||||
-rw-r--r-- | source/blenderplayer/bad_level_call_stubs/stubs.c | 2 | ||||
-rw-r--r-- | source/creator/CMakeLists.txt | 181 |
18 files changed, 431 insertions, 203 deletions
diff --git a/SConstruct b/SConstruct index b5075aa4345..cd4e31efeff 100644 --- a/SConstruct +++ b/SConstruct @@ -70,6 +70,7 @@ BlenderEnvironment = Blender.BlenderEnvironment B = Blender VERSION = btools.VERSION # This is used in creating the local config directories +VERSION_RELEASE_CYCLE = btools.VERSION_RELEASE_CYCLE ### globals ### platform = sys.platform @@ -524,6 +525,10 @@ if env['OURPLATFORM']!='darwin': if '__pycache__' in dn: # py3.2 cache dir dn.remove('__pycache__') + # only for testing builds + if VERSION_RELEASE_CYCLE == "release" and "addons_contrib" in dn: + dn.remove('addons_contrib') + dir = os.path.join(env['BF_INSTALLDIR'], VERSION) dir += os.sep + os.path.basename(scriptpath) + dp[len(scriptpath):] diff --git a/build_files/scons/tools/btools.py b/build_files/scons/tools/btools.py index 856231e3c84..4c826b12e89 100644 --- a/build_files/scons/tools/btools.py +++ b/build_files/scons/tools/btools.py @@ -52,7 +52,7 @@ def get_version(): else: ver_display = "%s%s" % (ver_base, ver_char) # assume release - return ver_base, ver_display + return ver_base, ver_display, ver_cycle raise Exception("%s: missing version string" % fname) @@ -80,7 +80,7 @@ def checkEndian(): # This is used in creating the local config directories -VERSION, VERSION_DISPLAY = get_version() +VERSION, VERSION_DISPLAY, VERSION_RELEASE_CYCLE = get_version() REVISION = get_revision() ENDIAN = checkEndian() diff --git a/doc/python_api/rst/info_gotcha.rst b/doc/python_api/rst/info_gotcha.rst index b17debbb15c..281f0689044 100644 --- a/doc/python_api/rst/info_gotcha.rst +++ b/doc/python_api/rst/info_gotcha.rst @@ -147,7 +147,7 @@ Armature Bones in Blender have three distinct data structures that contain them. .. note:: - In the following examples ``bpy.context.object`` is assumed to be an armature object. + In the following examples ``bpy.context.object`` is assumed to be an armature object. Edit Bones @@ -163,11 +163,11 @@ This is only possible in edit mode. This will be empty outside of editmode. - >>> mybones = bpy.context.selected_editable_bones + >>> mybones = bpy.context.selected_editable_bones Returns an editbone only in edit mode. - >>> bpy.context.active_bone + >>> bpy.context.active_bone Bones (Object Mode) @@ -179,15 +179,15 @@ Example using :class:`bpy.types.Bone` in object or pose mode: Returns a bone (not an editbone) outside of edit mode - >>> bpy.context.active_bone + >>> bpy.context.active_bone This works, as with blender the setting can be edited in any mode - >>> bpy.context.object.data.bones["Bone"].use_deform = True + >>> bpy.context.object.data.bones["Bone"].use_deform = True Accessible but read-only - >>> tail = myobj.data.bones["Bone"].tail + >>> tail = myobj.data.bones["Bone"].tail Pose Bones @@ -199,20 +199,20 @@ Examples using :class:`bpy.types.PoseBone` in object or pose mode: .. code-block:: python - # Gets the name of the first constraint (if it exists) - bpy.context.object.pose.bones["Bone"].constraints[0].name + # Gets the name of the first constraint (if it exists) + bpy.context.object.pose.bones["Bone"].constraints[0].name - # Gets the last selected pose bone (pose mode only) - bpy.context.active_pose_bone + # Gets the last selected pose bone (pose mode only) + bpy.context.active_pose_bone .. note:: - Notice the pose is accessed from the object rather than the object data, this is why blender can have 2 or more objects sharing the same armature in different poses. + Notice the pose is accessed from the object rather than the object data, this is why blender can have 2 or more objects sharing the same armature in different poses. .. note:: - Strictly speaking PoseBone's are not bones, they are just the state of the armature, stored in the :class:`bpy.types.Object` rather than the :class:`bpy.types.Armature`, the real bones are however accessible from the pose bones - :class:`bpy.types.PoseBone.bone` + Strictly speaking PoseBone's are not bones, they are just the state of the armature, stored in the :class:`bpy.types.Object` rather than the :class:`bpy.types.Armature`, the real bones are however accessible from the pose bones - :class:`bpy.types.PoseBone.bone` Armature Mode Switching @@ -223,6 +223,86 @@ While writing scripts that deal with armatures you may find you have to switch b This is mainly an issue with editmode since pose data can be manipulated without having to be in pose mode, however for operator access you may still need to enter pose mode. +Data Names +========== + + +Naming Limitations +------------------ + +A common mistake is to assume newly created data is given the requested name. + +This can cause bugs when you add some data (normally imported) and then reference it later by name. + +.. code-block:: python + + bpy.data.meshes.new(name=meshid) + + # normally some code, function calls... + bpy.data.meshes[meshid] + + +Or with name assignment... + +.. code-block:: python + + obj.name = objname + + # normally some code, function calls... + obj = bpy.data.meshes[objname] + + +Data names may not match the assigned values if they exceed the maximum length, are already used or an empty string. + + +Its better practice not to reference objects by names at all, once created you can store the data in a list, dictionary, on a class etc, there is rarely a reason to have to keep searching for the same data by name. + + +If you do need to use name references, its best to use a dictionary to maintain a mapping between the names of the imported assets and the newly created data, this way you don't run this risk of referencing existing data from the blend file, or worse modifying it. + +.. code-block:: python + + # typically declared in the main body of the function. + mesh_name_mapping = {} + + mesh = bpy.data.meshes.new(name=meshid) + mesh_name_mapping[meshid] = mesh + + # normally some code, or function calls... + + # use own dictionary rather then bpy.data + mesh = mesh_name_mapping[meshid] + + +Library Collisions +------------------ + +Blender keeps data names unique - :class:`bpy.types.ID.name` so you can't name two objects, meshes, scenes etc the same thing by accident. + +However when linking in library data from another blend file naming collisions can occur, so its best to avoid referencing data by name at all. + +This can be tricky at times and not even blender handles this correctly in some case (when selecting the modifier object for eg you can't select between multiple objects with the same name), but its still good to try avoid problems in this area. + + +If you need to select between local and library data, there is a feature in ``bpy.data`` members to allow for this. + +.. code-block:: python + + # typical name lookup, could be local or library. + obj = bpy.data.objects["my_obj"] + + # library object name look up using a pair + # where the second argument is the library path matching bpy.types.Library.filepath + obj = bpy.data.objects["my_obj", "//my_lib.blend"] + + # local object name look up using a pair + # where the second argument excludes library data from being returned. + obj = bpy.data.objects["my_obj", None] + + # both the examples above also works for 'get' + obj = bpy.data.objects.get(("my_obj", None)) + + Relative File Paths =================== @@ -230,12 +310,12 @@ Blenders relative file paths are not compatible with standard python modules suc Built in python functions don't understand blenders ``//`` prefix which denotes the blend file path. -A common case where you would run into this problem is when exporting a material with assosiated image paths. +A common case where you would run into this problem is when exporting a material with associated image paths. >>> bpy.path.abspath(image.filepath) -When using blender data from linked libraries there is an unfortunate complication since the path will be relative to the library rather then the open blend file. When the data block may be from an external blend file pass the library argument from the `bpy.types.ID`. +When using blender data from linked libraries there is an unfortunate complication since the path will be relative to the library rather then the open blend file. When the data block may be from an external blend file pass the library argument from the :class:`bpy.types.ID`. >>> bpy.path.abspath(image.filepath, library=image.library) @@ -289,7 +369,7 @@ Unicode encoding/decoding is a big topic with comprehensive python documentation * To print paths or to include them in the user interface use ``repr(path)`` first or ``"%r" % path`` with string formatting. -* **Possibly** - use bytes instead of python strings, when reading some input its less trouble to read it as binary data though you will still need to deciede how to treat any strings you want to use with Blender, some importers do this. +* **Possibly** - use bytes instead of python strings, when reading some input its less trouble to read it as binary data though you will still need to decide how to treat any strings you want to use with Blender, some importers do this. Strange errors using 'threading' module @@ -458,3 +538,14 @@ Removing Data **Any** data that you remove shouldn't be modified or accessed afterwards, this includes f-curves, drivers, render layers, timeline markers, modifiers, constraints along with objects, scenes, groups, bones.. etc. This is a problem in the API at the moment that we should eventually solve. + + +sys.exit +======== + +Some python modules will call sys.exit() themselves when an error occurs, while not common behavior this is something to watch out for because it may seem as if blender is crashing since sys.exit() will quit blender immediately. + +For example, the ``optparse`` module will print an error and exit if the arguments are invalid. + +An ugly way of troubleshooting this is to set ``sys.exit = None`` and see what line of python code is quitting, you could of course replace ``sys.exit``/ with your own function but manipulating python in this way is bad practice. + diff --git a/release/scripts/modules/addon_utils.py b/release/scripts/modules/addon_utils.py index 26611fb93ad..1bd218ad92a 100644 --- a/release/scripts/modules/addon_utils.py +++ b/release/scripts/modules/addon_utils.py @@ -62,7 +62,7 @@ def modules(module_cache): path_list = paths() # fake module importing - def fake_module(mod_name, mod_path, speedy=True): + def fake_module(mod_name, mod_path, speedy=True, force_support=None): global error_encoding if _bpy.app.debug: @@ -134,6 +134,9 @@ def modules(module_cache): traceback.print_exc() raise + if force_support is not None: + mod.bl_info["support"] = force_support + return mod else: return None @@ -141,6 +144,10 @@ def modules(module_cache): modules_stale = set(module_cache.keys()) for path in path_list: + + # force all contrib addons to be 'TESTING' + force_support = 'TESTING' if path.endswith("addons_contrib") else None + for mod_name, mod_path in _bpy.path.module_names(path): modules_stale -= {mod_name} mod = module_cache.get(mod_name) @@ -161,7 +168,7 @@ def modules(module_cache): mod = None if mod is None: - mod = fake_module(mod_name, mod_path) + mod = fake_module(mod_name, mod_path, force_support=force_support) if mod: module_cache[mod_name] = mod diff --git a/release/scripts/startup/bl_ui/__init__.py b/release/scripts/startup/bl_ui/__init__.py index 3db768f73fe..6aa08a7f50d 100644 --- a/release/scripts/startup/bl_ui/__init__.py +++ b/release/scripts/startup/bl_ui/__init__.py @@ -116,11 +116,15 @@ def register(): ) WindowManager.addon_support = EnumProperty( - items=[('OFFICIAL', "Official", ""), - ('COMMUNITY', 'Community', ""), + items=[('OFFICIAL', "Official", "Officially supported"), + ('COMMUNITY', "Community", "Maintained by community developers"), + ('TESTING', "Testing", "Newly contributed scripts (excluded from release builds)"), ], name="Support", - description="Display support level", default={'OFFICIAL', 'COMMUNITY'}, options={'ENUM_FLAG'}) + description="Display support level", + default={'OFFICIAL', 'COMMUNITY'}, + options={'ENUM_FLAG'}, + ) # done... diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py index 665d790f832..c889e7f3de6 100644 --- a/release/scripts/startup/bl_ui/space_userpref.py +++ b/release/scripts/startup/bl_ui/space_userpref.py @@ -891,6 +891,12 @@ class USERPREF_PT_addons(Panel): bl_region_type = 'WINDOW' bl_options = {'HIDE_HEADER'} + _support_icon_mapping = { + 'OFFICIAL': 'FILE_BLEND', + 'COMMUNITY': 'POSE_DATA', + 'TESTING': 'MOD_EXPLODE', + } + @classmethod def poll(cls, context): userpref = context.user_preferences @@ -931,12 +937,13 @@ class USERPREF_PT_addons(Panel): split = layout.split(percentage=0.2) col = split.column() col.prop(context.window_manager, "addon_search", text="", icon='VIEWZOOM') - col.label(text="Categories") - col.prop(context.window_manager, "addon_filter", expand=True) col.label(text="Supported Level") col.prop(context.window_manager, "addon_support", expand=True) + col.label(text="Categories") + col.prop(context.window_manager, "addon_filter", expand=True) + col = split.column() # set in addon_utils.modules(...) @@ -995,12 +1002,7 @@ class USERPREF_PT_addons(Panel): rowsub.label(icon='ERROR') # icon showing support level. - if info["support"] == 'OFFICIAL': - rowsub.label(icon='FILE_BLEND') - elif info["support"] == 'COMMUNITY': - rowsub.label(icon='POSE_DATA') - else: - rowsub.label(icon='QUESTION') + rowsub.label(icon=self._support_icon_mapping.get(info["support"], 'QUESTION')) if is_enabled: row.operator("wm.addon_disable", icon='CHECKBOX_HLT', text="", emboss=False).module = module_name diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index 5ab997d2c54..4bb9dc47fda 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -1576,7 +1576,7 @@ float driver_get_variable_value (ChannelDriver *driver, DriverVar *dvar) * - "evaltime" is the frame at which F-Curve is being evaluated * - has to return a float value */ -static float evaluate_driver (ChannelDriver *driver, float UNUSED(evaltime)) +static float evaluate_driver (ChannelDriver *driver, const float evaltime) { DriverVar *dvar; @@ -1663,8 +1663,10 @@ static float evaluate_driver (ChannelDriver *driver, float UNUSED(evaltime)) /* this evaluates the expression using Python,and returns its result: * - on errors it reports, then returns 0.0f */ - driver->curval= BPY_driver_exec(driver); + driver->curval= BPY_driver_exec(driver, evaltime); } +#else /* WITH_PYTHON*/ + (void)evaltime; #endif /* WITH_PYTHON*/ } break; @@ -2087,7 +2089,7 @@ static float fcurve_eval_samples (FCurve *fcu, FPoint *fpts, float evaltime) /* Evaluate and return the value of the given F-Curve at the specified frame ("evaltime") * Note: this is also used for drivers */ -float evaluate_fcurve (FCurve *fcu, float evaltime) +float evaluate_fcurve (FCurve *fcu, float evaltime) { float cvalue= 0.0f; float devaltime; diff --git a/source/blender/blenlib/intern/DLRB_tree.c b/source/blender/blenlib/intern/DLRB_tree.c index 72743e38d4c..4507d70e339 100644 --- a/source/blender/blenlib/intern/DLRB_tree.c +++ b/source/blender/blenlib/intern/DLRB_tree.c @@ -209,7 +209,7 @@ DLRBT_Node *BLI_dlrbTree_search_exact (DLRBT_Tree *tree, DLRBT_Comparator_FP cmp } } - /* return the nearest matching node */ + /* return the exactly matching node */ return (found == 1) ? (node) : (NULL); } diff --git a/source/blender/editors/interface/interface_anim.c b/source/blender/editors/interface/interface_anim.c index 1edd43d4e01..5e095bae922 100644 --- a/source/blender/editors/interface/interface_anim.c +++ b/source/blender/editors/interface/interface_anim.c @@ -164,24 +164,7 @@ int ui_but_anim_expression_create(uiBut *but, const char *str) /* set the expression */ // TODO: need some way of identifying variables used BLI_strncpy_utf8(driver->expression, str, sizeof(driver->expression)); - - /* FIXME: for now, assume that - * - for expressions, users are likely to be using "frame" -> current frame" as a variable - * - driver_add_new_variable() adds a single-prop variable by default - */ - { - DriverVar *dvar; - DriverTarget *dtar; - - dvar = driver_add_new_variable(driver); - BLI_strncpy(dvar->name, "frame", sizeof(dvar->name)); - - dtar = &dvar->targets[0]; - dtar->id = (ID *)CTX_data_scene(C); // XXX: should we check that C is valid first? - dtar->idtype= ID_SCE; - dtar->rna_path = BLI_sprintfN("frame_current"); - } - + /* updates */ driver->flag |= DRIVER_FLAG_RECOMPILE; WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME, NULL); diff --git a/source/blender/makesrna/RNA_types.h b/source/blender/makesrna/RNA_types.h index e768594fe73..85869115e79 100644 --- a/source/blender/makesrna/RNA_types.h +++ b/source/blender/makesrna/RNA_types.h @@ -303,13 +303,14 @@ typedef struct ParameterDynAlloc { typedef enum FunctionFlag { FUNC_NO_SELF = 1, /* for static functions */ - FUNC_USE_CONTEXT = 2, - FUNC_USE_REPORTS = 4, + FUNC_USE_MAIN = 2, + FUNC_USE_CONTEXT = 4, + FUNC_USE_REPORTS = 8, FUNC_USE_SELF_ID = 2048, /* registering */ - FUNC_REGISTER = 8, - FUNC_REGISTER_OPTIONAL = 8|16, + FUNC_REGISTER = 16, + FUNC_REGISTER_OPTIONAL = 16|32, /* internal flags */ FUNC_BUILTIN = 128, diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c index 6dbf7b9c553..c21685c9add 100644 --- a/source/blender/makesrna/intern/makesrna.c +++ b/source/blender/makesrna/intern/makesrna.c @@ -1709,6 +1709,12 @@ static void rna_def_function_funcs(FILE *f, StructDefRNA *dsrna, FunctionDefRNA first= 0; } + if(func->flag & FUNC_USE_MAIN) { + if(!first) fprintf(f, ", "); + first= 0; + fprintf(f, "CTX_data_main(C)"); /* may have direct access later */ + } + if(func->flag & FUNC_USE_CONTEXT) { if(!first) fprintf(f, ", "); first= 0; @@ -2007,6 +2013,12 @@ static void rna_generate_static_parameter_prototypes(BlenderRNA *brna, StructRNA first= 0; } + if(func->flag & FUNC_USE_MAIN) { + if(!first) fprintf(f, ", "); + first= 0; + fprintf(f, "Main *bmain"); + } + if(func->flag & FUNC_USE_CONTEXT) { if(!first) fprintf(f, ", "); first= 0; diff --git a/source/blender/makesrna/intern/rna_actuator.c b/source/blender/makesrna/intern/rna_actuator.c index db71dee26ce..b941e9ebed7 100644 --- a/source/blender/makesrna/intern/rna_actuator.c +++ b/source/blender/makesrna/intern/rna_actuator.c @@ -733,37 +733,37 @@ static void rna_def_object_actuator(BlenderRNA *brna) prop= RNA_def_property(srna, "force_max_x", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "dloc[0]"); RNA_def_property_ui_range(prop, -100.0, 100.0, 1, 2); - RNA_def_property_ui_text(prop, "Max", "Set the upper limit for force"); + RNA_def_property_ui_text(prop, "Max", "Upper limit for X force"); RNA_def_property_update(prop, NC_LOGIC, NULL); prop= RNA_def_property(srna, "force_min_x", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "drot[0]"); RNA_def_property_ui_range(prop, -100.0, 100.0, 1, 2); - RNA_def_property_ui_text(prop, "Min", "Set the lower limit for force"); + RNA_def_property_ui_text(prop, "Min", "Lower limit for X force"); RNA_def_property_update(prop, NC_LOGIC, NULL); prop= RNA_def_property(srna, "force_max_y", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "dloc[1]"); RNA_def_property_ui_range(prop, -100.0, 100.0, 1, 2); - RNA_def_property_ui_text(prop, "Max", "Set the upper limit for force"); + RNA_def_property_ui_text(prop, "Max", "Upper limit for Y force"); RNA_def_property_update(prop, NC_LOGIC, NULL); prop= RNA_def_property(srna, "force_min_y", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "drot[1]"); RNA_def_property_ui_range(prop, -100.0, 100.0, 1, 2); - RNA_def_property_ui_text(prop, "Min", "Set the lower limit for force"); + RNA_def_property_ui_text(prop, "Min", "Lower limit for Y force"); RNA_def_property_update(prop, NC_LOGIC, NULL); prop= RNA_def_property(srna, "force_max_z", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "dloc[2]"); RNA_def_property_ui_range(prop, -100.0, 100.0, 1, 2); - RNA_def_property_ui_text(prop, "Max", "Set the upper limit for force"); + RNA_def_property_ui_text(prop, "Max", "Upper limit for Z force"); RNA_def_property_update(prop, NC_LOGIC, NULL); prop= RNA_def_property(srna, "force_min_z", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "drot[2]"); RNA_def_property_ui_range(prop, -100.0, 100.0, 1, 2); - RNA_def_property_ui_text(prop, "Min", "Set the lower limit for force"); + RNA_def_property_ui_text(prop, "Min", "Lower limit for Z force"); RNA_def_property_update(prop, NC_LOGIC, NULL); /* floats 3 Arrays*/ @@ -771,42 +771,42 @@ static void rna_def_object_actuator(BlenderRNA *brna) RNA_def_property_float_sdna(prop, NULL, "dloc"); RNA_def_property_array(prop, 3); RNA_def_property_ui_range(prop, -10000.0, 10000.0, 10, 2); - RNA_def_property_ui_text(prop, "Loc", "Sets the location"); + RNA_def_property_ui_text(prop, "Loc", "Location"); RNA_def_property_update(prop, NC_LOGIC, NULL); prop= RNA_def_property(srna, "offset_rotation", PROP_FLOAT, PROP_EULER); RNA_def_property_float_sdna(prop, NULL, "drot"); RNA_def_property_array(prop, 3); RNA_def_property_ui_range(prop, -10000.0, 10000.0, 10, 2); - RNA_def_property_ui_text(prop, "Rot", "Sets the rotation"); + RNA_def_property_ui_text(prop, "Rot", "Rotation"); RNA_def_property_update(prop, NC_LOGIC, NULL); prop= RNA_def_property(srna, "force", PROP_FLOAT, PROP_XYZ); RNA_def_property_float_sdna(prop, NULL, "forceloc"); RNA_def_property_array(prop, 3); RNA_def_property_ui_range(prop, -10000.0, 10000.0, 10, 2); - RNA_def_property_ui_text(prop, "Force", "Sets the force"); + RNA_def_property_ui_text(prop, "Force", "Force"); RNA_def_property_update(prop, NC_LOGIC, NULL); prop= RNA_def_property(srna, "torque", PROP_FLOAT, PROP_XYZ); RNA_def_property_float_sdna(prop, NULL, "forcerot"); RNA_def_property_array(prop, 3); RNA_def_property_ui_range(prop, -10000.0, 10000.0, 10, 2); - RNA_def_property_ui_text(prop, "Torque", "Sets the torque"); + RNA_def_property_ui_text(prop, "Torque", "Torque"); RNA_def_property_update(prop, NC_LOGIC, NULL); prop= RNA_def_property(srna, "linear_velocity", PROP_FLOAT, PROP_XYZ); RNA_def_property_float_sdna(prop, NULL, "linearvelocity"); RNA_def_property_array(prop, 3); RNA_def_property_ui_range(prop, -10000.0, 10000.0, 10, 2); - RNA_def_property_ui_text(prop, "Linear Velocity", "Sets the linear velocity (in Servo mode it sets the target relative linear velocity, it will be achieved by automatic application of force. Null velocity is a valid target)"); + RNA_def_property_ui_text(prop, "Linear Velocity", "Linear velocity (in Servo mode it sets the target relative linear velocity, it will be achieved by automatic application of force - Null velocity is a valid target)"); RNA_def_property_update(prop, NC_LOGIC, NULL); prop= RNA_def_property(srna, "angular_velocity", PROP_FLOAT, PROP_XYZ); RNA_def_property_float_sdna(prop, NULL, "angularvelocity"); RNA_def_property_array(prop, 3); RNA_def_property_ui_range(prop, -10000.0, 10000.0, 10, 2); - RNA_def_property_ui_text(prop, "Angular Velocity", "Sets the angular velocity"); + RNA_def_property_ui_text(prop, "Angular Velocity", "Angular velocity"); RNA_def_property_update(prop, NC_LOGIC, NULL); /* booleans */ @@ -902,14 +902,14 @@ static void rna_def_camera_actuator(BlenderRNA *brna) RNA_def_property_float_sdna(prop, NULL, "damping"); RNA_def_property_range(prop, 0, 10.0); RNA_def_property_ui_range(prop, 0, 5.0, 1, 2); - RNA_def_property_ui_text(prop, "Damping", "Specify the strength of the constraint that drive the camera behind the target"); + RNA_def_property_ui_text(prop, "Damping", "Strength of the constraint that drives the camera behind the target"); RNA_def_property_update(prop, NC_LOGIC, NULL); /* x/y */ prop= RNA_def_property(srna, "axis", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "axis"); RNA_def_property_enum_items(prop, prop_axis_items); - RNA_def_property_ui_text(prop, "Axis", "Specify the axis the Camera will try to get behind"); + RNA_def_property_ui_text(prop, "Axis", "Axis the Camera will try to get behind"); RNA_def_property_update(prop, NC_LOGIC, NULL); } @@ -947,12 +947,12 @@ static void rna_def_sound_actuator(BlenderRNA *brna) prop= RNA_def_property(srna, "volume", PROP_FLOAT, PROP_NONE); RNA_def_property_ui_range(prop, 0.0, 1.0, 1, 2); RNA_def_property_range(prop, 0.0, 2.0); - RNA_def_property_ui_text(prop, "Volume", "Sets the initial volume of the sound"); + RNA_def_property_ui_text(prop, "Volume", "Initial volume of the sound"); RNA_def_property_update(prop, NC_LOGIC, NULL); prop= RNA_def_property(srna, "pitch", PROP_FLOAT, PROP_NONE); RNA_def_property_ui_range(prop, -12.0, 12.0, 1, 2); - RNA_def_property_ui_text(prop, "Pitch", "Sets the pitch of the sound"); + RNA_def_property_ui_text(prop, "Pitch", "Pitch of the sound"); RNA_def_property_update(prop, NC_LOGIC, NULL); /* floats - 3D Parameters */ @@ -989,7 +989,7 @@ static void rna_def_sound_actuator(BlenderRNA *brna) prop= RNA_def_property(srna, "cone_outer_gain_3d", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "sound3D.cone_outer_gain"); RNA_def_property_ui_range(prop, 0.0, 1.0, 1, 2); - RNA_def_property_ui_text(prop, "Cone Outer Gain", "The gain outside the outer cone. The gain in the outer cone will be interpolated between this value and the normal gain in the inner cone"); + RNA_def_property_ui_text(prop, "Cone Outer Gain", "The gain outside the outer cone (the gain in the outer cone will be interpolated between this value and the normal gain in the inner cone)"); RNA_def_property_update(prop, NC_LOGIC, NULL); prop= RNA_def_property(srna, "cone_outer_angle_3d", PROP_FLOAT, PROP_NONE); @@ -1118,7 +1118,7 @@ static void rna_def_constraint_actuator(BlenderRNA *brna) prop= RNA_def_property(srna, "direction", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "mode"); RNA_def_property_enum_items(prop, prop_direction_items); - RNA_def_property_ui_text(prop, "Direction", "Set the direction of the ray"); + RNA_def_property_ui_text(prop, "Direction", "Direction of the ray"); RNA_def_property_update(prop, NC_LOGIC, NULL); prop= RNA_def_property(srna, "direction_axis", PROP_ENUM, PROP_NONE); @@ -1150,7 +1150,7 @@ static void rna_def_constraint_actuator(BlenderRNA *brna) prop= RNA_def_property(srna, "range", PROP_FLOAT, PROP_NONE); RNA_def_property_float_funcs(prop, "rna_ConstraintActuator_range_get", "rna_ConstraintActuator_range_set", NULL); RNA_def_property_ui_range(prop, 0.f, 2000.f, 1, 2); - RNA_def_property_ui_text(prop, "Range", "Set the maximum length of ray"); + RNA_def_property_ui_text(prop, "Range", "Maximum length of ray"); RNA_def_property_update(prop, NC_LOGIC, NULL); prop= RNA_def_property(srna, "distance", PROP_FLOAT, PROP_NONE); @@ -1169,7 +1169,7 @@ static void rna_def_constraint_actuator(BlenderRNA *brna) //XXX add magic property lookup prop= RNA_def_property(srna, "property", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "matprop"); - RNA_def_property_ui_text(prop, "Property", "Ray detect only Objects with this property"); + RNA_def_property_ui_text(prop, "Property", "Ray detects only Objects with this property"); RNA_def_property_update(prop, NC_LOGIC, NULL); prop= RNA_def_property(srna, "time", PROP_INT, PROP_NONE); @@ -1201,14 +1201,14 @@ static void rna_def_constraint_actuator(BlenderRNA *brna) prop= RNA_def_property(srna, "angle_min", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "minloc[0]"); RNA_def_property_range(prop, 0.0, 180.0); - RNA_def_property_ui_text(prop, "Min Angle", "Minimum angle (in degree) to maintain with target direction. No correction is done if angle with target direction is between min and max"); + RNA_def_property_ui_text(prop, "Min Angle", "Minimum angle (in degree) to maintain with target direction (no correction is done if angle with target direction is between min and max)"); RNA_def_property_update(prop, NC_LOGIC, NULL); //XXX TODO - use radians internally then change to PROP_ANGLE prop= RNA_def_property(srna, "angle_max", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "maxloc[0]"); RNA_def_property_range(prop, 0.0, 180.0); - RNA_def_property_ui_text(prop, "Max Angle", "Maximum angle (in degree) allowed with target direction. No correction is done if angle with target direction is between min and max"); + RNA_def_property_ui_text(prop, "Max Angle", "Maximum angle (in degree) allowed with target direction (no correction is done if angle with target direction is between min and max)"); RNA_def_property_update(prop, NC_LOGIC, NULL); /* ACT_CONST_TYPE_FH */ @@ -1310,7 +1310,7 @@ static void rna_def_edit_object_actuator(BlenderRNA *brna) RNA_def_property_struct_type(prop, "Object"); RNA_def_property_pointer_sdna(prop, NULL, "ob"); RNA_def_property_flag(prop, PROP_EDITABLE); - RNA_def_property_ui_text(prop, "Object", "Add this Object and all its children (cant be on an visible layer)"); + RNA_def_property_ui_text(prop, "Object", "Add this Object and all its children (can't be on a visible layer)"); RNA_def_property_update(prop, NC_LOGIC, NULL); prop= RNA_def_property(srna, "track_object", PROP_POINTER, PROP_NONE); @@ -1411,13 +1411,13 @@ static void rna_def_scene_actuator(BlenderRNA *brna) prop= RNA_def_property(srna, "camera", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "Object"); RNA_def_property_flag(prop, PROP_EDITABLE); - RNA_def_property_ui_text(prop, "Camera Object", "Set this Camera. Leave empty to refer to self object"); + RNA_def_property_ui_text(prop, "Camera Object", "Set this Camera (leave empty to refer to self object)"); RNA_def_property_update(prop, NC_LOGIC, NULL); prop= RNA_def_property(srna, "scene", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "Scene"); RNA_def_property_flag(prop, PROP_EDITABLE); - RNA_def_property_ui_text(prop, "Scene", "Set the Scene to be added/removed/paused/resumed"); + RNA_def_property_ui_text(prop, "Scene", "Scene to be added/removed/paused/resumed"); RNA_def_property_update(prop, NC_LOGIC, NULL); /* XXX no need for those tooltips. to remove soon @@ -1462,7 +1462,7 @@ static void rna_def_random_actuator(BlenderRNA *brna) prop= RNA_def_property(srna, "seed", PROP_INT, PROP_NONE); RNA_def_property_ui_range(prop, 0, 1000, 1, 1); RNA_def_property_range(prop, 0, MAXFRAME); - RNA_def_property_ui_text(prop, "Seed", "Initial seed of the random generator. Use Python for more freedom (choose 0 for not random)"); + RNA_def_property_ui_text(prop, "Seed", "Initial seed of the random generator, use Python for more freedom (choose 0 for not random)"); RNA_def_property_update(prop, NC_LOGIC, NULL); prop= RNA_def_property(srna, "property", PROP_STRING, PROP_NONE); @@ -1491,7 +1491,7 @@ static void rna_def_random_actuator(BlenderRNA *brna) prop= RNA_def_property(srna, "chance", PROP_FLOAT, PROP_PERCENTAGE); RNA_def_property_float_sdna(prop, NULL, "float_arg_1"); RNA_def_property_range(prop, 0.0, 1.0); - RNA_def_property_ui_text(prop, "Chance", "Pick a number between 0 and 1. Success if you stay below this value"); + RNA_def_property_ui_text(prop, "Chance", "Pick a number between 0 and 1, success if it's below this value"); RNA_def_property_update(prop, NC_LOGIC, NULL); /* ACT_RANDOM_INT_CONST */ @@ -1505,13 +1505,13 @@ static void rna_def_random_actuator(BlenderRNA *brna) prop= RNA_def_property(srna, "int_min", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "int_arg_1"); RNA_def_property_range(prop, -1000, 1000); - RNA_def_property_ui_text(prop, "Min", "Choose a number from a range. Lower boundary of the range"); + RNA_def_property_ui_text(prop, "Min", "Choose a number from a range: lower boundary of the range"); RNA_def_property_update(prop, NC_LOGIC, NULL); prop= RNA_def_property(srna, "int_max", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "int_arg_2"); RNA_def_property_range(prop, -1000, 1000); - RNA_def_property_ui_text(prop, "Max", "Choose a number from a range. Upper boundary of the range"); + RNA_def_property_ui_text(prop, "Max", "Choose a number from a range: upper boundary of the range"); RNA_def_property_update(prop, NC_LOGIC, NULL); /* ACT_RANDOM_INT_POISSON */ @@ -1532,26 +1532,26 @@ static void rna_def_random_actuator(BlenderRNA *brna) prop= RNA_def_property(srna, "float_min", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "float_arg_1"); RNA_def_property_range(prop, -1000.0, 1000.0); - RNA_def_property_ui_text(prop, "Min", "Choose a number from a range. Lower boundary of the range"); + RNA_def_property_ui_text(prop, "Min", "Choose a number from a range: lower boundary of the range"); RNA_def_property_update(prop, NC_LOGIC, NULL); prop= RNA_def_property(srna, "float_max", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "float_arg_2"); RNA_def_property_range(prop, -1000.0, 1000.0); - RNA_def_property_ui_text(prop, "Max", "Choose a number from a range. Upper boundary of the range"); + RNA_def_property_ui_text(prop, "Max", "Choose a number from a range: upper boundary of the range"); RNA_def_property_update(prop, NC_LOGIC, NULL); /* ACT_RANDOM_FLOAT_NORMAL */ prop= RNA_def_property(srna, "float_mean", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "float_arg_1"); RNA_def_property_range(prop, -1000.0, 1000.0); - RNA_def_property_ui_text(prop, "Mean", "A normal distribution. Mean of the distribution"); + RNA_def_property_ui_text(prop, "Mean", "A normal distribution: mean of the distribution"); RNA_def_property_update(prop, NC_LOGIC, NULL); prop= RNA_def_property(srna, "standard_derivation", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "float_arg_2"); RNA_def_property_range(prop, -1000.0, 1000.0); - RNA_def_property_ui_text(prop, "SD", "A normal distribution. Standard deviation of the distribution"); + RNA_def_property_ui_text(prop, "SD", "A normal distribution: standard deviation of the distribution"); RNA_def_property_update(prop, NC_LOGIC, NULL); /* ACT_RANDOM_FLOAT_NEGATIVE_EXPONENTIAL */ @@ -1578,11 +1578,11 @@ static void rna_def_message_actuator(BlenderRNA *brna) prop= RNA_def_property(srna, "to_property", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "toPropName"); - RNA_def_property_ui_text(prop, "To", "Optional send message to objects with this name only, or empty to broadcast"); + RNA_def_property_ui_text(prop, "To", "Optional, send message to objects with this name only, or empty to broadcast"); RNA_def_property_update(prop, NC_LOGIC, NULL); prop= RNA_def_property(srna, "subject", PROP_STRING, PROP_NONE); - RNA_def_property_ui_text(prop, "Subject", "Optional message subject. This is what can be filtered on"); + RNA_def_property_ui_text(prop, "Subject", "Optional, message subject (this is what can be filtered on)"); RNA_def_property_update(prop, NC_LOGIC, NULL); prop= RNA_def_property(srna, "body_type", PROP_ENUM, PROP_NONE); @@ -1593,7 +1593,7 @@ static void rna_def_message_actuator(BlenderRNA *brna) /* ACT_MESG_MESG */ prop= RNA_def_property(srna, "body_message", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "body"); - RNA_def_property_ui_text(prop, "Body", "Optional message body Text"); + RNA_def_property_ui_text(prop, "Body", "Optional, message body Text"); RNA_def_property_update(prop, NC_LOGIC, NULL); /* ACT_MESG_PROP */ @@ -1649,12 +1649,12 @@ static void rna_def_visibility_actuator(BlenderRNA *brna) prop= RNA_def_property(srna, "use_visible", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", ACT_VISIBILITY_INVISIBLE); - RNA_def_property_ui_text(prop, "Visible", "Set the objects visible. Initialized from the object render restriction toggle in physics button"); + RNA_def_property_ui_text(prop, "Visible", "Set the objects visible (initialized from the object render restriction toggle in physics button)"); RNA_def_property_update(prop, NC_LOGIC, NULL); prop= RNA_def_property(srna, "use_occlusion", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", ACT_VISIBILITY_OCCLUSION); - RNA_def_property_ui_text(prop, "Occlusion", "Set the object to occlude objects behind it. Initialized from the object type in physics button"); + RNA_def_property_ui_text(prop, "Occlusion", "Set the object to occlude objects behind it (initialized from the object type in physics button)"); RNA_def_property_update(prop, NC_LOGIC, NULL); prop= RNA_def_property(srna, "apply_to_children", PROP_BOOLEAN, PROP_NONE); @@ -1712,7 +1712,7 @@ static void rna_def_twodfilter_actuator(BlenderRNA *brna) prop= RNA_def_property(srna, "motion_blur_factor", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "float_arg"); - RNA_def_property_ui_text(prop, "Value", "Set motion blur factor"); + RNA_def_property_ui_text(prop, "Value", "Motion blur factor"); RNA_def_property_range(prop, 0.0, 1.0); RNA_def_property_update(prop, NC_LOGIC, NULL); @@ -1828,7 +1828,7 @@ static void rna_def_shape_action_actuator(BlenderRNA *brna) prop= RNA_def_property(srna, "priority", PROP_INT, PROP_NONE); RNA_def_property_range(prop, 0, 100); - RNA_def_property_ui_text(prop, "Priority", "Execution priority - lower numbers will override actions with higher numbers. With 2 or more actions at once, the overriding channels must be lower in the stack"); + RNA_def_property_ui_text(prop, "Priority", "Execution priority - lower numbers will override actions with higher numbers (with 2 or more actions at once, the overriding channels must be lower in the stack)"); RNA_def_property_update(prop, NC_LOGIC, NULL); prop= RNA_def_property(srna, "frame_property", PROP_STRING, PROP_NONE); @@ -1904,7 +1904,7 @@ static void rna_def_armature_actuator(BlenderRNA *brna) prop= RNA_def_property(srna, "constraint", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "constraint"); - RNA_def_property_ui_text(prop, "Constraint", "Name of the constraint you want to control"); + RNA_def_property_ui_text(prop, "Constraint", "Name of the constraint to control"); RNA_def_property_update(prop, NC_LOGIC, "rna_Actuator_Armature_update"); prop= RNA_def_property(srna, "target", PROP_POINTER, PROP_NONE); @@ -1923,7 +1923,7 @@ static void rna_def_armature_actuator(BlenderRNA *brna) prop= RNA_def_property(srna, "weight", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "weight"); RNA_def_property_range(prop, 0.0, 1.0); - RNA_def_property_ui_text(prop, "Weight", "Set weight of this constraint"); + RNA_def_property_ui_text(prop, "Weight", "Weight of this constraint"); RNA_def_property_update(prop, NC_LOGIC, NULL); } @@ -1985,7 +1985,7 @@ static void rna_def_steering_actuator(BlenderRNA *brna) RNA_def_property_struct_type(prop, "Object"); RNA_def_property_pointer_sdna(prop, NULL, "target"); RNA_def_property_flag(prop, PROP_EDITABLE); - RNA_def_property_ui_text(prop, "Target Object", "Set target object"); + RNA_def_property_ui_text(prop, "Target Object", "Target object"); RNA_def_property_update(prop, NC_LOGIC, NULL); prop= RNA_def_property(srna, "self_terminated", PROP_BOOLEAN, PROP_NONE); diff --git a/source/blender/python/BPY_extern.h b/source/blender/python/BPY_extern.h index 29e0185c2f2..51f9063c289 100644 --- a/source/blender/python/BPY_extern.h +++ b/source/blender/python/BPY_extern.h @@ -74,7 +74,7 @@ void BPY_modules_load_user(struct bContext *C); void BPY_app_handlers_reset(const short do_all); void BPY_driver_reset(void); -float BPY_driver_exec(struct ChannelDriver *driver); +float BPY_driver_exec(struct ChannelDriver *driver, const float evaltime); int BPY_button_exec(struct bContext *C, const char *expr, double *value, const short verbose); int BPY_string_exec(struct bContext *C, const char *expr); diff --git a/source/blender/python/intern/bpy_driver.c b/source/blender/python/intern/bpy_driver.c index 12fb5ed43b4..2aad4d8f2fe 100644 --- a/source/blender/python/intern/bpy_driver.c +++ b/source/blender/python/intern/bpy_driver.c @@ -91,6 +91,29 @@ int bpy_pydriver_create_dict(void) return 0; } +/* note, this function should do nothing most runs, only when changing frame */ +static PyObject *bpy_pydriver_InternStr__frame= NULL; + +static void bpy_pydriver_update_dict(const float evaltime) +{ + /* not thread safe but neither is python */ + static float evaltime_prev= FLT_MAX; + + if (evaltime_prev != evaltime) { + + /* currently only update the frame */ + if (bpy_pydriver_InternStr__frame == NULL) { + bpy_pydriver_InternStr__frame= PyUnicode_FromString("frame"); + } + + PyDict_SetItem(bpy_pydriver_Dict, + bpy_pydriver_InternStr__frame, + PyFloat_FromDouble(evaltime)); + + evaltime_prev= evaltime; + } +} + /* Update function, it gets rid of pydrivers global dictionary, forcing * BPY_driver_exec to recreate it. This function is used to force * reloading the Blender text module "pydrivers.py", if available, so @@ -110,6 +133,11 @@ void BPY_driver_reset(void) bpy_pydriver_Dict= NULL; } + if (bpy_pydriver_InternStr__frame) { + Py_DECREF(bpy_pydriver_InternStr__frame); + bpy_pydriver_InternStr__frame= NULL; + } + if (use_gil) PyGILState_Release(gilstate); @@ -139,7 +167,7 @@ static void pydriver_error(ChannelDriver *driver) * now release the GIL on python operator execution instead, using * PyEval_SaveThread() / PyEval_RestoreThread() so we dont lock up blender. */ -float BPY_driver_exec(ChannelDriver *driver) +float BPY_driver_exec(ChannelDriver *driver, const float evaltime) { PyObject *driver_vars=NULL; PyObject *retval= NULL; @@ -183,6 +211,10 @@ float BPY_driver_exec(ChannelDriver *driver) } } + /* update global namespace */ + bpy_pydriver_update_dict(evaltime); + + if (driver->expr_comp==NULL) driver->flag |= DRIVER_FLAG_RECOMPILE; @@ -246,6 +278,7 @@ float BPY_driver_exec(ChannelDriver *driver) } } + #if 0 // slow, with this can avoid all Py_CompileString above. /* execute expression to get a value */ retval= PyRun_String(expr, Py_eval_input, bpy_pydriver_Dict, driver_vars); diff --git a/source/blender/python/intern/bpy_driver.h b/source/blender/python/intern/bpy_driver.h index 3e38cacf6d1..802a3649e20 100644 --- a/source/blender/python/intern/bpy_driver.h +++ b/source/blender/python/intern/bpy_driver.h @@ -33,7 +33,7 @@ int bpy_pydriver_create_dict(void); extern PyObject *bpy_pydriver_Dict; /* externals */ -float BPY_driver_exec(struct ChannelDriver *driver); +float BPY_driver_exec(struct ChannelDriver *driver, const float evaltime); void BPY_driver_reset(void); #endif // BPY_DRIVER_H diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index f1916355971..3bde38d1445 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -64,6 +64,7 @@ #include "MEM_guardedalloc.h" +#include "BKE_main.h" #include "BKE_idcode.h" #include "BKE_context.h" #include "BKE_global.h" /* evil G.* */ @@ -2096,6 +2097,84 @@ static PyObject *pyrna_prop_collection_subscript_str(BPy_PropertyRNA *self, cons } /* static PyObject *pyrna_prop_array_subscript_str(BPy_PropertyRNA *self, char *keyname) */ +/* special case: bpy.data.objects["some_id_name", "//some_lib_name.blend"] + * also for: bpy.data.objects.get(("some_id_name", "//some_lib_name.blend"), fallback) */ +static PyObject *pyrna_prop_collection_subscript_str_lib_pair(BPy_PropertyRNA *self, PyObject *key, const char *err_prefix, const short err_not_found) +{ + char *keyname; + + /* first validate the args, all we know is that they are a tuple */ + if (PyTuple_GET_SIZE(key) != 2) { + PyErr_Format(PyExc_KeyError, + "%s: tuple key must be a pair, not size %d", + err_prefix, PyTuple_GET_SIZE(key)); + return NULL; + } + else if (self->ptr.type != &RNA_BlendData) { + PyErr_Format(PyExc_KeyError, + "%s: is only valid for bpy.data collections, not %.200s", + err_prefix, RNA_struct_identifier(self->ptr.type)); + return NULL; + } + else if ((keyname= _PyUnicode_AsString(PyTuple_GET_ITEM(key, 0))) == NULL) { + PyErr_Format(PyExc_KeyError, + "%s: id must be a string, not %.200s", + err_prefix, Py_TYPE(PyTuple_GET_ITEM(key, 0))->tp_name); + return NULL; + } + else { + PyObject *keylib= PyTuple_GET_ITEM(key, 1); + Library *lib; + PyObject *ret= NULL; + + if (keylib == Py_None) { + lib= NULL; + } + else if (PyUnicode_Check(keylib)) { + Main *bmain= self->ptr.data; + const char *keylib_str= _PyUnicode_AsString(keylib); + lib= BLI_findstring(&bmain->library, keylib_str, offsetof(Library, name)); + if (lib == NULL) { + if (err_not_found) { + PyErr_Format(PyExc_KeyError, + "%s: lib name '%.240s' " + "does not reference a valid library", + err_prefix, keylib_str); + } + + return NULL; + } + } + else { + PyErr_Format(PyExc_KeyError, + "%s: lib must be a sting or None, not %.200s", + err_prefix, Py_TYPE(keylib)->tp_name); + return NULL; + } + + /* lib is either a valid poniter or NULL, + * either way can do direct comparison with id.lib */ + + RNA_PROP_BEGIN(&self->ptr, itemptr, self->prop) { + ID *id= itemptr.data; /* always an ID */ + if (id->lib == lib && (strncmp(keyname, id->name+2, sizeof(id->name)-2) == 0)) { + ret= pyrna_struct_CreatePyObject(&itemptr); + break; + } + } + RNA_PROP_END; + + /* we may want to fail silently as with collection.get() */ + if ((ret == NULL) && err_not_found) { + /* only runs for getitem access so use fixed string */ + PyErr_SetString(PyExc_KeyError, + "bpy_prop_collection[key, lib]: not found"); + } + + return ret; + } +} + static PyObject *pyrna_prop_collection_subscript_slice(BPy_PropertyRNA *self, Py_ssize_t start, Py_ssize_t stop) { CollectionPropertyIterator rna_macro_iter; @@ -2266,6 +2345,10 @@ static PyObject *pyrna_prop_collection_subscript(BPy_PropertyRNA *self, PyObject } } } + else if (PyTuple_Check(key)) { + /* special case, for ID datablocks we */ + return pyrna_prop_collection_subscript_str_lib_pair(self, key, "bpy_prop_collection[id, lib]", TRUE); + } else { PyErr_Format(PyExc_TypeError, "bpy_prop_collection[key]: invalid key, " @@ -3915,6 +3998,7 @@ static PyObject *pyrna_struct_as_pointer(BPy_StructRNA *self) return PyLong_FromVoidPtr(self->ptr.data); } +/* TODO, get (string, lib) pair */ PyDoc_STRVAR(pyrna_prop_collection_get_doc, ".. method:: get(key, default=None)\n" "\n" @@ -3931,16 +4015,31 @@ static PyObject *pyrna_prop_collection_get(BPy_PropertyRNA *self, PyObject *args { PointerRNA newptr; - const char *key; + PyObject *key_ob; PyObject* def= Py_None; PYRNA_PROP_CHECK_OBJ(self); - if (!PyArg_ParseTuple(args, "s|O:get", &key, &def)) + if (!PyArg_ParseTuple(args, "O|O:get", &key_ob, &def)) return NULL; - if (RNA_property_collection_lookup_string(&self->ptr, self->prop, key, &newptr)) - return pyrna_struct_CreatePyObject(&newptr); + if (PyUnicode_Check(key_ob)) { + const char *key= _PyUnicode_AsString(key_ob); + + if (RNA_property_collection_lookup_string(&self->ptr, self->prop, key, &newptr)) + return pyrna_struct_CreatePyObject(&newptr); + } + else if (PyTuple_Check(key_ob)) { + PyObject *ret= pyrna_prop_collection_subscript_str_lib_pair(self, key_ob, "bpy_prop_collection.get((id, lib))", FALSE); + if (ret) { + return ret; + } + } + else { + PyErr_Format(PyExc_KeyError, + "bpy_prop_collection.get(key, ...): key must be a string or tuple, not %.200s", + Py_TYPE(key_ob)->tp_name); + } return Py_INCREF(def), def; } diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c index 807ba256247..0b4b6ca9112 100644 --- a/source/blenderplayer/bad_level_call_stubs/stubs.c +++ b/source/blenderplayer/bad_level_call_stubs/stubs.c @@ -473,7 +473,7 @@ void BPY_text_free_code(struct Text *text) {} void BPY_id_release(struct Text *text) {} int BPY_context_member_get(struct Context *C, const char *member, struct bContextDataResult *result) { return 0; } void BPY_pyconstraint_target(struct bPythonConstraint *con, struct bConstraintTarget *ct) {} -float BPY_driver_exec(struct ChannelDriver *driver) {return 0.0f;} /* might need this one! */ +float BPY_driver_exec(struct ChannelDriver *driver, const float evaltime) {return 0.0f;} /* might need this one! */ void BPY_DECREF(void *pyob_ptr) {} void BPY_pyconstraint_exec(struct bPythonConstraint *con, struct bConstraintOb *cob, struct ListBase *targets) {} void macro_wrapper(struct wmOperatorType *ot, void *userdata) {} ; diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index 5f6b6255b68..d0bbd9db45a 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -233,10 +233,6 @@ else() set(TARGETDIR ${EXECUTABLE_OUTPUT_PATH}) endif() - -# ----------------------------------------------------------------------------- -# Install Targets - set(BLENDER_TEXT_FILES ${CMAKE_SOURCE_DIR}/release/text/GPL-license.txt ${CMAKE_SOURCE_DIR}/release/text/Python-license.txt @@ -244,8 +240,11 @@ set(BLENDER_TEXT_FILES ${CMAKE_SOURCE_DIR}/release/text/readme.html ) -if(UNIX AND NOT APPLE) +# ----------------------------------------------------------------------------- +# Platform Spesific Var: TARGETDIR_VER + +if(UNIX AND NOT APPLE) if(WITH_INSTALL_PORTABLE) set(TARGETDIR_VER ${TARGETDIR}/${BLENDER_VERSION}) else() @@ -256,18 +255,71 @@ if(UNIX AND NOT APPLE) endif() endif() - # important to make a clean install each time - # else old scripts get loaded. +elseif(WIN32) + set(TARGETDIR_VER ${TARGETDIR}/${BLENDER_VERSION}) + +elseif(APPLE) + set(TARGETDIR_VER ${TARGETDIR}/blender.app/Contents/MacOS/${BLENDER_VERSION}) + +endif() + + +# ----------------------------------------------------------------------------- +# Install Targets (Generic, All Platforms) + + +# important to make a clean install each time, else old scripts get loaded. +install( + CODE + "file(REMOVE_RECURSE ${TARGETDIR_VER})" +) + +if(WITH_PYTHON) + # install(CODE "message(\"copying blender scripts...\")") + + # exclude addons_contrib if release + if("${BLENDER_VERSION_CYCLE}" STREQUAL "release") + set(ADDON_EXCLUDE_CONDITIONAL "addons_contrib/*") + else() + set(ADDON_EXCLUDE_CONDITIONAL "_addons_contrib/*") # dummy, wont do anything + endif() + install( - CODE - "file(REMOVE_RECURSE ${TARGETDIR_VER})" + DIRECTORY ${CMAKE_SOURCE_DIR}/release/scripts + DESTINATION ${TARGETDIR_VER} + PATTERN ".svn" EXCLUDE + PATTERN "__pycache__" EXCLUDE + PATTERN "${ADDON_EXCLUDE_CONDITIONAL}" EXCLUDE ) + + unset(ADDON_EXCLUDE_CONDITIONAL) +endif() +# localization +if(WITH_INTERNATIONAL) + install( + DIRECTORY + ${CMAKE_SOURCE_DIR}/release/datafiles/locale + ${CMAKE_SOURCE_DIR}/release/datafiles/fonts + DESTINATION ${TARGETDIR_VER}/datafiles + PATTERN ".svn" EXCLUDE + ) +endif() + +# helpful tip when using make +if("${CMAKE_GENERATOR}" MATCHES ".*Makefiles.*") # message after building. add_custom_command( TARGET blender POST_BUILD MAIN_DEPENDENCY blender COMMAND ${CMAKE_COMMAND} -E echo 'now run: \"make install\" to copy runtime files & scripts to ${TARGETDIR_VER}' ) +endif() + + +# ----------------------------------------------------------------------------- +# Install Targets (Platform Specific) + +if(UNIX AND NOT APPLE) # there are a few differences between portable and system install if(WITH_INSTALL_PORTABLE) @@ -348,16 +400,6 @@ if(UNIX AND NOT APPLE) ) endif() - if(WITH_INTERNATIONAL) - install( - DIRECTORY - ${CMAKE_SOURCE_DIR}/release/datafiles/locale - ${CMAKE_SOURCE_DIR}/release/datafiles/fonts - DESTINATION ${TARGETDIR_VER}/datafiles - PATTERN ".svn" EXCLUDE - ) - endif() - # plugins in blender 2.5 don't work at the moment. # # install( @@ -367,14 +409,6 @@ if(UNIX AND NOT APPLE) # ) if(WITH_PYTHON) - # install(CODE "message(\"copying blender scripts...\")") - install( - DIRECTORY ${CMAKE_SOURCE_DIR}/release/scripts - DESTINATION ${TARGETDIR_VER} - PATTERN ".svn" EXCLUDE - PATTERN "__pycache__" EXCLUDE - ) - if(WITH_PYTHON_INSTALL) # Copy the systems python into the install directory # Scons copy in tools/Blender.py @@ -403,27 +437,12 @@ if(UNIX AND NOT APPLE) endif() elseif(WIN32) - set(TARGETDIR_VER ${TARGETDIR}/${BLENDER_VERSION}) - - install( # same as linux!, deduplicate - CODE - "file(REMOVE_RECURSE ${TARGETDIR_VER})" - ) - - install( # same as linux!, deduplicate + install( FILES ${BLENDER_TEXT_FILES} DESTINATION ${TARGETDIR} ) - if(WITH_INTERNATIONAL) # same as linux!, deduplicate - install( - DIRECTORY - ${CMAKE_SOURCE_DIR}/release/datafiles/locale - ${CMAKE_SOURCE_DIR}/release/datafiles/fonts - DESTINATION ${TARGETDIR_VER}/datafiles - PATTERN ".svn" EXCLUDE - ) - + if(WITH_INTERNATIONAL) install( FILES ${LIBDIR}/gettext/lib/gnu_gettext.dll DESTINATION ${TARGETDIR} @@ -446,13 +465,6 @@ elseif(WIN32) # ) if(WITH_PYTHON) - # install(CODE "message(\"copying blender scripts...\")") - install( # same as linux!, deduplicate - DIRECTORY ${CMAKE_SOURCE_DIR}/release/scripts - DESTINATION ${TARGETDIR_VER} - PATTERN ".svn" EXCLUDE - PATTERN "__pycache__" EXCLUDE - ) install( FILES ${LIBDIR}/python/lib/python32.dll @@ -584,29 +596,6 @@ elseif(WIN32) endif() elseif(APPLE) - set(SOURCEDIR ${CMAKE_SOURCE_DIR}/source/darwin/blender.app) - set(SOURCEINFO ${SOURCEDIR}/Contents/Info.plist) - set(TARGETDIR_VER ${TARGETDIR}/blender.app/Contents/MacOS/${BLENDER_VERSION}) - - # setup Info.plist - execute_process(COMMAND date "+%Y-%m-%d" OUTPUT_VARIABLE BLENDER_DATE OUTPUT_STRIP_TRAILING_WHITESPACE) - - set_target_properties(blender PROPERTIES - MACOSX_BUNDLE_INFO_PLIST ${SOURCEINFO} - MACOSX_BUNDLE_SHORT_VERSION_STRING ${BLENDER_VERSION} - MACOSX_BUNDLE_LONG_VERSION_STRING "${BLENDER_VERSION} ${BLENDER_DATE}") - - # important to make a clean install each time else old scripts get loaded. - install( - CODE - "file(REMOVE_RECURSE ${TARGETDIR_VER})" - ) - - # message after building. - add_custom_command( - TARGET blender POST_BUILD MAIN_DEPENDENCY blender - COMMAND ${CMAKE_COMMAND} -E echo 'now run: \"make install\" to copy runtime files & scripts to ${TARGETDIR_VER}' - ) # handy install macro to exclude files, we use \$ escape for the "to" # argument when calling so ${BUILD_TYPE} does not get expanded @@ -625,6 +614,17 @@ elseif(APPLE) ) endmacro() + set(OSX_APP_SOURCEDIR ${CMAKE_SOURCE_DIR}/source/darwin/blender.app) + + # setup Info.plist + execute_process(COMMAND date "+%Y-%m-%d" OUTPUT_VARIABLE BLENDER_DATE OUTPUT_STRIP_TRAILING_WHITESPACE) + + set_target_properties(blender PROPERTIES + MACOSX_BUNDLE_INFO_PLIST ${OSX_APP_SOURCEDIR}/Contents/Info.plist + MACOSX_BUNDLE_SHORT_VERSION_STRING ${BLENDER_VERSION} + MACOSX_BUNDLE_LONG_VERSION_STRING "${BLENDER_VERSION} ${BLENDER_DATE}") + + # install release and app files install( FILES ${BLENDER_TEXT_FILES} @@ -632,26 +632,15 @@ elseif(APPLE) ) install( - FILES ${SOURCEDIR}/Contents/PkgInfo + FILES ${OSX_APP_SOURCEDIR}/Contents/PkgInfo DESTINATION ${TARGETDIR}/blender.app/Contents ) install_dir( - ${SOURCEDIR}/Contents/Resources + ${OSX_APP_SOURCEDIR}/Contents/Resources \${TARGETDIR}/blender.app/Contents/ ) - # localization - if(WITH_INTERNATIONAL) - install( - DIRECTORY - ${CMAKE_SOURCE_DIR}/release/datafiles/locale - ${CMAKE_SOURCE_DIR}/release/datafiles/fonts - DESTINATION ${TARGETDIR_VER}/datafiles - PATTERN ".svn" EXCLUDE - ) - endif() - # python if(WITH_PYTHON) # the python zip is first extract as part of the build process, @@ -678,18 +667,13 @@ elseif(APPLE) \${TARGETDIR_VER} ) - # copy scripts - install_dir( - ${CMAKE_SOURCE_DIR}/release/scripts - \${TARGETDIR_VER} - ) endif() # install blenderplayer bundle - copy of blender.app above. re-using macros et al # note we are using OSX Bundle as base and copying Blender dummy bundle on top of it if(WITH_GAMEENGINE AND WITH_PLAYER) - set(PLAYER_SOURCEDIR ${CMAKE_SOURCE_DIR}/source/darwin/blenderplayer.app) - set(PLAYER_SOURCEINFO ${PLAYER_SOURCEDIR}/Contents/Info.plist) + set(OSX_APP_PLAYER_SOURCEDIR ${CMAKE_SOURCE_DIR}/source/darwin/blenderplayer.app) + set(PLAYER_SOURCEINFO ${OSX_APP_PLAYER_SOURCEDIR}/Contents/Info.plist) set(PLAYER_TARGETDIR_VER ${TARGETDIR}/blenderplayer.app/Contents/MacOS/${BLENDER_VERSION}) @@ -700,12 +684,12 @@ elseif(APPLE) ) install( - FILES ${PLAYER_SOURCEDIR}/Contents/PkgInfo + FILES ${OSX_APP_PLAYER_SOURCEDIR}/Contents/PkgInfo DESTINATION ${TARGETDIR}/blenderplayer.app/Contents ) install_dir( - ${PLAYER_SOURCEDIR}/Contents/Resources + ${OSX_APP_PLAYER_SOURCEDIR}/Contents/Resources \${TARGETDIR}/blenderplayer.app/Contents/ ) @@ -728,6 +712,11 @@ elseif(APPLE) endif() endif() +# ----------------------------------------------------------------------------- +# Generic Install, for all targets + + + # install more files specified elsewhere delayed_do_install(${TARGETDIR_VER}) |