Merge branch 'master' into blender2.8
authorBastien Montagne <montagne29@wanadoo.fr>
Tue, 3 Apr 2018 14:13:13 +0000 (16:13 +0200)
committerBastien Montagne <montagne29@wanadoo.fr>
Tue, 3 Apr 2018 14:13:13 +0000 (16:13 +0200)
1  2 
release/scripts/startup/bl_ui/space_info.py
source/blender/makesrna/intern/rna_rna.c

index 8c69e733a2d6bb7fb7be8a7cb4b19b13b579f99c,180e48af3863ebbd09038176ec49c8770b2ee111..96e8f9420d9661206ea0b37d374a5fcade59f515
@@@ -28,40 -28,25 +28,40 @@@ class INFO_HT_header(Header)
          layout = self.layout
  
          window = context.window
 +        workspace = context.workspace
 +        screen = context.screen
          scene = context.scene
 -        rd = scene.render
 +        layer = context.view_layer
 +        view_render = workspace.view_render
  
          row = layout.row(align=True)
          row.template_header()
  
          INFO_MT_editor_menus.draw_collapsible(context, layout)
  
 -        if window.screen.show_fullscreen:
 +        layout.separator()
 +
 +        if screen.show_fullscreen:
              layout.operator("screen.back_to_previous", icon='SCREEN_BACK', text="Back to Previous")
              layout.separator()
          else:
 -            layout.template_ID(context.window, "screen", new="screen.new", unlink="screen.delete")
 -            layout.template_ID(context.screen, "scene", new="scene.new", unlink="scene.delete")
 +            layout.template_ID(window, "workspace", new="workspace.workspace_add_menu", unlink="workspace.workspace_delete")
 +            layout.template_search_preview(window, "screen", workspace, "screens", new="screen.new", unlink="screen.delete", rows=2, cols=6)
 +
 +        act_mode_item = bpy.types.WorkSpace.bl_rna.properties['object_mode'].enum_items[workspace.object_mode]
 +        layout.operator_menu_enum("object.mode_set", "mode", text=act_mode_item.name, icon=act_mode_item.icon)
 +
 +        row = layout.row()
 +        row.active = not workspace.use_scene_settings
 +        # Active workspace view-layer is retrieved through window, not through workspace.
 +        row.template_search(window, "view_layer", scene, "view_layers")
 +
 +        if view_render.has_multiple_engines:
 +            row.prop(view_render, "engine", text="")
  
          layout.separator()
  
 -        if rd.has_multiple_engines:
 -            layout.prop(rd, "engine", text="")
 +        layout.template_ID(window, "scene", new="scene.new", unlink="scene.delete")
  
          layout.separator()
  
@@@ -84,7 -69,7 +84,7 @@@
              return
  
          row.operator("wm.splash", text="", icon='BLENDER', emboss=False)
 -        row.label(text=scene.statistics(), translate=False)
 +        row.label(text=scene.statistics(workspace, context.view_layer), translate=False)
  
  
  class INFO_MT_editor_menus(Menu):
  
      @staticmethod
      def draw_menus(layout, context):
 -        scene = context.scene
 -        rd = scene.render
 +        view_render = context.view_render
  
          layout.menu("INFO_MT_file")
  
 -        if rd.use_game_engine:
 +        if view_render.use_game_engine:
              layout.menu("INFO_MT_game")
          else:
              layout.menu("INFO_MT_render")
@@@ -168,6 -154,7 +168,7 @@@ class INFO_MT_file(Menu)
          layout.separator()
  
          layout.menu("INFO_MT_file_external_data", icon='EXTERNAL_DATA')
+         layout.operator("wm.blend_strings_utf8_validate", icon='FILE_BLEND')
  
          layout.separator()
  
@@@ -307,7 -294,7 +308,7 @@@ class INFO_MT_window(Menu)
  
          layout = self.layout
  
 -        layout.operator("wm.window_duplicate")
 +        layout.operator("wm.window_new")
          layout.operator("wm.window_fullscreen_toggle", icon='FULLSCREEN_ENTER')
  
          layout.separator()
index 0452c6440526e4743990cad0d4c0817c2efb17e6,b1b7965286f142c133929bd90303b542c0e220c8..a46c8e2f18f8ba3d40cbcf79504b824ae3076984
@@@ -107,8 -107,6 +107,8 @@@ const EnumPropertyItem rna_enum_propert
  #include "MEM_guardedalloc.h"
  #include "BLI_ghash.h"
  
 +#include "BKE_library_override.h"
 +
  /* Struct */
  
  static void rna_Struct_identifier_get(PointerRNA *ptr, char *value)
@@@ -566,13 -564,6 +566,13 @@@ static int rna_Property_animatable_get(
        return (prop->flag & PROP_ANIMATABLE) != 0;
  }
  
 +static int rna_Property_overridable_get(PointerRNA *ptr)
 +{
 +      PropertyRNA *prop = (PropertyRNA *)ptr->data;
 +
 +      return (prop->flag & PROP_OVERRIDABLE_STATIC) != 0;
 +}
 +
  static int rna_Property_use_output_get(PointerRNA *ptr)
  {
        PropertyRNA *prop = (PropertyRNA *)ptr->data;
@@@ -638,7 -629,7 +638,7 @@@ static const EnumPropertyItem *rna_Prop
        int totitem = 0;
  
        for (const EnumPropertyItem *struct_tags = RNA_struct_property_tag_defines(srna);
-            struct_tags->identifier;
+            struct_tags != NULL && struct_tags->identifier != NULL;
             struct_tags++)
        {
                memcpy(&tmp, struct_tags, sizeof(tmp));
@@@ -1091,1013 -1082,6 +1091,1013 @@@ static int rna_BlenderRNA_structs_looku
        return false;
  }
  
 +/* Default override (and compare) callbacks. */
 +
 +/* Used for both Pointer and Collection properties. */
 +static int rna_property_override_diff_propptr(
 +        PointerRNA *propptr_a, PointerRNA *propptr_b, eRNACompareMode mode, const bool no_ownership,
 +        IDOverrideStatic *override, const char *rna_path, const int flags, bool *r_override_changed)
 +{
 +      const bool do_create = override != NULL && (flags & RNA_OVERRIDE_COMPARE_CREATE) != 0 && rna_path != NULL;
 +
 +      bool is_id = false;
 +      bool is_type_null = false;
 +
 +      /* Beware, PointerRNA_NULL has no type and is considered a 'blank page'! */
 +      if (propptr_a->type == NULL) {
 +              if (propptr_b->type == NULL) {
 +                      if (r_override_changed) {
 +                              *r_override_changed = false;
 +                      }
 +                      return 0;
 +              }
 +              is_id = RNA_struct_is_ID(propptr_b->type);
 +              is_type_null = true;
 +      }
 +      else {
 +              is_id = RNA_struct_is_ID(propptr_a->type);
 +              is_type_null = (propptr_b->type == NULL);
 +      }
 +
 +      if (is_id) {
 +              BLI_assert(propptr_a->data == propptr_a->id.data && propptr_b->data == propptr_b->id.data);
 +              BLI_assert(no_ownership);  /* For now, once we deal with nodetrees we'll want to get rid of that one. */
 +      }
 +
 +      if (override) {
 +              if (no_ownership /* || is_id */ || is_type_null) {
 +                      /* In case this pointer prop does not own its data (or one is NULL), do not compare structs!
 +                       * This is a quite safe path to infinite loop, among other nasty issues.
 +                       * Instead, just compare pointers themselves. */
 +                      const int comp = (propptr_a->data != propptr_b->data);
 +
 +                      if (do_create && comp != 0) {
 +                              bool created = false;
 +                              IDOverrideStaticProperty *op = BKE_override_static_property_get(override, rna_path, &created);
 +
 +                              if (op != NULL && created) {  /* If not yet overridden... */
 +                                      BKE_override_static_property_operation_get(
 +                                                  op, IDOVERRIDESTATIC_OP_REPLACE, NULL, NULL, -1, -1, true, NULL, NULL);
 +                                      if (r_override_changed) {
 +                                              *r_override_changed = created;
 +                                      }
 +                              }
 +                      }
 +
 +                      return comp;
 +              }
 +              else {
 +                      eRNAOverrideMatchResult report_flags = 0;
 +                      const bool match = RNA_struct_override_matches(propptr_a, propptr_b, rna_path, override, flags, &report_flags);
 +                      if (r_override_changed && (report_flags & RNA_OVERRIDE_MATCH_RESULT_CREATED) != 0) {
 +                              *r_override_changed = true;
 +                      }
 +                      return !match;
 +              }
 +      }
 +      else {
 +              return !RNA_struct_equals(propptr_a, propptr_b, mode);
 +      }
 +}
 +
 +static char *rna_path_collection_prop_item_extend(const char *rna_path_prop, const char *item_name)
 +{
 +      const size_t esc_item_name_len = strlen(item_name) * 2;
 +      char *esc_item_name = alloca(sizeof(*esc_item_name) * esc_item_name_len);
 +      BLI_strescape(esc_item_name, item_name, esc_item_name_len);
 +      return BLI_sprintfN("%s[\"%s\"]", rna_path_prop, esc_item_name);
 +}
 +
 +int rna_property_override_diff_default(PointerRNA *ptr_a, PointerRNA *ptr_b,
 +        PropertyRNA *prop_a, PropertyRNA *prop_b,
 +        const int len_a, const int len_b,
 +        const int mode,
 +        IDOverrideStatic *override, const char *rna_path,
 +        const int flags, bool *r_override_changed)
 +{
 +      BLI_assert(len_a == len_b);
 +
 +      /* Note: at this point, we are sure that when len_a is zero, we are not handling an (empty) array. */
 +
 +      const bool do_create = override != NULL && (flags & RNA_OVERRIDE_COMPARE_CREATE) != 0 && rna_path != NULL;
 +
 +      switch (RNA_property_type(prop_a)) {
 +              case PROP_BOOLEAN:
 +              {
 +                      if (len_a) {
 +                              int array_stack_a[RNA_STACK_ARRAY], array_stack_b[RNA_STACK_ARRAY];
 +                              int *array_a, *array_b;
 +
 +                              array_a = (len_a > RNA_STACK_ARRAY) ? MEM_mallocN(sizeof(int) * len_a, "RNA equals") : array_stack_a;
 +                              array_b = (len_b > RNA_STACK_ARRAY) ? MEM_mallocN(sizeof(int) * len_b, "RNA equals") : array_stack_b;
 +
 +                              RNA_property_boolean_get_array(ptr_a, prop_a, array_a);
 +                              RNA_property_boolean_get_array(ptr_b, prop_b, array_b);
 +
 +                              const int comp = memcmp(array_a, array_b, sizeof(int) * len_a);
 +
 +                              if (do_create && comp != 0) {
 +                                      /* XXX TODO this will have to be refined to handle array items */
 +                                      bool created = false;
 +                                      IDOverrideStaticProperty *op = BKE_override_static_property_get(override, rna_path, &created);
 +
 +                                      if (op != NULL && created) {
 +                                              BKE_override_static_property_operation_get(
 +                                                          op, IDOVERRIDESTATIC_OP_REPLACE, NULL, NULL, -1, -1, true, NULL, NULL);
 +                                              if (r_override_changed) {
 +                                                      *r_override_changed = created;
 +                                              }
 +                                      }
 +                                      else {
 +                                              /* Already overriden prop, we'll have to check arrays items etc. */
 +                                      }
 +                              }
 +
 +                              if (array_a != array_stack_a) MEM_freeN(array_a);
 +                              if (array_b != array_stack_b) MEM_freeN(array_b);
 +
 +                              return comp;
 +                      }
 +                      else {
 +                              const int value_a = RNA_property_boolean_get(ptr_a, prop_a);
 +                              const int value_b = RNA_property_boolean_get(ptr_b, prop_b);
 +                              const int comp = (value_a < value_b) ? -1 : (value_a > value_b) ? 1 : 0;
 +
 +                              if (do_create && comp != 0) {
 +                                      bool created = false;
 +                                      IDOverrideStaticProperty *op = BKE_override_static_property_get(override, rna_path, &created);
 +
 +                                      if (op != NULL && created) {  /* If not yet overridden... */
 +                                              BKE_override_static_property_operation_get(
 +                                                          op, IDOVERRIDESTATIC_OP_REPLACE, NULL, NULL, -1, -1, true, NULL, NULL);
 +                                              if (r_override_changed) {
 +                                                      *r_override_changed = created;
 +                                              }
 +                                      }
 +                              }
 +
 +                              return comp;
 +                      }
 +              }
 +
 +              case PROP_INT:
 +              {
 +                      if (len_a) {
 +                              int array_stack_a[RNA_STACK_ARRAY], array_stack_b[RNA_STACK_ARRAY];
 +                              int *array_a, *array_b;
 +
 +                              array_a = (len_a > RNA_STACK_ARRAY) ? MEM_mallocN(sizeof(int) * len_a, "RNA equals") : array_stack_a;
 +                              array_b = (len_b > RNA_STACK_ARRAY) ? MEM_mallocN(sizeof(int) * len_b, "RNA equals") : array_stack_b;
 +
 +                              RNA_property_int_get_array(ptr_a, prop_a, array_a);
 +                              RNA_property_int_get_array(ptr_b, prop_b, array_b);
 +
 +                              const int comp = memcmp(array_a, array_b, sizeof(int) * len_a);
 +
 +                              if (do_create && comp != 0) {
 +                                      /* XXX TODO this will have to be refined to handle array items */
 +                                      bool created = false;
 +                                      IDOverrideStaticProperty *op = BKE_override_static_property_get(override, rna_path, &created);
 +
 +                                      if (op != NULL && created) {
 +                                              BKE_override_static_property_operation_get(
 +                                                          op, IDOVERRIDESTATIC_OP_REPLACE, NULL, NULL, -1, -1, true, NULL, NULL);
 +                                              if (r_override_changed) {
 +                                                      *r_override_changed = created;
 +                                              }
 +                                      }
 +                                      else {
 +                                              /* Already overriden prop, we'll have to check arrays items etc. */
 +                                      }
 +                              }
 +
 +                              if (array_a != array_stack_a) MEM_freeN(array_a);
 +                              if (array_b != array_stack_b) MEM_freeN(array_b);
 +
 +                              return comp;
 +                      }
 +                      else {
 +                              const int value_a = RNA_property_int_get(ptr_a, prop_a);
 +                              const int value_b = RNA_property_int_get(ptr_b, prop_b);
 +                              const int comp = (value_a < value_b) ? -1 : (value_a > value_b) ? 1 : 0;
 +
 +                              if (do_create && comp != 0) {
 +                                      bool created = false;
 +                                      IDOverrideStaticProperty *op = BKE_override_static_property_get(override, rna_path, &created);
 +
 +                                      if (op != NULL && created) {  /* If not yet overridden... */
 +                                              BKE_override_static_property_operation_get(
 +                                                          op, IDOVERRIDESTATIC_OP_REPLACE, NULL, NULL, -1, -1, true, NULL, NULL);
 +                                              if (r_override_changed) {
 +                                                      *r_override_changed = created;
 +                                              }
 +                                      }
 +                              }
 +
 +                              return comp;
 +                      }
 +              }
 +
 +              case PROP_FLOAT:
 +              {
 +                      const bool is_proportional = (prop_a->flag & PROP_PROPORTIONAL) != 0;
 +                      if (len_a) {
 +                              float array_stack_a[RNA_STACK_ARRAY], array_stack_b[RNA_STACK_ARRAY];
 +                              float *array_a, *array_b;
 +
 +                              array_a = (len_a > RNA_STACK_ARRAY) ? MEM_mallocN(sizeof(float) * len_a, "RNA equals") : array_stack_a;
 +                              array_b = (len_b > RNA_STACK_ARRAY) ? MEM_mallocN(sizeof(float) * len_b, "RNA equals") : array_stack_b;
 +
 +                              RNA_property_float_get_array(ptr_a, prop_a, array_a);
 +                              RNA_property_float_get_array(ptr_b, prop_b, array_b);
 +
 +                              const int comp = memcmp(array_a, array_b, sizeof(float) * len_a);
 +
 +                              if (do_create && comp != 0) {
 +                                      /* XXX TODO this will have to be refined to handle array items */
 +                                      bool created = false;
 +                                      IDOverrideStaticProperty *op = BKE_override_static_property_get(override, rna_path, &created);
 +
 +                                      if (op != NULL && created) {
 +                                              BKE_override_static_property_operation_get(
 +                                                          op, is_proportional ? IDOVERRIDESTATIC_OP_MULTIPLY : IDOVERRIDESTATIC_OP_REPLACE,
 +                                                          NULL, NULL, -1, -1, true, NULL, NULL);
 +                                              if (r_override_changed) {
 +                                                      *r_override_changed = created;
 +                                              }
 +                                      }
 +                                      else {
 +                                              /* Already overriden prop, we'll have to check arrays items etc. */
 +                                      }
 +                              }
 +
 +                              if (array_a != array_stack_a) MEM_freeN(array_a);
 +                              if (array_b != array_stack_b) MEM_freeN(array_b);
 +
 +                              return comp;
 +                      }
 +                      else {
 +                              const float value_a = RNA_property_float_get(ptr_a, prop_a);
 +                              const float value_b = RNA_property_float_get(ptr_b, prop_b);
 +                              const int comp = (value_a < value_b) ? -1 : (value_a > value_b) ? 1 : 0;
 +
 +                              if (do_create && comp != 0) {
 +                                      bool created = false;
 +                                      IDOverrideStaticProperty *op = BKE_override_static_property_get(override, rna_path, &created);
 +
 +                                      if (op != NULL && created) {  /* If not yet overridden... */
 +                                              BKE_override_static_property_operation_get(
 +                                                          op, is_proportional ? IDOVERRIDESTATIC_OP_MULTIPLY : IDOVERRIDESTATIC_OP_REPLACE,
 +                                                          NULL, NULL, -1, -1, true, NULL, NULL);
 +                                              if (r_override_changed) {
 +                                                      *r_override_changed = created;
 +                                              }
 +                                      }
 +                              }
 +
 +                              return comp ;
 +                      }
 +              }
 +
 +              case PROP_ENUM:
 +              {
 +                      const int value_a = RNA_property_enum_get(ptr_a, prop_a);
 +                      const int value_b = RNA_property_enum_get(ptr_b, prop_b);
 +                      const int comp = value_a != value_b;
 +
 +                      if (do_create && comp != 0) {
 +                              bool created = false;
 +                              IDOverrideStaticProperty *op = BKE_override_static_property_get(override, rna_path, &created);
 +
 +                              if (op != NULL && created) {  /* If not yet overridden... */
 +                                      BKE_override_static_property_operation_get(
 +                                                  op, IDOVERRIDESTATIC_OP_REPLACE, NULL, NULL, -1, -1, true, NULL, NULL);
 +                                      if (r_override_changed) {
 +                                              *r_override_changed = created;
 +                                      }
 +                              }
 +                      }
 +
 +                      return comp;
 +              }
 +
 +              case PROP_STRING:
 +              {
 +                      char fixed_a[128], fixed_b[128];
 +                      int len_str_a, len_str_b;
 +                      char *value_a = RNA_property_string_get_alloc(ptr_a, prop_a, fixed_a, sizeof(fixed_a), &len_str_a);
 +                      char *value_b = RNA_property_string_get_alloc(ptr_b, prop_b, fixed_b, sizeof(fixed_b), &len_str_b);
 +                      const int comp = strcmp(value_a, value_b);
 +
 +                      if (do_create && comp != 0) {
 +                              bool created = false;
 +                              IDOverrideStaticProperty *op = BKE_override_static_property_get(override, rna_path, &created);
 +
 +                              if (op != NULL && created) {  /* If not yet overridden... */
 +                                      BKE_override_static_property_operation_get(
 +                                                  op, IDOVERRIDESTATIC_OP_REPLACE, NULL, NULL, -1, -1, true, NULL, NULL);
 +                                      if (r_override_changed) {
 +                                              *r_override_changed = created;
 +                                      }
 +                              }
 +                      }
 +
 +                      if (value_a != fixed_a) MEM_freeN(value_a);
 +                      if (value_b != fixed_b) MEM_freeN(value_b);
 +
 +                      return comp;
 +              }
 +
 +              case PROP_POINTER:
 +              {
 +                      if (STREQ(RNA_property_identifier(prop_a), "rna_type")) {
 +                              /* Dummy 'pass' answer, this is a meta-data and must be ignored... */
 +                              return 0;
 +                      }
 +                      else {
 +                              PointerRNA propptr_a = RNA_property_pointer_get(ptr_a, prop_a);
 +                              PointerRNA propptr_b = RNA_property_pointer_get(ptr_b, prop_b);
 +                              const bool no_ownership = (RNA_property_flag(prop_a) & PROP_PTR_NO_OWNERSHIP) != 0;
 +                              return rna_property_override_diff_propptr(
 +                                          &propptr_a, &propptr_b, mode, no_ownership,
 +                                          override, rna_path, flags, r_override_changed);
 +                      }
 +                      break;
 +              }
 +
 +              case PROP_COLLECTION:
 +              {
 +                      bool equals = true;
 +                      int idx = 0;
 +
 +                      CollectionPropertyIterator iter_a, iter_b;
 +                      RNA_property_collection_begin(ptr_a, prop_a, &iter_a);
 +                      RNA_property_collection_begin(ptr_b, prop_b, &iter_b);
 +
 +                      for (; iter_a.valid && iter_b.valid;
 +                           RNA_property_collection_next(&iter_a), RNA_property_collection_next(&iter_b), idx++)
 +                      {
 +                              char *extended_rna_path = NULL;
 +
 +                              if (iter_a.ptr.type != iter_b.ptr.type) {
 +                                      /* nothing we can do (for until we support adding/removing from collections), skip it. */
 +                                      equals = false;
 +                                      continue;
 +                              }
 +                              else if (iter_a.ptr.type == NULL) {
 +                                      /* NULL RNA pointer... */
 +                                      BLI_assert(iter_a.ptr.data == NULL);
 +                                      BLI_assert(iter_b.ptr.data == NULL);
 +                                      continue;
 +                              }
 +
 +                              PropertyRNA *propname = RNA_struct_name_property(iter_a.ptr.type);
 +                              char propname_buff_a[256], propname_buff_b[256];
 +                              char *propname_a = NULL, *propname_b = NULL;
 +
 +                              if (propname != NULL) {
 +                                      propname_a = RNA_property_string_get_alloc(&iter_a.ptr, propname, propname_buff_a, sizeof(propname_buff_a), NULL);
 +                                      propname_b = RNA_property_string_get_alloc(&iter_b.ptr, propname, propname_buff_b, sizeof(propname_buff_b), NULL);
 +                              }
 +                              /* There may be a propname defined in some cases, while no actual name set
 +                               * (e.g. happens with point cache), in that case too we want to fall back to index. */
 +                              if ((propname_a != NULL && propname_a[0] != '\0') || (propname_b != NULL && propname_b[0] != '\0')) {
 +                                      if (!STREQ(propname_a, propname_b)) {
 +                                              /* Same as above, not same structs. */
 +                                              equals = false;
 +                                      }
 +                                      else if (rna_path) {
 +                                              extended_rna_path = rna_path_collection_prop_item_extend(rna_path, propname_a);
 +                                      }
 +                              }
 +                              else {  /* Based on index... */
 +                                      if (rna_path) {
 +                                              extended_rna_path = BLI_sprintfN("%s[%d]", rna_path, idx);
 +                                      }
 +                              }
 +
 +                              if (equals || do_create) {
 +                                      const bool no_ownership = (RNA_property_flag(prop_a) & PROP_PTR_NO_OWNERSHIP) != 0;
 +                                      const int eq = rna_property_override_diff_propptr(
 +                                                    &iter_a.ptr, &iter_b.ptr, mode, no_ownership,
 +                                                    override, extended_rna_path, flags, r_override_changed);
 +                                      equals = equals && eq;
 +                              }
 +
 +                              if (propname_a != propname_buff_a) {
 +                                      MEM_SAFE_FREE(propname_a);
 +                              }
 +                              if (propname_b != propname_buff_b) {
 +                                      MEM_SAFE_FREE(propname_b);
 +                              }
 +                              MEM_SAFE_FREE(extended_rna_path);
 +
 +                              if (!rna_path && !equals) {
 +                                      break;  /* Early out in case we do not want to loop over whole collection. */
 +                              }
 +                      }
 +
 +                      equals = equals && !(iter_a.valid || iter_b.valid);  /* Not same number of items in both collections... */
 +                      RNA_property_collection_end(&iter_a);
 +                      RNA_property_collection_end(&iter_b);
 +
 +                      return (equals == false);
 +              }
 +
 +              default:
 +                      break;
 +      }
 +
 +      return 0;
 +}
 +
 +bool rna_property_override_store_default(
 +        PointerRNA *ptr_local, PointerRNA *ptr_reference, PointerRNA *ptr_storage,
 +        PropertyRNA *prop_local, PropertyRNA *prop_reference, PropertyRNA *prop_storage,
 +        const int len_local, const int len_reference, const int len_storage,
 +        IDOverrideStaticPropertyOperation *opop)
 +{
 +      BLI_assert(len_local == len_reference && (!ptr_storage || len_local == len_storage));
 +      UNUSED_VARS_NDEBUG(len_reference, len_storage);
 +
 +      bool changed = false;
 +      const int index = opop->subitem_reference_index;
 +
 +      if (!ELEM(opop->operation, IDOVERRIDESTATIC_OP_ADD, IDOVERRIDESTATIC_OP_SUBTRACT, IDOVERRIDESTATIC_OP_MULTIPLY)) {
 +              return changed;
 +      }
 +
 +      /* XXX TODO About range limits.
 +       * Ideally, it woudl be great to get rid of RNA range in that specific case.
 +       * However, this won't be that easy and will add yet another layer of complexity in generated code,
 +       * not to mention that we could most likely *not* bypass custom setters anyway.
 +       * So for now, if needed second operand value is not in valid range, we simply fall back
 +       * to a mere REPLACE operation.
 +       * Time will say whether this is acceptable limitation or not. */
 +      switch (RNA_property_type(prop_local)) {
 +              case PROP_BOOLEAN:
 +                      /* TODO support boolean ops? Really doubt this would ever be useful though... */
 +                      BLI_assert(0 && "Boolean properties support no override diff operation");
 +                      break;
 +              case PROP_INT:
 +              {
 +                      int prop_min, prop_max;
 +                      RNA_property_int_range(ptr_local, prop_local, &prop_min, &prop_max);
 +
 +                      if (len_local) {
 +                              if (index == -1) {
 +                                      int array_stack_a[RNA_STACK_ARRAY], array_stack_b[RNA_STACK_ARRAY];
 +                                      int *array_a, *array_b;
 +
 +                                      array_a = (len_local > RNA_STACK_ARRAY) ? MEM_mallocN(sizeof(*array_a) * len_local, __func__) : array_stack_a;
 +                                      RNA_property_int_get_array(ptr_reference, prop_reference, array_a);
 +
 +                                      switch (opop->operation) {
 +                                              case IDOVERRIDESTATIC_OP_ADD:
 +                                              case IDOVERRIDESTATIC_OP_SUBTRACT:
 +                                              {
 +                                                      const int fac = opop->operation == IDOVERRIDESTATIC_OP_ADD ? 1 : -1;
 +                                                      const int other_op = opop->operation == IDOVERRIDESTATIC_OP_ADD ? IDOVERRIDESTATIC_OP_SUBTRACT : IDOVERRIDESTATIC_OP_ADD;
 +                                                      bool do_set = true;
 +                                                      array_b = (len_local > RNA_STACK_ARRAY) ? MEM_mallocN(sizeof(*array_b) * len_local, __func__) : array_stack_b;
 +                                                      RNA_property_int_get_array(ptr_local, prop_local, array_b);
 +                                                      for (int i = len_local; i--;) {
 +                                                              array_b[i] = fac * (array_b[i] - array_a[i]);
 +                                                              if (array_b[i] < prop_min || array_b[i] > prop_max) {
 +                                                                      opop->operation = other_op;
 +                                                                      for (int j = len_local; j--;) {
 +                                                                              array_b[j] = j >= i ? -array_b[j] : fac * (array_a[j] - array_b[j]);
 +                                                                              if (array_b[j] < prop_min || array_b[j] > prop_max) {
 +                                                                                      /* We failed to  find a suitable diff op,
 +                                                                                       * fall back to plain REPLACE one. */
 +                                                                                      opop->operation = IDOVERRIDESTATIC_OP_REPLACE;
 +                                                                                      do_set = false;
 +                                                                                      break;
 +                                                                              }
 +                                                                      }
 +                                                                      break;
 +                                                              }
 +                                                      }
 +                                                      if (do_set) {
 +                                                              changed = true;
 +                                                              RNA_property_int_set_array(ptr_storage, prop_storage, array_b);
 +                                                      }
 +                                                      if (array_b != array_stack_b) MEM_freeN(array_b);
 +                                                      break;
 +                                              }
 +                                              default:
 +                                                      BLI_assert(0 && "Unsupported RNA override diff operation on integer");
 +                                                      break;
 +                                      }
 +
 +                                      if (array_a != array_stack_a) MEM_freeN(array_a);
 +                              }
 +                              else {
 +                                      const int value = RNA_property_int_get_index(ptr_reference, prop_reference, index);
 +
 +                                      switch (opop->operation) {
 +                                              case IDOVERRIDESTATIC_OP_ADD:
 +                                              case IDOVERRIDESTATIC_OP_SUBTRACT:
 +                                              {
 +                                                      const int fac = opop->operation == IDOVERRIDESTATIC_OP_ADD ? 1 : -1;
 +                                                      const int other_op = opop->operation == IDOVERRIDESTATIC_OP_ADD ? IDOVERRIDESTATIC_OP_SUBTRACT : IDOVERRIDESTATIC_OP_ADD;
 +                                                      int b = fac * (RNA_property_int_get_index(ptr_local, prop_local, index) - value);
 +                                                      if (b < prop_min || b > prop_max) {
 +                                                              opop->operation = other_op;
 +                                                              b = -b;
 +                                                              if (b < prop_min || b > prop_max) {
 +                                                                      opop->operation = IDOVERRIDESTATIC_OP_REPLACE;
 +                                                                      break;
 +                                                              }
 +                                                      }
 +                                                      changed = true;
 +                                                      RNA_property_int_set_index(ptr_storage, prop_storage, index, b);
 +                                                      break;
 +                                              }
 +                                              default:
 +                                                      BLI_assert(0 && "Unsupported RNA override diff operation on integer");
 +                                                      break;
 +                                      }
 +                              }
 +                      }
 +                      else {
 +                              const int value = RNA_property_int_get(ptr_reference, prop_reference);
 +
 +                              switch (opop->operation) {
 +                                      case IDOVERRIDESTATIC_OP_ADD:
 +                                      case IDOVERRIDESTATIC_OP_SUBTRACT:
 +                                      {
 +                                              const int fac = opop->operation == IDOVERRIDESTATIC_OP_ADD ? 1 : -1;
 +                                              const int other_op = opop->operation == IDOVERRIDESTATIC_OP_ADD ? IDOVERRIDESTATIC_OP_SUBTRACT : IDOVERRIDESTATIC_OP_ADD;
 +                                              int b = fac * (RNA_property_int_get(ptr_local, prop_local) - value);
 +                                              if (b < prop_min || b > prop_max) {
 +                                                      opop->operation = other_op;
 +                                                      b = -b;
 +                                                      if (b < prop_min || b > prop_max) {
 +                                                              opop->operation = IDOVERRIDESTATIC_OP_REPLACE;
 +                                                              break;
 +                                                      }
 +                                              }
 +                                              changed = true;
 +                                              RNA_property_int_set(ptr_storage, prop_storage, b);
 +                                              break;
 +                                      }
 +                                      default:
 +                                              BLI_assert(0 && "Unsupported RNA override diff operation on integer");
 +                                              break;
 +                              }
 +                      }
 +                      break;
 +              }
 +              case PROP_FLOAT:
 +              {
 +                      float prop_min, prop_max;
 +                      RNA_property_float_range(ptr_local, prop_local, &prop_min, &prop_max);
 +
 +                      if (len_local) {
 +                              if (index == -1) {
 +                                      float array_stack_a[RNA_STACK_ARRAY], array_stack_b[RNA_STACK_ARRAY];
 +                                      float *array_a, *array_b;
 +
 +                                      array_a = (len_local > RNA_STACK_ARRAY) ? MEM_mallocN(sizeof(*array_a) * len_local, __func__) : array_stack_a;
 +
 +                                      RNA_property_float_get_array(ptr_reference, prop_reference, array_a);
 +                                      switch (opop->operation) {
 +                                              case IDOVERRIDESTATIC_OP_ADD:
 +                                              case IDOVERRIDESTATIC_OP_SUBTRACT:
 +                                              {
 +                                                      const float fac = opop->operation == IDOVERRIDESTATIC_OP_ADD ? 1.0 : -1.0;
 +                                                      const int other_op = opop->operation == IDOVERRIDESTATIC_OP_ADD ? IDOVERRIDESTATIC_OP_SUBTRACT : IDOVERRIDESTATIC_OP_ADD;
 +                                                      bool do_set = true;
 +                                                      array_b = (len_local > RNA_STACK_ARRAY) ? MEM_mallocN(sizeof(*array_b) * len_local, __func__) : array_stack_b;
 +                                                      RNA_property_float_get_array(ptr_local, prop_local, array_b);
 +                                                      for (int i = len_local; i--;) {
 +                                                              array_b[i] = fac * (array_b[i] - array_a[i]);
 +                                                              if (array_b[i] < prop_min || array_b[i] > prop_max) {
 +                                                                      opop->operation = other_op;
 +                                                                      for (int j = len_local; j--;) {
 +                                                                              array_b[j] = j >= i ? -array_b[j] : fac * (array_a[j] - array_b[j]);
 +                                                                              if (array_b[j] < prop_min || array_b[j] > prop_max) {
 +                                                                                      /* We failed to  find a suitable diff op,
 +                                                                                       * fall back to plain REPLACE one. */
 +                                                                                      opop->operation = IDOVERRIDESTATIC_OP_REPLACE;
 +                                                                                      do_set = false;
 +                                                                                      break;
 +                                                                              }
 +                                                                      }
 +                                                                      break;
 +                                                              }
 +                                                      }
 +                                                      if (do_set) {
 +                                                              changed = true;
 +                                                              RNA_property_float_set_array(ptr_storage, prop_storage, array_b);
 +                                                      }
 +                                                      if (array_b != array_stack_b) MEM_freeN(array_b);
 +                                                      break;
 +                                              }
 +                                              case IDOVERRIDESTATIC_OP_MULTIPLY:
 +                                              {
 +                                                      bool do_set = true;
 +                                                      array_b = (len_local > RNA_STACK_ARRAY) ? MEM_mallocN(sizeof(*array_b) * len_local, __func__) : array_stack_b;
 +                                                      RNA_property_float_get_array(ptr_local, prop_local, array_b);
 +                                                      for (int i = len_local; i--;) {
 +                                                              array_b[i] = array_a[i] == 0.0f ? array_b[i] : array_b[i] / array_a[i];
 +                                                              if (array_b[i] < prop_min || array_b[i] > prop_max) {
 +                                                                      opop->operation = IDOVERRIDESTATIC_OP_REPLACE;
 +                                                                      do_set = false;
 +                                                                      break;
 +                                                              }
 +                                                      }
 +                                                      if (do_set) {
 +                                                              changed = true;
 +                                                              RNA_property_float_set_array(ptr_storage, prop_storage, array_b);
 +                                                      }
 +                                                      if (array_b != array_stack_b) MEM_freeN(array_b);
 +                                                      break;
 +                                              }
 +                                              default:
 +                                                      BLI_assert(0 && "Unsupported RNA override diff operation on float");
 +                                                      break;
 +                                      }
 +
 +                                      if (array_a != array_stack_a) MEM_freeN(array_a);
 +                              }
 +                              else {
 +                                      const float value = RNA_property_float_get_index(ptr_reference, prop_reference, index);
 +
 +                                      switch (opop->operation) {
 +                                              case IDOVERRIDESTATIC_OP_ADD:
 +                                              case IDOVERRIDESTATIC_OP_SUBTRACT:
 +                                              {
 +                                                      const float fac = opop->operation == IDOVERRIDESTATIC_OP_ADD ? 1.0f : -1.0f;
 +                                                      const int other_op = opop->operation == IDOVERRIDESTATIC_OP_ADD ? IDOVERRIDESTATIC_OP_SUBTRACT : IDOVERRIDESTATIC_OP_ADD;
 +                                                      float b = fac * (RNA_property_float_get_index(ptr_local, prop_local, index) - value);
 +                                                      if (b < prop_min || b > prop_max) {
 +                                                              opop->operation = other_op;
 +                                                              b = -b;
 +                                                              if (b < prop_min || b > prop_max) {
 +                                                                      opop->operation = IDOVERRIDESTATIC_OP_REPLACE;
 +                                                                      break;
 +                                                              }
 +                                                      }
 +                                                      changed = true;
 +                                                      RNA_property_float_set_index(ptr_storage, prop_storage, index, b);
 +                                                      break;
 +                                              }
 +                                              case IDOVERRIDESTATIC_OP_MULTIPLY:
 +                                              {
 +                                                      const float b = RNA_property_float_get_index(ptr_local, prop_local, index) / (value == 0.0f ?  1.0f : value);
 +                                                      if (b < prop_min || b > prop_max) {
 +                                                              opop->operation = IDOVERRIDESTATIC_OP_REPLACE;
 +                                                              break;
 +                                                      }
 +                                                      changed = true;
 +                                                      RNA_property_float_set_index(ptr_storage, prop_storage, index, b);
 +                                                      break;
 +                                              }
 +                                              default:
 +                                                      BLI_assert(0 && "Unsupported RNA override diff operation on float");
 +                                                      break;
 +                                      }
 +                              }
 +                      }
 +                      else {
 +                              const float value = RNA_property_float_get(ptr_reference, prop_reference);
 +
 +                              switch (opop->operation) {
 +                                      case IDOVERRIDESTATIC_OP_ADD:
 +                                      case IDOVERRIDESTATIC_OP_SUBTRACT:
 +                                      {
 +                                              const float fac = opop->operation == IDOVERRIDESTATIC_OP_ADD ? 1.0f : -1.0f;
 +                                              const int other_op = opop->operation == IDOVERRIDESTATIC_OP_ADD ? IDOVERRIDESTATIC_OP_SUBTRACT : IDOVERRIDESTATIC_OP_ADD;
 +                                              float b = fac * (RNA_property_float_get(ptr_local, prop_local) - value);
 +                                              if (b < prop_min || b > prop_max) {
 +                                                      opop->operation = other_op;
 +                                                      b = -b;
 +                                                      if (b < prop_min || b > prop_max) {
 +                                                              opop->operation = IDOVERRIDESTATIC_OP_REPLACE;
 +                                                              break;
 +                                                      }
 +                                              }
 +                                              changed = true;
 +                                              RNA_property_float_set(ptr_storage, prop_storage, b);
 +                                              break;
 +                                      }
 +                                      case IDOVERRIDESTATIC_OP_MULTIPLY:
 +                                      {
 +                                              const float b = RNA_property_float_get(ptr_local, prop_local) / (value == 0.0f ?  1.0f : value);
 +                                              if (b < prop_min || b > prop_max) {
 +                                                      opop->operation = IDOVERRIDESTATIC_OP_REPLACE;
 +                                                      break;
 +                                              }
 +                                              changed = true;
 +                                              RNA_property_float_set(ptr_storage, prop_storage, b);
 +                                              break;
 +                                      }
 +                                      default:
 +                                              BLI_assert(0 && "Unsupported RNA override diff operation on float");
 +                                              break;
 +                              }
 +                      }
 +                      return true;
 +              }
 +              case PROP_ENUM:
 +                      /* TODO support add/sub, for bitflags? */
 +                      BLI_assert(0 && "Enum properties support no override diff operation");
 +                      break;
 +              case PROP_POINTER:
 +                      BLI_assert(0 && "Pointer properties support no override diff operation");
 +                      break;
 +              case PROP_STRING:
 +                      BLI_assert(0 && "String properties support no override diff operation");
 +                      break;
 +              case PROP_COLLECTION:
 +                      /* XXX TODO support this of course... */
 +                      BLI_assert(0 && "Collection properties support no override diff operation");
 +                      break;
 +              default:
 +                      break;
 +      }
 +
 +      return changed;
 +}
 +
 +bool rna_property_override_apply_default(
 +        PointerRNA *ptr_dst, PointerRNA *ptr_src, PointerRNA *ptr_storage,
 +        PropertyRNA *prop_dst, PropertyRNA *prop_src, PropertyRNA *prop_storage,
 +        const int len_dst, const int len_src, const int len_storage,
 +        IDOverrideStaticPropertyOperation *opop)
 +{
 +      BLI_assert(len_dst == len_src && (!ptr_storage || len_dst == len_storage));
 +      UNUSED_VARS_NDEBUG(len_src, len_storage);
 +
 +      const int index = opop->subitem_reference_index;
 +      const short override_op = opop->operation;
 +
 +      switch (RNA_property_type(prop_dst)) {
 +              case PROP_BOOLEAN:
 +                      if (len_dst) {
 +                              if (index == -1) {
 +                                      int array_stack_a[RNA_STACK_ARRAY];
 +                                      int *array_a;
 +
 +                                      array_a = (len_dst > RNA_STACK_ARRAY) ? MEM_mallocN(sizeof(*array_a) * len_dst, __func__) : array_stack_a;
 +
 +                                      RNA_property_boolean_get_array(ptr_src, prop_src, array_a);
 +
 +                                      switch (override_op) {
 +                                              case IDOVERRIDESTATIC_OP_REPLACE:
 +                                                      RNA_property_boolean_set_array(ptr_dst, prop_dst, array_a);
 +                                                      break;
 +                                              default:
 +                                                      BLI_assert(0 && "Unsupported RNA override operation on boolean");
 +                                                      return false;
 +                                      }
 +
 +                                      if (array_a != array_stack_a) MEM_freeN(array_a);
 +                              }
 +                              else {
 +                                      const int value = RNA_property_boolean_get_index(ptr_src, prop_src, index);
 +
 +                                      switch (override_op) {
 +                                              case IDOVERRIDESTATIC_OP_REPLACE:
 +                                                      RNA_property_boolean_set_index(ptr_dst, prop_dst, index, value);
 +                                                      break;
 +                                              default:
 +                                                      BLI_assert(0 && "Unsupported RNA override operation on boolean");
 +                                                      return false;
 +                                      }
 +                              }
 +                      }
 +                      else {
 +                              const int value = RNA_property_boolean_get(ptr_src, prop_src);
 +
 +                              switch (override_op) {
 +                                      case IDOVERRIDESTATIC_OP_REPLACE:
 +                                              RNA_property_boolean_set(ptr_dst, prop_dst, value);
 +                                              break;
 +                                      default:
 +                                              BLI_assert(0 && "Unsupported RNA override operation on boolean");
 +                                              return false;
 +                              }
 +                      }
 +                      return true;
 +              case PROP_INT:
 +                      if (len_dst) {
 +                              if (index == -1) {
 +                                      int array_stack_a[RNA_STACK_ARRAY], array_stack_b[RNA_STACK_ARRAY];
 +                                      int *array_a, *array_b;
 +
 +                                      array_a = (len_dst > RNA_STACK_ARRAY) ? MEM_mallocN(sizeof(*array_a) * len_dst, __func__) : array_stack_a;
 +
 +                                      switch (override_op) {
 +                                              case IDOVERRIDESTATIC_OP_REPLACE:
 +                                                      RNA_property_int_get_array(ptr_src, prop_src, array_a);
 +                                                      RNA_property_int_set_array(ptr_dst, prop_dst, array_a);
 +                                                      break;
 +                                              case IDOVERRIDESTATIC_OP_ADD:
 +                                              case IDOVERRIDESTATIC_OP_SUBTRACT:
 +                                                      RNA_property_int_get_array(ptr_dst, prop_dst, array_a);
 +                                                      array_b = (len_dst > RNA_STACK_ARRAY) ? MEM_mallocN(sizeof(*array_b) * len_dst, __func__) : array_stack_b;
 +                                                      RNA_property_int_get_array(ptr_storage, prop_storage, array_b);
 +                                                      if (override_op == IDOVERRIDESTATIC_OP_ADD) {
 +                                                              for (int i = len_dst; i--;) array_a[i] += array_b[i];
 +                                                      }
 +                                                      else {
 +                                                              for (int i = len_dst; i--;) array_a[i] -= array_b[i];
 +                                                      }
 +                                                      RNA_property_int_set_array(ptr_dst, prop_dst, array_a);
 +                                                      if (array_b != array_stack_b) MEM_freeN(array_b);
 +                                                      break;
 +                                              default:
 +                                                      BLI_assert(0 && "Unsupported RNA override operation on integer");
 +                                                      return false;
 +                                      }
 +
 +                                      if (array_a != array_stack_a) MEM_freeN(array_a);
 +                              }
 +                              else {
 +                                      const int storage_value = ptr_storage ? RNA_property_int_get_index(ptr_storage, prop_storage, index) : 0;
 +
 +                                      switch (override_op) {
 +                                              case IDOVERRIDESTATIC_OP_REPLACE:
 +                                                      RNA_property_int_set_index(ptr_dst, prop_dst, index,
 +                                                                                 RNA_property_int_get_index(ptr_src, prop_src, index));
 +                                                      break;
 +                                              case IDOVERRIDESTATIC_OP_ADD:
 +                                                      RNA_property_int_set_index(ptr_dst, prop_dst, index,
 +                                                                                 RNA_property_int_get_index(ptr_dst, prop_dst, index) - storage_value);
 +                                                      break;
 +                                              case IDOVERRIDESTATIC_OP_SUBTRACT:
 +                                                      RNA_property_int_set_index(ptr_dst, prop_dst, index,
 +                                                                                 RNA_property_int_get_index(ptr_dst, prop_dst, index) - storage_value);
 +                                                      break;
 +                                              default:
 +                                                      BLI_assert(0 && "Unsupported RNA override operation on integer");
 +                                                      return false;
 +                                      }
 +                              }
 +                      }
 +                      else {
 +                              const int storage_value = ptr_storage ? RNA_property_int_get(ptr_storage, prop_storage) : 0;
 +
 +                              switch (override_op) {
 +                                      case IDOVERRIDESTATIC_OP_REPLACE:
 +                                              RNA_property_int_set(ptr_dst, prop_dst, RNA_property_int_get(ptr_src, prop_src));
 +                                              break;
 +                                      case IDOVERRIDESTATIC_OP_ADD:
 +                                              RNA_property_int_set(ptr_dst, prop_dst, RNA_property_int_get(ptr_dst, prop_dst) + storage_value);
 +                                              break;
 +                                      case IDOVERRIDESTATIC_OP_SUBTRACT:
 +                                              RNA_property_int_set(ptr_dst, prop_dst, RNA_property_int_get(ptr_dst, prop_dst) - storage_value);
 +                                              break;
 +                                      default:
 +                                              BLI_assert(0 && "Unsupported RNA override operation on integer");
 +                                              return false;
 +                              }
 +                      }
 +                      return true;
 +              case PROP_FLOAT:
 +                      if (len_dst) {
 +                              if (index == -1) {
 +                                      float array_stack_a[RNA_STACK_ARRAY], array_stack_b[RNA_STACK_ARRAY];
 +                                      float *array_a, *array_b;
 +
 +                                      array_a = (len_dst > RNA_STACK_ARRAY) ? MEM_mallocN(sizeof(*array_a) * len_dst, __func__) : array_stack_a;
 +
 +                                      switch (override_op) {
 +                                              case IDOVERRIDESTATIC_OP_REPLACE:
 +                                                      RNA_property_float_get_array(ptr_src, prop_src, array_a);
 +                                                      RNA_property_float_set_array(ptr_dst, prop_dst, array_a);
 +                                                      break;
 +                                              case IDOVERRIDESTATIC_OP_ADD:
 +                                              case IDOVERRIDESTATIC_OP_SUBTRACT:
 +                                              case IDOVERRIDESTATIC_OP_MULTIPLY:
 +                                                      RNA_property_float_get_array(ptr_dst, prop_dst, array_a);
 +                                                      array_b = (len_dst > RNA_STACK_ARRAY) ? MEM_mallocN(sizeof(*array_b) * len_dst, __func__) : array_stack_b;
 +                                                      RNA_property_float_get_array(ptr_storage, prop_storage, array_b);
 +                                                      if (override_op == IDOVERRIDESTATIC_OP_ADD) {
 +                                                              for (int i = len_dst; i--;) array_a[i] += array_b[i];
 +                                                      }
 +                                                      else if (override_op == IDOVERRIDESTATIC_OP_SUBTRACT) {
 +                                                              for (int i = len_dst; i--;) array_a[i] -= array_b[i];
 +                                                      }
 +                                                      else {
 +                                                              for (int i = len_dst; i--;) array_a[i] *= array_b[i];
 +                                                      }
 +                                                      RNA_property_float_set_array(ptr_dst, prop_dst, array_a);
 +                                                      if (array_b != array_stack_b) MEM_freeN(array_b);
 +                                                      break;
 +                                              default:
 +                                                      BLI_assert(0 && "Unsupported RNA override operation on float");
 +                                                      return false;
 +                                      }
 +
 +                                      if (array_a != array_stack_a) MEM_freeN(array_a);
 +                              }
 +                              else {
 +                                      const float storage_value = ptr_storage ? RNA_property_float_get_index(ptr_storage, prop_storage, index) : 0.0f;
 +
 +                                      switch (override_op) {
 +                                              case IDOVERRIDESTATIC_OP_REPLACE:
 +                                                      RNA_property_float_set_index(ptr_dst, prop_dst, index,
 +                                                                                   RNA_property_float_get_index(ptr_src, prop_src, index));
 +                                                      break;
 +                                              case IDOVERRIDESTATIC_OP_ADD:
 +                                                      RNA_property_float_set_index(ptr_dst, prop_dst, index,
 +                                                                                   RNA_property_float_get_index(ptr_dst, prop_dst, index) + storage_value);
 +                                                      break;
 +                                              case IDOVERRIDESTATIC_OP_SUBTRACT:
 +                                                      RNA_property_float_set_index(ptr_dst, prop_dst, index,
 +                                                                                   RNA_property_float_get_index(ptr_dst, prop_dst, index) - storage_value);
 +                                                      break;
 +                                              case IDOVERRIDESTATIC_OP_MULTIPLY:
 +                                                      RNA_property_float_set_index(ptr_dst, prop_dst, index,
 +                                                                                   RNA_property_float_get_index(ptr_dst, prop_dst, index) * storage_value);
 +                                                      break;
 +                                              default:
 +                                                      BLI_assert(0 && "Unsupported RNA override operation on float");
 +                                                      return false;
 +                                      }
 +                              }
 +                      }
 +                      else {
 +                              const float storage_value = ptr_storage ? RNA_property_float_get(ptr_storage, prop_storage) : 0.0f;
 +
 +                              switch (override_op) {
 +                                      case IDOVERRIDESTATIC_OP_REPLACE:
 +                                              RNA_property_float_set(ptr_dst, prop_dst, RNA_property_float_get(ptr_src, prop_src));
 +                                              break;
 +                                      case IDOVERRIDESTATIC_OP_ADD:
 +                                              RNA_property_float_set(ptr_dst, prop_dst, RNA_property_float_get(ptr_dst, prop_dst) + storage_value);
 +                                              break;
 +                                      case IDOVERRIDESTATIC_OP_SUBTRACT:
 +                                              RNA_property_float_set(ptr_dst, prop_dst, RNA_property_float_get(ptr_dst, prop_dst) - storage_value);
 +                                              break;
 +                                      case IDOVERRIDESTATIC_OP_MULTIPLY:
 +                                              RNA_property_float_set(ptr_dst, prop_dst, RNA_property_float_get(ptr_dst, prop_dst) * storage_value);
 +                                              break;
 +                                      default:
 +                                              BLI_assert(0 && "Unsupported RNA override operation on float");
 +                                              return false;
 +                              }
 +                      }
 +                      return true;
 +              case PROP_ENUM:
 +              {
 +                      const int value = RNA_property_enum_get(ptr_src, prop_src);
 +
 +                      switch (override_op) {
 +                              case IDOVERRIDESTATIC_OP_REPLACE:
 +                                      RNA_property_enum_set(ptr_dst, prop_dst, value);
 +                                      break;
 +                              /* TODO support add/sub, for bitflags? */
 +                              default:
 +                                      BLI_assert(0 && "Unsupported RNA override operation on enum");
 +                                      return false;
 +                      }
 +                      return true;
 +              }
 +              case PROP_POINTER:
 +              {
 +                      PointerRNA value = RNA_property_pointer_get(ptr_src, prop_src);
 +
 +                      switch (override_op) {
 +                              case IDOVERRIDESTATIC_OP_REPLACE:
 +                                      RNA_property_pointer_set(ptr_dst, prop_dst, value);
 +                                      break;
 +                              default:
 +                                      BLI_assert(0 && "Unsupported RNA override operation on pointer");
 +                                      return false;
 +                      }
 +                      return true;
 +              }
 +              case PROP_STRING:
 +              {
 +                      char buff[256];
 +                      char *value = RNA_property_string_get_alloc(ptr_src, prop_src, buff, sizeof(buff), NULL);
 +
 +                      switch (override_op) {
 +                              case IDOVERRIDESTATIC_OP_REPLACE:
 +                                      RNA_property_string_set(ptr_dst, prop_dst, value);
 +                                      break;
 +                              default:
 +                                      BLI_assert(0 && "Unsupported RNA override operation on string");
 +                                      return false;
 +                      }
 +
 +                      if (value != buff) MEM_freeN(value);
 +                      return true;
 +              }
 +              default:
 +                      /* TODO PROP_COLLECTION of course! */
 +                      return false;
 +      }
 +
 +      return false;
 +}
 +
 +
  
  #else
  
@@@ -2275,11 -1259,6 +2275,11 @@@ static void rna_def_property(BlenderRN
        RNA_def_property_boolean_funcs(prop, "rna_Property_animatable_get", NULL);
        RNA_def_property_ui_text(prop, "Animatable", "Property is animatable through RNA");
  
 +      prop = RNA_def_property(srna, "is_overridable", PROP_BOOLEAN, PROP_NONE);
 +      RNA_def_property_clear_flag(prop, PROP_EDITABLE);
 +      RNA_def_property_boolean_funcs(prop, "rna_Property_overridable_get", NULL);
 +      RNA_def_property_ui_text(prop, "Overridable", "Property is overridable through RNA");
 +
        prop = RNA_def_property(srna, "is_required", PROP_BOOLEAN, PROP_NONE);
        RNA_def_property_clear_flag(prop, PROP_EDITABLE);
        RNA_def_property_boolean_funcs(prop, "rna_Property_is_required_get", NULL);