svn merge ^/trunk/blender -r41939:41954
authorCampbell Barton <ideasman42@gmail.com>
Fri, 18 Nov 2011 05:06:53 +0000 (05:06 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Fri, 18 Nov 2011 05:06:53 +0000 (05:06 +0000)
18 files changed:
SConstruct
build_files/scons/tools/btools.py
doc/python_api/rst/info_gotcha.rst
release/scripts/modules/addon_utils.py
release/scripts/startup/bl_ui/__init__.py
release/scripts/startup/bl_ui/space_userpref.py
source/blender/blenkernel/intern/fcurve.c
source/blender/blenlib/intern/DLRB_tree.c
source/blender/editors/interface/interface_anim.c
source/blender/makesrna/RNA_types.h
source/blender/makesrna/intern/makesrna.c
source/blender/makesrna/intern/rna_actuator.c
source/blender/python/BPY_extern.h
source/blender/python/intern/bpy_driver.c
source/blender/python/intern/bpy_driver.h
source/blender/python/intern/bpy_rna.c
source/blenderplayer/bad_level_call_stubs/stubs.c
source/creator/CMakeLists.txt

index b5075aa43450e0f8adf20bb5697a87725586236a..cd4e31efeff917e03ee5085a0a89ca87b26c6d59 100644 (file)
@@ -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):]
 
index 856231e3c84936aa56595f1b98d02850c56b8105..4c826b12e89b850f094913d05cd57a5602b5efad 100644 (file)
@@ -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()
 
index b17debbb15cbfabc590d68420b0de870f78e8a79..281f068904484bc630450a33674ce3f29f140309 100644 (file)
@@ -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.
+
index 26611fb93adbdd1ccd106803d6119223d35171f0..1bd218ad92aa7cf6192115e221cd351a76d5dde3 100644 (file)
@@ -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
 
index 3db768f73fe3e4dc7afc4201bd408dcdd5c91bc0..6aa08a7f50da615d42d9b476944b490ac7a25eba 100644 (file)
@@ -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...
 
 
index 665d790f832d8754bdcddd5d9a8c88fa27685fd4..c889e7f3de6a790557073cd15a9ba7588ac2415d 100644 (file)
@@ -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
index 5ab997d2c54175f3e5fc0414733135a3793039b7..4bb9dc47fda8d74fc4502947e3ef31b2a35d6c1a 100644 (file)
@@ -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;
index 72743e38d4cbd10328fc5e0a6304aea1752fbab2..4507d70e3394facdf68fc2740d08a652db1e84c6 100644 (file)
@@ -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);
 }
 
index 1edd43d4e01eed6af7dc992906c12314ae04613d..5e095bae922089cefbdf166c729eda7ae33ccf75 100644 (file)
@@ -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);
index e768594fe7314c0d265e7606bb069a9808e34e42..85869115e79386b0fddebe7484e566be06e4f6b9 100644 (file)
@@ -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,
index 6dbf7b9c553f5d32ebc1a20d639bffcdcdce30cc..c21685c9add55c39da6ae5914ee06cddb67d5f8d 100644 (file)
@@ -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;
index db71dee26ced3d3aa09fe50d0c4181b9acd29c8b..b941e9ebed72dae7dce027e83e36801367094127 100644 (file)
@@ -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);
index 29e0185c2f242cb37d0332a9090d31e9c24cee2d..51f9063c2898e52957b3b11c23e26005faa47de3 100644 (file)
@@ -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);
index 12fb5ed43b4e95abab07e55f6927abd9ca34a253..2aad4d8f2fe12c055d55378b8231a2e051b52f1e 100644 (file)
@@ -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);
index 3e38cacf6d1dce11a734b9ea2a2bebedb1251084..802a3649e203d16c6d94b9bccf5bd20507cc4789 100644 (file)
@@ -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
index f1916355971283c4f7a2b2e279eaa2f896b6abdd..3bde38d144563a6fd5d31fc35f7df598dd810eb4 100644 (file)
@@ -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;
 }
index 807ba256247a2a5b81f9c61449f17abd6cdbce40..0b4b6ca9112022773d269f9fd75b5df6f2ba5615 100644 (file)
@@ -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) {} ;
index 5f6b6255b68135dfeacf8d867006a327cf073152..d0bbd9db45aeeae559abd2a8a39442473b7aff6e 100644 (file)
@@ -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})