Merge branch 'master' into blender2.8
authorCampbell Barton <ideasman42@gmail.com>
Fri, 30 Nov 2018 04:11:32 +0000 (15:11 +1100)
committerCampbell Barton <ideasman42@gmail.com>
Fri, 30 Nov 2018 04:11:32 +0000 (15:11 +1100)
14 files changed:
1  2 
source/blender/blenkernel/BKE_fcurve.h
source/blender/blenkernel/intern/anim_sys.c
source/blender/blenkernel/intern/fcurve.c
source/blender/blenkernel/intern/library_query.c
source/blender/blenkernel/intern/object.c
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/versioning_270.c
source/blender/blenloader/intern/writefile.c
source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
source/blender/depsgraph/intern/builder/deg_builder_relations.cc
source/blender/editors/animation/anim_filter.c
source/blender/editors/armature/armature_relations.c
source/blender/editors/gpencil/gpencil_data.c
source/blender/editors/space_outliner/outliner_tree.c

@@@ -956,23 -562,12 +956,23 @@@ void DepsgraphNodeBuilder::build_driver
  {
        build_driver_id_property(id, fcurve->rna_path);
        LISTBASE_FOREACH (DriverVar *, dvar, &fcurve->driver->variables) {
-               DRIVER_TARGETS_USED_LOOPER(dvar)
+               DRIVER_TARGETS_USED_LOOPER_BEGIN(dvar)
                {
 +                      if (dtar->id == NULL) {
 +                              continue;
 +                      }
                        build_id(dtar->id);
                        build_driver_id_property(dtar->id, dtar->rna_path);
 +                      /* Corresponds to dtar_id_ensure_proxy_from(). */
 +                      if ((GS(dtar->id->name) == ID_OB) &&
 +                          (((Object *)dtar->id)->proxy_from != NULL))
 +                      {
 +                              Object *proxy_from = ((Object *)dtar->id)->proxy_from;
 +                              build_id(&proxy_from->id);
 +                              build_driver_id_property(&proxy_from->id, dtar->rna_path);
 +                      }
                }
-               DRIVER_TARGETS_LOOPER_END
+               DRIVER_TARGETS_LOOPER_END;
        }
  }
  
@@@ -1530,20 -1191,22 +1530,20 @@@ void DepsgraphRelationBuilder::build_dr
                                        continue;
                                }
                                add_relation(variable_key, driver_key, "RNA Target -> Driver");
 +                              if (proxy_from != NULL) {
 +                                      RNAPathKey proxy_from_variable_key(&proxy_from->id,
 +                                                                         dtar->rna_path);
 +                                      add_relation(proxy_from_variable_key,
 +                                                   variable_key,
 +                                                   "Proxy From -> Variable");
 +                              }
                        }
                        else {
 -                              if (dtar->id == id) {
 -                                      /* Ignore input dependency if we're driving properties of
 -                                       * the same ID, otherwise we'll be ending up in a cyclic
 -                                       * dependency here.
 -                                       */
 -                                      continue;
 -                              }
 -                              /* Resolve path to get node. */
 -                              RNAPathKey target_key(dtar->id,
 -                                                    dtar->rna_path ? dtar->rna_path : "");
 -                              add_relation(target_key, driver_key, "RNA Target -> Driver");
 +                              /* If rna_path is NULL, and DTAR_FLAG_STRUCT_REF isn't set, this
 +                               * is an incomplete target reference, so nothing to do here. */
                        }
                }
-               DRIVER_TARGETS_LOOPER_END
+               DRIVER_TARGETS_LOOPER_END;
        }
  }
  
@@@ -1842,315 -1399,111 +1842,315 @@@ static int gpencil_vertex_group_smooth_
        return OPERATOR_FINISHED;
  }
  
 -void GPENCIL_OT_palette_add(wmOperatorType *ot)
 +void GPENCIL_OT_vertex_group_smooth(wmOperatorType *ot)
  {
        /* identifiers */
 -      ot->name = "Add Palette";
 -      ot->idname = "GPENCIL_OT_palette_add";
 -      ot->description = "Add new Grease Pencil palette for the active Grease Pencil data-block";
 +      ot->name = "Smooth Vertex Group";
 +      ot->idname = "GPENCIL_OT_vertex_group_smooth";
 +      ot->description = "Smooth weights to the active vertex group";
 +
 +      /* api callbacks */
 +      ot->poll = gpencil_vertex_group_weight_poll;
 +      ot->exec = gpencil_vertex_group_smooth_exec;
  
 +      /* flags */
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
  
 -      /* callbacks */
 -      ot->exec = gp_palette_add_exec;
 -      ot->poll = gp_add_poll;
 +      RNA_def_float(ot->srna, "factor", 0.5f, 0.0f, 1.0, "Factor", "", 0.0f, 1.0f);
 +      RNA_def_int(ot->srna, "repeat", 1, 1, 10000, "Iterations", "", 1, 200);
  }
  
 -/* ******************* Remove Active Palette ************************* */
 +/****************************** Join ***********************************/
  
 -static int gp_palette_remove_exec(bContext *C, wmOperator *op)
 -{
 -      bGPdata *gpd = ED_gpencil_data_get_active(C);
 -      bGPDpalette *palette = BKE_gpencil_palette_getactive(gpd);
 +/* userdata for joined_gpencil_fix_animdata_cb() */
 +typedef struct tJoinGPencil_AdtFixData {
 +      bGPdata *src_gpd;
 +      bGPdata *tar_gpd;
  
 -      /* sanity checks */
 -      if (ELEM(NULL, gpd, palette))
 -              return OPERATOR_CANCELLED;
 +      GHash *names_map;
 +} tJoinGPencil_AdtFixData;
  
 -      if (BLI_listbase_count_at_most(&gpd->palettes, 2) < 2) {
 -              BKE_report(op->reports, RPT_ERROR, "Grease Pencil needs a palette, unable to delete the last one");
 -              return OPERATOR_CANCELLED;
 -      }
 +/* Callback to pass to BKE_fcurves_main_cb() for RNA Paths attached to each F-Curve used in the AnimData */
 +static void joined_gpencil_fix_animdata_cb(ID *id, FCurve *fcu, void *user_data)
 +{
 +      tJoinGPencil_AdtFixData *afd = (tJoinGPencil_AdtFixData *)user_data;
 +      ID *src_id = &afd->src_gpd->id;
 +      ID *dst_id = &afd->tar_gpd->id;
  
 +      GHashIterator gh_iter;
  
 -      /* make the palette before this the new active palette
 -       * - use the one after if this is the first
 -       * - if this is the only palette, this naturally becomes NULL
 -       */
 -      if (palette->prev)
 -              BKE_gpencil_palette_setactive(gpd, palette->prev);
 -      else
 -              BKE_gpencil_palette_setactive(gpd, palette->next);
 +      /* Fix paths - If this is the target datablock, it will have some "dirty" paths */
 +      if ((id == src_id) && fcu->rna_path && strstr(fcu->rna_path, "layers[")) {
 +              GHASH_ITER(gh_iter, afd->names_map) {
 +                      const char *old_name = BLI_ghashIterator_getKey(&gh_iter);
 +                      const char *new_name = BLI_ghashIterator_getValue(&gh_iter);
  
 -      /* delete the palette now... */
 -      BKE_gpencil_palette_delete(gpd, palette);
 +                      /* only remap if changed; this still means there will be some waste if there aren't many drivers/keys */
 +                      if (!STREQ(old_name, new_name) && strstr(fcu->rna_path, old_name)) {
 +                              fcu->rna_path = BKE_animsys_fix_rna_path_rename(
 +                                      id, fcu->rna_path, "layers",
 +                                      old_name, new_name, 0, 0, false);
  
 -      /* notifiers */
 -      WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
 +                              /* we don't want to apply a second remapping on this F-Curve now,
 +                               * so stop trying to fix names names
 +                               */
 +                              break;
 +                      }
 +              }
 +      }
  
 -      return OPERATOR_FINISHED;
 +      /* Fix driver targets */
 +      if (fcu->driver) {
 +              /* Fix driver references to invalid ID's */
 +              for (DriverVar *dvar = fcu->driver->variables.first; dvar; dvar = dvar->next) {
 +                      /* only change the used targets, since the others will need fixing manually anyway */
-                       DRIVER_TARGETS_USED_LOOPER(dvar)
++                      DRIVER_TARGETS_USED_LOOPER_BEGIN(dvar)
 +                      {
 +                              /* change the ID's used... */
 +                              if (dtar->id == src_id) {
 +                                      dtar->id = dst_id;
 +
 +                                      /* also check on the subtarget...
 +                                       * XXX: We duplicate the logic from drivers_path_rename_fix() here, with our own
 +                                       *      little twists so that we know that it isn't going to clobber the wrong data
 +                                       */
 +                                      if (dtar->rna_path && strstr(dtar->rna_path, "layers[")) {
 +                                              GHASH_ITER(gh_iter, afd->names_map) {
 +                                                      const char *old_name = BLI_ghashIterator_getKey(&gh_iter);
 +                                                      const char *new_name = BLI_ghashIterator_getValue(&gh_iter);
 +
 +                                                      /* only remap if changed */
 +                                                      if (!STREQ(old_name, new_name)) {
 +                                                              if ((dtar->rna_path) && strstr(dtar->rna_path, old_name)) {
 +                                                                      /* Fix up path */
 +                                                                      dtar->rna_path = BKE_animsys_fix_rna_path_rename(
 +                                                                              id, dtar->rna_path, "layers",
 +                                                                              old_name, new_name, 0, 0, false);
 +                                                                      break; /* no need to try any more names for layer path */
 +                                                              }
 +                                                      }
 +                                              }
 +                                      }
 +                              }
 +                      }
-                       DRIVER_TARGETS_LOOPER_END
++                      DRIVER_TARGETS_LOOPER_END;
 +              }
 +      }
  }
  
 -void GPENCIL_OT_palette_remove(wmOperatorType *ot)
 +/* join objects called from OBJECT_OT_join */
 +int ED_gpencil_join_objects_exec(bContext *C, wmOperator *op)
  {
 -      /* identifiers */
 -      ot->name = "Remove palette";
 -      ot->idname = "GPENCIL_OT_palette_remove";
 -      ot->description = "Remove active Grease Pencil palette";
 +      Main *bmain = CTX_data_main(C);
 +      Scene *scene = CTX_data_scene(C);
 +      Depsgraph *depsgraph = CTX_data_depsgraph(C);
 +      Object  *ob_active = CTX_data_active_object(C);
 +      bGPdata *gpd_dst = NULL;
 +      bool ok = false;
 +
 +      /* Ensure we're in right mode and that the active object is correct */
 +      if (!ob_active || ob_active->type != OB_GPENCIL)
 +              return OPERATOR_CANCELLED;
  
 -      ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 +      bGPdata *gpd = (bGPdata *)ob_active->data;
 +      if ((!gpd) || GPENCIL_ANY_MODE(gpd)) {
 +              return OPERATOR_CANCELLED;
 +      }
  
 -      /* callbacks */
 -      ot->exec = gp_palette_remove_exec;
 -      ot->poll = gp_active_palette_poll;
 -}
 +      /* Ensure all rotations are applied before */
 +      // XXX: Why don't we apply them here instead of warning?
 +      CTX_DATA_BEGIN(C, Object *, ob_iter, selected_editable_objects)
 +      {
 +              if (ob_iter->type == OB_GPENCIL) {
 +                      if ((ob_iter->rot[0] != 0) ||
 +                          (ob_iter->rot[1] != 0) ||
 +                          (ob_iter->rot[2] != 0))
 +                      {
 +                              BKE_report(op->reports, RPT_ERROR, "Apply all rotations before join objects");
 +                              return OPERATOR_CANCELLED;
 +                      }
 +              }
 +      }
 +      CTX_DATA_END;
  
 -/* ********************** Change Palette ***************************** */
 +      CTX_DATA_BEGIN(C, Object *, ob_iter, selected_editable_objects)
 +      {
 +              if (ob_iter == ob_active) {
 +                      ok = true;
 +                      break;
 +              }
 +      }
 +      CTX_DATA_END;
  
 -static int gp_palette_change_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(evt))
 -{
 -      uiPopupMenu *pup;
 -      uiLayout *layout;
 +      /* that way the active object is always selected */
 +      if (ok == false) {
 +              BKE_report(op->reports, RPT_WARNING, "Active object is not a selected grease pencil");
 +              return OPERATOR_CANCELLED;
 +      }
  
 -      /* call the menu, which will call this operator again, hence the canceled */
 -      pup = UI_popup_menu_begin(C, op->type->name, ICON_NONE);
 -      layout = UI_popup_menu_layout(pup);
 -      uiItemsEnumO(layout, "GPENCIL_OT_palette_change", "palette");
 -      UI_popup_menu_end(C, pup);
 +      gpd_dst = ob_active->data;
 +      Object *ob_dst = ob_active;
 +
 +      /* loop and join all data */
 +      CTX_DATA_BEGIN(C, Object *, ob_iter, selected_editable_objects)
 +      {
 +              if ((ob_iter->type == OB_GPENCIL) && (ob_iter != ob_active)) {
 +                      /* we assume that each datablock is not already used in active object */
 +                      if (ob_active->data != ob_iter->data) {
 +                              Object *ob_src = ob_iter;
 +                              bGPdata *gpd_src = ob_iter->data;
 +
 +                              /* Apply all GP modifiers before */
 +                              for (GpencilModifierData *md = ob_iter->greasepencil_modifiers.first; md; md = md->next) {
 +                                      const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type);
 +                                      if (mti->bakeModifier) {
 +                                              mti->bakeModifier(bmain, depsgraph, md, ob_iter);
 +                                      }
 +                              }
  
 -      return OPERATOR_INTERFACE;
 -}
 +                              /* copy vertex groups to the base one's */
 +                              int old_idx = 0;
 +                              for (bDeformGroup *dg = ob_iter->defbase.first; dg; dg = dg->next) {
 +                                      bDeformGroup *vgroup = MEM_dupallocN(dg);
 +                                      int idx = BLI_listbase_count(&ob_active->defbase);
 +                                      defgroup_unique_name(vgroup, ob_active);
 +                                      BLI_addtail(&ob_active->defbase, vgroup);
 +                                      /* update vertex groups in strokes in original data */
 +                                      for (bGPDlayer *gpl_src = gpd->layers.first; gpl_src; gpl_src = gpl_src->next) {
 +                                              for (bGPDframe *gpf = gpl_src->frames.first; gpf; gpf = gpf->next) {
 +                                                      for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
 +                                                              MDeformVert *dvert;
 +                                                              int i;
 +                                                              for (i = 0, dvert = gps->dvert; i < gps->totpoints; i++, dvert++) {
 +                                                                      if ((dvert->dw) && (dvert->dw->def_nr == old_idx)) {
 +                                                                              dvert->dw->def_nr = idx;
 +                                                                      }
 +                                                              }
 +                                                      }
 +                                              }
 +                                      }
 +                                      old_idx++;
 +                              }
 +                              if (ob_active->defbase.first && ob_active->actdef == 0) {
 +                                      ob_active->actdef = 1;
 +                              }
  
 -static int gp_palette_change_exec(bContext *C, wmOperator *op)
 -{
 -      bGPdata *gpd = CTX_data_gpencil_data(C);
 -      bGPDpalette *palette = NULL;
 -      int palette_num = RNA_enum_get(op->ptr, "palette");
 +                              /* add missing materials reading source materials and checking in destination object */
 +                              short *totcol = give_totcolp(ob_src);
  
 -      /* Get palette or create new one */
 -      if (palette_num == -1) {
 -              /* Create palette */
 -              palette = BKE_gpencil_palette_addnew(gpd, DATA_("GP_Palette"), true);
 -      }
 -      else {
 -              /* Try to get palette */
 -              palette = BLI_findlink(&gpd->palettes, palette_num);
 +                              for (short i = 0; i < *totcol; i++) {
 +                                      Material *tmp_ma = give_current_material(ob_src, i + 1);
 +                                      if (BKE_gpencil_get_material_index(ob_dst, tmp_ma) == 0) {
 +                                              BKE_object_material_slot_add(bmain, ob_dst);
 +                                              assign_material(bmain, ob_dst, tmp_ma, ob_dst->totcol, BKE_MAT_ASSIGN_USERPREF);
 +                                      }
 +                              }
  
 -              if (palette == NULL) {
 -                      BKE_reportf(op->reports, RPT_ERROR, "Cannot change to non-existent palette (index = %d)", palette_num);
 -                      return OPERATOR_CANCELLED;
 +                              /* duplicate bGPDlayers  */
 +                              tJoinGPencil_AdtFixData afd = {0};
 +                              afd.src_gpd = gpd_src;
 +                              afd.tar_gpd = gpd_dst;
 +                              afd.names_map = BLI_ghash_str_new("joined_gp_layers_map");
 +
 +                              float imat[3][3], bmat[3][3];
 +                              float offset_global[3];
 +                              float offset_local[3];
 +
 +                              sub_v3_v3v3(offset_global, ob_active->loc, ob_iter->obmat[3]);
 +                              copy_m3_m4(bmat, ob_active->obmat);
 +                              invert_m3_m3(imat, bmat);
 +                              mul_m3_v3(imat, offset_global);
 +                              mul_v3_m3v3(offset_local, imat, offset_global);
 +
 +
 +                              for (bGPDlayer *gpl_src = gpd_src->layers.first; gpl_src; gpl_src = gpl_src->next) {
 +                                      bGPDlayer *gpl_new = BKE_gpencil_layer_duplicate(gpl_src);
 +                                      float diff_mat[4][4];
 +                                      float inverse_diff_mat[4][4];
 +
 +                                      /* recalculate all stroke points */
 +                                      ED_gpencil_parent_location(depsgraph, ob_iter, gpd_src, gpl_src, diff_mat);
 +                                      invert_m4_m4(inverse_diff_mat, diff_mat);
 +
 +                                      Material *ma_src = NULL;
 +                                      int idx;
 +                                      for (bGPDframe *gpf = gpl_new->frames.first; gpf; gpf = gpf->next) {
 +                                              for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
 +
 +                                                      /* reasign material. Look old material and try to find in dst */
 +                                                      ma_src = give_current_material(ob_src, gps->mat_nr + 1);
 +                                                      if (ma_src != NULL) {
 +                                                              idx = BKE_gpencil_get_material_index(ob_dst, ma_src);
 +                                                              if (idx > 0) {
 +                                                                      gps->mat_nr = idx - 1;
 +                                                              }
 +                                                              else {
 +                                                                      gps->mat_nr = 0;
 +                                                              }
 +                                                      }
 +                                                      else {
 +                                                              gps->mat_nr = 0;
 +                                                      }
 +
 +                                                      bGPDspoint *pt;
 +                                                      int i;
 +                                                      for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
 +                                                              float mpt[3];
 +                                                              mul_v3_m4v3(mpt, inverse_diff_mat, &pt->x);
 +                                                              sub_v3_v3(mpt, offset_local);
 +                                                              mul_v3_m4v3(&pt->x, diff_mat, mpt);
 +                                                      }
 +                                              }
 +                                      }
 +
 +                                      /* be sure name is unique in new object */
 +                                      BLI_uniquename(&gpd_dst->layers, gpl_new, DATA_("GP_Layer"), '.', offsetof(bGPDlayer, info), sizeof(gpl_new->info));
 +                                      BLI_ghash_insert(afd.names_map, BLI_strdup(gpl_src->info), gpl_new->info);
 +
 +                                      /* add to destination datablock */
 +                                      BLI_addtail(&gpd_dst->layers, gpl_new);
 +                              }
 +
 +                              /* Fix all the animation data */
 +                              BKE_fcurves_main_cb(bmain, joined_gpencil_fix_animdata_cb, &afd);
 +                              BLI_ghash_free(afd.names_map, MEM_freeN, NULL);
 +
 +                              /* Only copy over animdata now, after all the remapping has been done,
 +                               * so that we don't have to worry about ambiguities re which datablock
 +                               * a layer came from!
 +                               */
 +                              if (ob_iter->adt) {
 +                                      if (ob_active->adt == NULL) {
 +                                              /* no animdata, so just use a copy of the whole thing */
 +                                              ob_active->adt = BKE_animdata_copy(bmain, ob_iter->adt, 0);
 +                                      }
 +                                      else {
 +                                              /* merge in data - we'll fix the drivers manually */
 +                                              BKE_animdata_merge_copy(bmain, &ob_active->id, &ob_iter->id, ADT_MERGECOPY_KEEP_DST, false);
 +                                      }
 +                              }
 +
 +                              if (gpd_src->adt) {
 +                                      if (gpd_dst->adt == NULL) {
 +                                              /* no animdata, so just use a copy of the whole thing */
 +                                              gpd_dst->adt = BKE_animdata_copy(bmain, gpd_src->adt, 0);
 +                                      }
 +                                      else {
 +                                              /* merge in data - we'll fix the drivers manually */
 +                                              BKE_animdata_merge_copy(bmain, &gpd_dst->id, &gpd_src->id, ADT_MERGECOPY_KEEP_DST, false);
 +                                      }
 +                              }
 +                      }
 +
 +                      /* Free the old object */
 +                      ED_object_base_free_and_unlink(bmain, scene, ob_iter);
                }
        }
 +      CTX_DATA_END;
  
 -      /* Set active palette */
 -      BKE_gpencil_palette_setactive(gpd, palette);
 +      DEG_relations_tag_update(bmain);  /* because we removed object(s) */
  
 -      /* updates */
 -      WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
 +      WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
  
        return OPERATOR_FINISHED;
  }