Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/blenkernel/BKE_action.h5
-rw-r--r--source/blender/blenkernel/BKE_object.h2
-rw-r--r--source/blender/blenkernel/intern/action.c25
-rw-r--r--source/blender/blenkernel/intern/armature.c50
-rw-r--r--source/blender/blenkernel/intern/depsgraph.c7
-rw-r--r--source/blender/blenkernel/intern/object.c130
-rw-r--r--source/blender/blenloader/intern/readfile.c29
-rw-r--r--source/blender/blenloader/intern/writefile.c1
-rw-r--r--source/blender/include/BDR_editobject.h1
-rw-r--r--source/blender/include/BIF_interface.h1
-rw-r--r--source/blender/include/BIF_outliner.h1
-rw-r--r--source/blender/makesdna/DNA_action_types.h4
-rw-r--r--source/blender/makesdna/DNA_armature_types.h4
-rw-r--r--source/blender/makesdna/DNA_object_types.h3
-rw-r--r--source/blender/src/buttons_editing.c4
-rw-r--r--source/blender/src/editobject.c38
-rw-r--r--source/blender/src/header_view3d.c10
-rw-r--r--source/blender/src/interface.c24
-rw-r--r--source/blender/src/interface_draw.c12
-rw-r--r--source/blender/src/outliner.c7
-rw-r--r--source/blender/src/poseobject.c7
-rw-r--r--source/blender/src/space.c2
-rwxr-xr-xsource/blender/src/transform_generics.c22
23 files changed, 342 insertions, 47 deletions
diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h
index 01984eb9cba..e848ef0a11b 100644
--- a/source/blender/blenkernel/BKE_action.h
+++ b/source/blender/blenkernel/BKE_action.h
@@ -139,6 +139,11 @@ struct bAction *bake_obIPO_to_action(struct Object *ob);
void blend_poses(struct bPose *dst, struct bPose *src, float srcweight, short mode);
void extract_pose_from_pose(struct bPose *pose, const struct bPose *src);
+/* for proxy */
+void copy_pose_result(struct bPose *to, struct bPose *from);
+/* clear all transforms */
+void rest_pose(struct bPose *pose);
+
/* map global time (frame nr) to strip converted time, doesn't clip */
float get_action_frame(struct Object *ob, float cframe);
/* map strip time to global time (frame nr) */
diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h
index bbaf42a91b1..26f129ae2a5 100644
--- a/source/blender/blenkernel/BKE_object.h
+++ b/source/blender/blenkernel/BKE_object.h
@@ -55,6 +55,8 @@ void free_object(struct Object *ob);
void object_free_display(struct Object *ob);
void object_free_modifiers(struct Object *ob);
+void object_make_proxy(struct Object *ob, struct Object *target);
+
void unlink_object(struct Object *ob);
int exist_object(struct Object *obtest);
void *add_camera(void);
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
index 17910c01fa3..9f42e682e82 100644
--- a/source/blender/blenkernel/intern/action.c
+++ b/source/blender/blenkernel/intern/action.c
@@ -696,8 +696,8 @@ void extract_pose_from_action(bPose *pose, bAction *act, float ctime)
pose->ctime= ctime; /* used for cyclic offset matching */
}
-/* for do_all_pose_actions, clears the pose */
-static void rest_pose(bPose *pose)
+/* for do_all_pose_actions, clears the pose. Now also exported for proxy and tools */
+void rest_pose(bPose *pose)
{
bPoseChannel *pchan;
int i;
@@ -720,6 +720,27 @@ static void rest_pose(bPose *pose)
}
}
+/* both poses should be in sync */
+void copy_pose_result(bPose *to, bPose *from)
+{
+ bPoseChannel *pchanto, *pchanfrom;
+
+ if(to==NULL || from==NULL) {
+ printf("pose result copy error\n"); // debug temp
+ return;
+ }
+
+ pchanto= to->chanbase.first;
+ pchanfrom= from->chanbase.first;
+ for(; pchanto && pchanfrom; pchanto= pchanto->next, pchanfrom= pchanfrom->next) {
+ Mat4CpyMat4(pchanto->pose_mat, pchanfrom->pose_mat);
+ Mat4CpyMat4(pchanto->chan_mat, pchanfrom->chan_mat);
+ VECCOPY(pchanto->pose_head, pchanfrom->pose_head);
+ VECCOPY(pchanto->pose_tail, pchanfrom->pose_tail);
+ pchanto->flag= pchanfrom->flag;
+ }
+}
+
/* ********** NLA with non-poses works with ipo channels ********** */
typedef struct NlaIpoChannel {
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index 9462c508084..251a14fd4b3 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -964,6 +964,50 @@ void where_is_armature (bArmature *arm)
}
}
+/* if bone layer is protected, copy the data from proxy->pose */
+static void pose_proxy_synchronize(Object *ob, Object *proxy, int layer_protected)
+{
+ bPose *pose= ob->pose, *proxypose= proxy->pose;
+ bPoseChannel *pchan, *pchanp, pchanw;
+ bConstraint *con;
+ char *str;
+
+ if(proxypose==NULL) return;
+
+ /* clear all transformation values from library */
+ rest_pose(proxypose);
+
+ pchan= pose->chanbase.first;
+ pchanp= proxypose->chanbase.first;
+ for(; pchan && pchanp; pchan= pchan->next, pchanp= pchanp->next) {
+ if(pchan->bone->layer & layer_protected) {
+
+ /* copy posechannel to temp, but restore important pointers */
+ pchanw= *pchanp;
+ pchanw.prev= pchan->prev;
+ pchanw.next= pchan->next;
+ pchanw.parent= pchan->parent;
+ pchanw.child= pchan->child;
+ pchanw.path= NULL;
+
+ /* constraints, set target ob pointer to own object */
+ copy_constraints(&pchanw.constraints, &pchanp->constraints);
+
+ for(con= pchanw.constraints.first; con; con= con->next) {
+ if(proxy==get_constraint_target(con, &str))
+ set_constraint_target(con, ob, NULL);
+ }
+
+ /* free stuff from current channel */
+ if(pchan->path) MEM_freeN(pchan->path);
+ free_constraints(&pchan->constraints);
+
+ /* the final copy */
+ *pchan= pchanw;
+ }
+ }
+}
+
static int rebuild_pose_bone(bPose *pose, Bone *bone, bPoseChannel *parchan, int counter)
{
bPoseChannel *pchan = verify_pose_channel (pose, bone->name); // verify checks and/or adds
@@ -983,7 +1027,7 @@ static int rebuild_pose_bone(bPose *pose, Bone *bone, bPoseChannel *parchan, int
return counter;
}
-/* only after leave editmode, duplicating, but also for validating older files */
+/* only after leave editmode, duplicating, validating older files, library syncing */
/* NOTE: pose->flag is set for it */
void armature_rebuild_pose(Object *ob, bArmature *arm)
{
@@ -1019,6 +1063,10 @@ void armature_rebuild_pose(Object *ob, bArmature *arm)
}
// printf("rebuild pose %s, %d bones\n", ob->id.name, counter);
+ /* synchronize protected layers with proxy */
+ if(ob->id.lib==NULL && ob->proxy)
+ pose_proxy_synchronize(ob, ob->proxy, arm->layer_protected);
+
update_pose_constraint_flags(ob->pose); // for IK detection for example
/* the sorting */
diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c
index afe40b20893..726ce3eeba6 100644
--- a/source/blender/blenkernel/intern/depsgraph.c
+++ b/source/blender/blenkernel/intern/depsgraph.c
@@ -466,6 +466,11 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Object *ob, int
dag_add_relation(dag,node2,node,DAG_RL_OB_OB);
addtoroot = 0;
}
+ if (ob->id.lib==NULL && ob->proxy) {
+ node2 = dag_get_node(dag, ob->proxy);
+ dag_add_relation(dag, node, node2, DAG_RL_DATA_DATA|DAG_RL_OB_OB);
+ /* inverted relation, so addtoroot shouldn't be set to zero */
+ }
if (ob->transflag & OB_DUPLI) {
if((ob->transflag & OB_DUPLIGROUP) && ob->dup_group) {
@@ -588,6 +593,8 @@ struct DagForest *build_dag(struct Scene *sce, short mask)
ob= base->object;
build_dag_object(dag, scenenode, ob, mask);
+ if(ob->proxy)
+ build_dag_object(dag, scenenode, ob->proxy, mask);
/* handled in next loop */
if(ob->dup_group)
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 3a01daeca1a..0685bc268d4 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -111,7 +111,7 @@
#include "BPY_extern.h"
/* Local function protos */
-static void solve_parenting (Object *ob, Object *par, float slowmat[][4], int simul);
+static void solve_parenting (Object *ob, Object *par, float obmat[][4], float slowmat[][4], int simul);
float originmat[3][3]; /* after where_is_object(), can be used in other functions (bad!) */
Object workob;
@@ -269,7 +269,11 @@ void unlink_object(Object *ob)
/* check all objects: parents en bevels and fields */
obt= G.main->object.first;
while(obt) {
- if(obt->id.lib==NULL) {
+ if(obt->id.lib) {
+ if(obt->proxy==ob)
+ obt->proxy= NULL;
+ }
+ else {
if(obt->parent==ob) {
obt->parent= NULL;
@@ -859,6 +863,23 @@ SoftBody *copy_softbody(SoftBody *sb)
return sbn;
}
+static void copy_object_pose(Object *obn, Object *ob)
+{
+ bPoseChannel *chan;
+
+ copy_pose(&obn->pose, ob->pose, 1);
+
+ for (chan = obn->pose->chanbase.first; chan; chan=chan->next){
+ bConstraint *con;
+ char *str;
+ chan->flag &= ~(POSE_LOC|POSE_ROT|POSE_SIZE);
+ for(con= chan->constraints.first; con; con= con->next) {
+ if(ob==get_constraint_target(con, &str))
+ set_constraint_target(con, obn, NULL);
+ }
+ }
+}
+
Object *copy_object(Object *ob)
{
Object *obn;
@@ -872,7 +893,8 @@ Object *copy_object(Object *ob)
}
if(ob->bb) obn->bb= MEM_dupallocN(ob->bb);
- obn->path= 0;
+ obn->path= NULL;
+ obn->proxy= NULL;
obn->flag &= ~OB_FROMGROUP;
copy_effects(&obn->effect, &ob->effect);
@@ -894,7 +916,7 @@ Object *copy_object(Object *ob)
copy_actuators(&obn->actuators, &ob->actuators);
if(ob->pose) {
- copy_pose(&obn->pose, ob->pose, 1);
+ copy_object_pose(obn, ob);
/* backwards compat... non-armatures can get poses in older files? */
if(ob->type==OB_ARMATURE)
armature_rebuild_pose(obn, obn->data);
@@ -968,9 +990,11 @@ void make_local_object(Object *ob)
* - mixed: make copy
*/
- if(ob->id.lib==0) return;
+ if(ob->id.lib==NULL) return;
+ if(ob->proxy) return;
+
if(ob->id.us==1) {
- ob->id.lib= 0;
+ ob->id.lib= NULL;
ob->id.flag= LIB_LOCAL;
new_id(0, (ID *)ob, 0);
@@ -1020,6 +1044,48 @@ void make_local_object(Object *ob)
expand_local_object(ob);
}
+/* *************** PROXY **************** */
+
+/* proxy rule: lib_object->proxy == the one we borrow from, set temporally while object_update */
+/* local_object->proxy == pointer to library object, saved in files and read */
+
+void object_make_proxy(Object *ob, Object *target)
+{
+ /* paranoia checks */
+ if(ob->id.lib || target->id.lib==NULL) {
+ printf("cannot make proxy\n");
+ return;
+ }
+
+ ob->proxy= target;
+ target->proxy= ob;
+
+ ob->recalc= target->recalc= OB_RECALC;
+
+ /* copy transform */
+ VECCOPY(ob->loc, target->loc);
+ VECCOPY(ob->rot, target->rot);
+ VECCOPY(ob->size, target->size);
+
+ ob->parent= target->parent; /* libdata */
+ Mat4CpyMat4(ob->parentinv, target->parentinv);
+ ob->ipo= target->ipo; /* libdata */
+
+ /* skip constraints, constraintchannels, nla? */
+
+ ob->type= target->type;
+ ob->data= target->data;
+ id_us_plus((ID *)ob->data); /* ensures lib data becomes LIB_EXTERN */
+
+ /* type conversions */
+ if(target->type == OB_ARMATURE) {
+ copy_object_pose(ob, target); /* data copy, object pointers in constraints */
+ rest_pose(ob->pose); /* clear all transforms in channels */
+ armature_rebuild_pose(ob, ob->data); /* set all internal links */
+ }
+}
+
+
/* *************** CALC ****************** */
/* there is also a timing calculation in drawobject() */
@@ -1380,7 +1446,6 @@ int during_scriptlink(void) {
void where_is_object_time(Object *ob, float ctime)
{
- Object *par;
float *fp1, *fp2, slowmat[4][4] = MAT4_UNITY;
float stime, fac1, fac2, vec[3];
int a;
@@ -1395,6 +1460,7 @@ void where_is_object_time(Object *ob, float ctime)
/* this is needed to be able to grab objects with ipos, otherwise it always freezes them */
stime= bsystem_time(ob, 0, ctime, 0.0);
if(stime != ob->ctime) {
+
ob->ctime= stime;
if(ob->ipo) {
@@ -1413,8 +1479,8 @@ void where_is_object_time(Object *ob, float ctime)
}
if(ob->parent) {
- par= ob->parent;
-
+ Object *par= ob->parent;
+
if(ob->ipoflag & OB_OFFS_PARENT) ctime-= ob->sf;
/* hurms, code below conflicts with depgraph... (ton) */
@@ -1426,10 +1492,11 @@ void where_is_object_time(Object *ob, float ctime)
pushdata(par, sizeof(Object));
pop= 1;
- where_is_object_time(par, ctime);
+ if(par->id.lib && par->proxy); // was a copied matrix, no where_is! bad...
+ else where_is_object_time(par, ctime);
}
- solve_parenting(ob, par, slowmat, 0);
+ solve_parenting(ob, par, ob->obmat, slowmat, 0);
if(pop) {
poplast(par);
@@ -1474,17 +1541,17 @@ void where_is_object_time(Object *ob, float ctime)
else ob->transflag &= ~OB_NEG_SCALE;
}
-static void solve_parenting (Object *ob, Object *par, float slowmat[][4], int simul)
+static void solve_parenting (Object *ob, Object *par, float obmat[][4], float slowmat[][4], int simul)
{
float totmat[4][4];
float tmat[4][4];
- float obmat[4][4];
+ float locmat[4][4];
float vec[3];
int ok;
- object_to_mat4(ob, obmat);
+ object_to_mat4(ob, locmat);
- if(ob->partype & PARSLOW) Mat4CpyMat4(slowmat, ob->obmat);
+ if(ob->partype & PARSLOW) Mat4CpyMat4(slowmat, obmat);
switch(ob->partype & PARTYPE) {
@@ -1533,10 +1600,10 @@ static void solve_parenting (Object *ob, Object *par, float slowmat[][4], int si
// total
Mat4MulSerie(tmat, totmat, ob->parentinv,
NULL, NULL, NULL, NULL, NULL, NULL);
- Mat4MulSerie(ob->obmat, tmat, obmat,
+ Mat4MulSerie(obmat, tmat, locmat,
NULL, NULL, NULL, NULL, NULL, NULL);
- if (simul){
+ if (simul) {
}
else{
@@ -1609,7 +1676,7 @@ for a lamp that is the child of another object */
if(ob->parent) {
par= ob->parent;
- solve_parenting(ob, par, slowmat, 1);
+ solve_parenting(ob, par, ob->obmat, slowmat, 1);
if(ob->partype & PARSLOW) {
@@ -1883,17 +1950,26 @@ void minmax_object(Object *ob, float *min, float *max)
}
}
+/* proxy rule: lib_object->proxy == the one we borrow from, set on read */
+/* local_object->proxy == pointer to library object, saved in files and read */
+
+
/* the main object update call, for object matrix, constraints, keys and displist (modifiers) */
/* requires flags to be set! */
void object_handle_update(Object *ob)
{
if(ob->recalc & OB_RECALC) {
- if(ob->recalc & OB_RECALC_OB) where_is_object(ob);
+ if(ob->recalc & OB_RECALC_OB) {
+ if(ob->id.lib && ob->proxy)
+ Mat4CpyMat4(ob->obmat, ob->proxy->obmat);
+ else
+ where_is_object(ob);
+ }
if(ob->recalc & OB_RECALC_DATA) {
-// printf("recalcdata %s\n", ob->id.name+2);
+ // printf("recalcdata %s\n", ob->id.name+2);
/* includes all keys and modifiers */
if(ob->type==OB_MESH) {
@@ -1909,14 +1985,22 @@ void object_handle_update(Object *ob)
lattice_calc_modifiers(ob);
}
else if(ob->type==OB_ARMATURE) {
- /* this actually only happens for reading old files... */
+ /* this happens for reading old files and to match library armatures with poses */
if(ob->pose==NULL || (ob->pose->flag & POSE_RECALC))
armature_rebuild_pose(ob, ob->data);
- do_all_pose_actions(ob);
- where_is_pose(ob);
+
+ if(ob->id.lib && ob->proxy)
+ copy_pose_result(ob->pose, ob->proxy->pose);
+ else {
+ do_all_pose_actions(ob);
+ where_is_pose(ob);
+ }
}
}
+ if(ob->id.lib==NULL && ob->proxy)
+ object_handle_update(ob->proxy);
+
ob->recalc &= ~OB_RECALC;
}
}
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index ddbacb1ef23..fd80536dea1 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -1589,18 +1589,29 @@ static void lib_link_pose(FileData *fd, Object *ob, bPose *pose)
{
bPoseChannel *pchan;
bArmature *arm= ob->data;
- int rebuild= 0;
+ int rebuild;
+
if (!pose || !arm)
return;
+ /* always rebuild to match lib changes */
+ rebuild= (ob->id.lib==NULL && arm->id.lib);
for (pchan = pose->chanbase.first; pchan; pchan=pchan->next) {
lib_link_constraints(fd, (ID *)ob, &pchan->constraints);
- // hurms... loop in a loop, but yah... later... (ton)
+
+ /* hurms... loop in a loop, but yah... later... (ton) */
pchan->bone= get_named_bone(arm, pchan->name);
+
pchan->custom= newlibadr(fd, arm->id.lib, pchan->custom);
if(pchan->bone==NULL)
rebuild= 1;
+ else if(ob->id.lib==NULL && arm->id.lib) {
+ /* local pose selection copied to armature, bit hackish */
+ pchan->bone->flag &= ~(BONE_SELECTED|BONE_ACTIVE);
+ pchan->bone->flag |= pchan->selectflag;
+ }
}
+
if(rebuild) {
ob->recalc= OB_RECALC;
pose->flag |= POSE_RECALC;
@@ -2407,7 +2418,19 @@ static void lib_link_object(FileData *fd, Main *main)
ob->ipo= newlibadr_us(fd, ob->id.lib, ob->ipo);
ob->action = newlibadr_us(fd, ob->id.lib, ob->action);
ob->dup_group= newlibadr_us(fd, ob->id.lib, ob->dup_group);
-
+ if(ob->id.lib) {
+ /* no proxy in library data, is default local data */
+ ob->proxy= NULL; ob->proxy_group= NULL;
+ }
+ else {
+ ob->proxy= newlibadr_us(fd, ob->id.lib, ob->proxy);
+ if(ob->proxy) {
+ ob->proxy->proxy= ob;
+ /* force proxy updates after load/undo, a bit weak */
+ ob->recalc= ob->proxy->recalc= OB_RECALC;
+ }
+ ob->proxy_group= newlibadr_us(fd, ob->id.lib, ob->proxy_group);
+ }
poin= ob->data;
ob->data= newlibadr_us(fd, ob->id.lib, ob->data);
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index e92101e10e7..5577c7aa8a6 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -710,6 +710,7 @@ static void write_pose(WriteData *wd, bPose *pose)
// Write channels
for (chan=pose->chanbase.first; chan; chan=chan->next) {
write_constraints(wd, &chan->constraints);
+ chan->selectflag= chan->bone->flag & (BONE_SELECTED|BONE_ACTIVE); // gets restored on read, for library armatures
writestruct(wd, DATA, "bPoseChannel", 1, chan);
}
diff --git a/source/blender/include/BDR_editobject.h b/source/blender/include/BDR_editobject.h
index b86209f46f6..4a175728d99 100644
--- a/source/blender/include/BDR_editobject.h
+++ b/source/blender/include/BDR_editobject.h
@@ -55,6 +55,7 @@ void set_slowparent(void);
void make_vertex_parent(void);
int test_parent_loop(struct Object *par, struct Object *ob);
void make_parent(void);
+void make_proxy(void);
#define EM_WAITCURSOR (1 << 0)
#define EM_FREEDATA (1 << 1)
diff --git a/source/blender/include/BIF_interface.h b/source/blender/include/BIF_interface.h
index 41a5bc5e5a1..0f263096792 100644
--- a/source/blender/include/BIF_interface.h
+++ b/source/blender/include/BIF_interface.h
@@ -163,6 +163,7 @@ struct ScrArea;
#define BUT_COLORBAND (30<<9)
#define BUT_NORMAL (31<<9)
#define BUT_CURVE (32<<9)
+#define BUT_TOGDUAL (33<<9)
#define BUTTYPE (63<<9)
diff --git a/source/blender/include/BIF_outliner.h b/source/blender/include/BIF_outliner.h
index 4d281e08c14..dc71d02970c 100644
--- a/source/blender/include/BIF_outliner.h
+++ b/source/blender/include/BIF_outliner.h
@@ -71,6 +71,7 @@ typedef struct TreeElement {
#define TSE_VERSE_OBJ_NODE 16
#define TSE_VERSE_GEOM_NODE 17
/*#endif*/
+#define TSE_PROXY 18
/* outliner search flags */
#define OL_FIND 0
diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h
index 2c6122198b8..d27dc391f24 100644
--- a/source/blender/makesdna/DNA_action_types.h
+++ b/source/blender/makesdna/DNA_action_types.h
@@ -49,8 +49,8 @@ typedef struct bPoseChannel {
short flag; /* dynamic, for detecting transform changes */
short constflag; /* for quick detecting which constraints affect this channel */
short ikflag; /* settings for IK bones */
- short pad1;
- int pathlen; /* for drawing paths, the amount of frames */
+ short selectflag; /* copy of bone flag, so you can work with library armatures */
+ int pathlen; /* for drawing paths, the amount of frames */
short protectflag;/* protect channels from being transformed */
short pad2;
diff --git a/source/blender/makesdna/DNA_armature_types.h b/source/blender/makesdna/DNA_armature_types.h
index 0b59173afa7..cfcdd4ec959 100644
--- a/source/blender/makesdna/DNA_armature_types.h
+++ b/source/blender/makesdna/DNA_armature_types.h
@@ -76,8 +76,10 @@ typedef struct bArmature {
ListBase chainbase;
int flag;
int drawtype;
- short deformflag, layer;
+ short deformflag, pad1;
+ short layer, layer_protected; /* for buttons to work, both variables in this order together */
short ghostep, ghostsize;
+ int pad2;
}bArmature;
/* armature->flag */
diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h
index ef43ab72dfc..8a4ef6cda37 100644
--- a/source/blender/makesdna/DNA_object_types.h
+++ b/source/blender/makesdna/DNA_object_types.h
@@ -86,7 +86,8 @@ typedef struct Object {
int par1, par2, par3; /* can be vertexnrs */
char parsubstr[32]; /* String describing subobject info */
void *pardata;
- struct Object *parent, *track;
+ struct Object *parent, *track, *proxy;
+ struct Group *proxy_group;
struct Ipo *ipo;
struct Path *path;
struct BoundBox *bb;
diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c
index 48c73d2eaf0..07c02e279d2 100644
--- a/source/blender/src/buttons_editing.c
+++ b/source/blender/src/buttons_editing.c
@@ -3146,13 +3146,13 @@ static void editing_panel_armature_type(Object *ob, bArmature *arm)
uiBlockBeginAlign(block);
for(a=0; a<8; a++) {
short dx= 18;
- but= uiDefButBitS(block, TOG, 1<<a, REDRAWVIEW3D, "", 10+a*dx, 123, dx, 15, &arm->layer, 0, 0, 0, 0, "");
+ but= uiDefButBitS(block, BUT_TOGDUAL, 1<<a, REDRAWVIEW3D, "", 10+a*dx, 123, dx, 15, &arm->layer, 0, 0, 0, 0, "");
uiButSetFunc(but, armature_layer_cb, &arm->layer, (void *)(1<<a));
}
uiBlockBeginAlign(block);
for(a=8; a<16; a++) {
short dx= 18;
- but= uiDefButBitS(block, TOG, 1<<a, REDRAWVIEW3D, "", 18+a*dx, 123, dx, 15, &arm->layer, 0, 0, 0, 0, "");
+ but= uiDefButBitS(block, BUT_TOGDUAL, 1<<a, REDRAWVIEW3D, "", 18+a*dx, 123, dx, 15, &arm->layer, 0, 0, 0, 0, "");
uiButSetFunc(but, armature_layer_cb, &arm->layer, (void *)(1<<a));
}
diff --git a/source/blender/src/editobject.c b/source/blender/src/editobject.c
index f2ed963dfb5..57802d3eb3e 100644
--- a/source/blender/src/editobject.c
+++ b/source/blender/src/editobject.c
@@ -1239,6 +1239,44 @@ void make_vertex_parent(void)
/* BIF_undo_push(str); not, conflicts with editmode undo... */
}
+/* adds empty object to become local replacement data of a library-linked object */
+void make_proxy(void)
+{
+ Object *ob= OBACT;
+
+ if(G.scene->id.lib) return;
+ if(ob==NULL) return;
+
+ if(ob->id.lib==NULL) {
+ error("Can not make proxy for non-linked object");
+ }
+ else if(okee("Make Proxy Object")) {
+ Object *newob;
+ Base *newbase, *oldbase= BASACT;
+ char name[32];
+
+ newob= add_object(OB_EMPTY);
+ strcpy(name, ob->id.name+2);
+ strcat(name, "_proxy");
+ rename_id(&newob->id, name);
+
+ /* set layers OK */
+ newbase= BASACT; /* add_object sets active... */
+ newbase->lay= oldbase->lay;
+ newob->lay= newbase->lay;
+
+ /* remove base, leave user count of object, it gets linked in object_make_proxy */
+ BLI_remlink(&G.scene->base, oldbase);
+ MEM_freeN(oldbase);
+
+ object_make_proxy(newob, ob);
+
+ DAG_scene_sort(G.scene);
+ allqueue(REDRAWALL, 0);
+ BIF_undo_push("Make Proxy Object");
+ }
+}
+
int test_parent_loop(Object *par, Object *ob)
{
/* test if 'ob' is a parent somewhere in par's parents */
diff --git a/source/blender/src/header_view3d.c b/source/blender/src/header_view3d.c
index a7032aefea6..c3d57d7e2d7 100644
--- a/source/blender/src/header_view3d.c
+++ b/source/blender/src/header_view3d.c
@@ -59,6 +59,7 @@
#include "DNA_text_types.h" /* for space handlers */
#include "DNA_texture_types.h"
+#include "BKE_action.h"
#include "BKE_curve.h"
#include "BKE_depsgraph.h"
#include "BKE_displist.h"
@@ -3521,6 +3522,8 @@ static uiBlock *view3d_edit_armaturemenu(void *arg_unused)
static void do_view3d_pose_armature_transformmenu(void *arg, int event)
{
+ Object *ob= OBACT;
+
switch(event) {
case 0: /* clear origin */
clear_object('o');
@@ -3534,6 +3537,11 @@ static void do_view3d_pose_armature_transformmenu(void *arg, int event)
case 3: /* clear location */
clear_object('g');
break;
+ case 4: /* clear pose */
+ rest_pose(ob->pose);
+ DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
+ BIF_undo_push("Clear Pose");
+ break;
}
allqueue(REDRAWVIEW3D, 0);
}
@@ -3546,6 +3554,8 @@ static uiBlock *view3d_pose_armature_transformmenu(void *arg_unused)
block= uiNewBlock(&curarea->uiblocks, "view3d_pose_armature_transformmenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
uiBlockSetButmFunc(block, do_view3d_pose_armature_transformmenu, NULL);
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Clear Pose|W", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Clear Location|Alt G", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Clear Rotation|Alt R", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Clear Scale|Alt S", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
diff --git a/source/blender/src/interface.c b/source/blender/src/interface.c
index 10c97f1f894..7e94ede8fd4 100644
--- a/source/blender/src/interface.c
+++ b/source/blender/src/interface.c
@@ -1419,6 +1419,7 @@ static void ui_is_but_sel(uiBut *but)
case TOG:
case TOGR:
case TOG3:
+ case BUT_TOGDUAL:
case ICONTOG:
if(value!=but->min) push= 1;
break;
@@ -1501,12 +1502,20 @@ static int ui_do_but_KEYEVT(uiBut *but)
return (event!=0);
}
-static int ui_do_but_TOG(uiBlock *block, uiBut *but)
+static int ui_do_but_TOG(uiBlock *block, uiBut *but, int qual)
{
uiBut *bt;
double value;
int w, lvalue, push;
+ /* local hack... */
+ if(but->type==BUT_TOGDUAL && qual) {
+ if(but->pointype==SHO)
+ but->poin += 2;
+ else if(but->pointype==INT)
+ but->poin += 4;
+ }
+
value= ui_get_but_val(but);
lvalue= (int)value;
@@ -1534,6 +1543,7 @@ static int ui_do_but_TOG(uiBlock *block, uiBut *but)
if(lvalue==0) lvalue= 1<<(but->bitnr);
}
}
+
ui_set_but_val(but, (double)lvalue);
if(but->type==ICONTOG) ui_check_but(but);
// no frontbuffer draw for this one
@@ -1551,6 +1561,14 @@ static int ui_do_but_TOG(uiBlock *block, uiBut *but)
if((but->flag & UI_NO_HILITE)==0) ui_draw_but(but);
}
+ /* end local hack... */
+ if(but->type==BUT_TOGDUAL && qual) {
+ if(but->pointype==SHO)
+ but->poin -= 2;
+ else if(but->pointype==INT)
+ but->poin -= 2;
+ }
+
/* no while loop...this button is used for viewmove */
uibut_do_func(but);
@@ -3817,8 +3835,9 @@ static int ui_do_button(uiBlock *block, uiBut *but, uiEvent *uevent)
case TOGR:
case ICONTOG:
case TOGN:
+ case BUT_TOGDUAL:
if(uevent->val) {
- retval= ui_do_but_TOG(block, but);
+ retval= ui_do_but_TOG(block, but, uevent->qual);
}
break;
@@ -5483,6 +5502,7 @@ static int ui_auto_themecol(uiBut *but)
case TOG3:
case TOGR:
case TOGN:
+ case BUT_TOGDUAL:
return TH_BUT_SETTING;
case SLI:
case NUM:
diff --git a/source/blender/src/interface_draw.c b/source/blender/src/interface_draw.c
index 58ca38ec30c..b91a8f83b64 100644
--- a/source/blender/src/interface_draw.c
+++ b/source/blender/src/interface_draw.c
@@ -1507,6 +1507,18 @@ static void ui_draw_text_icon(uiBut *but)
}
}
}
+
+ if(but->type==BUT_TOGDUAL) {
+ int dualset= 0;
+ if(but->pointype==SHO)
+ dualset= BTST( *(((short *)but->poin)+1), but->bitnr);
+ else if(but->pointype==INT)
+ dualset= BTST( *(((int *)but->poin)+1), but->bitnr);
+ if(dualset) {
+ ui_draw_icon(but, ICON_DOT);
+ }
+ }
+
if(but->drawstr[0]!=0) {
int transopts;
int tog3= 0;
diff --git a/source/blender/src/outliner.c b/source/blender/src/outliner.c
index 1f15bb62205..01eb93c9f60 100644
--- a/source/blender/src/outliner.c
+++ b/source/blender/src/outliner.c
@@ -432,6 +432,9 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
{
Object *ob= (Object *)id;
+ if(ob->proxy && ob->id.lib==NULL)
+ outliner_add_element(soops, &te->subtree, ob->proxy, te, TSE_PROXY, 0);
+
outliner_add_element(soops, &te->subtree, ob->data, te, 0, 0);
if(ob->pose) {
@@ -566,7 +569,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
if(ob->dup_group)
outliner_add_element(soops, &te->subtree, ob->dup_group, te, 0, 0);
-
+
if(ob->nlastrips.first) {
bActionStrip *strip;
TreeElement *ten;
@@ -2628,6 +2631,8 @@ static void tselem_draw_icon(float x, float y, TreeStoreElem *tselem, TreeElemen
BIF_icon_draw(x, y, ICON_ARMATURE_DEHLT); break;
case TSE_POSE_CHANNEL:
BIF_icon_draw(x, y, ICON_WPAINT_DEHLT); break;
+ case TSE_PROXY:
+ BIF_icon_draw(x, y, ICON_GHOST); break;
#ifdef WITH_VERSE
case ID_VS:
case ID_MS:
diff --git a/source/blender/src/poseobject.c b/source/blender/src/poseobject.c
index cce2e3705a3..f1d7761fa6c 100644
--- a/source/blender/src/poseobject.c
+++ b/source/blender/src/poseobject.c
@@ -323,7 +323,7 @@ void pose_special_editmenu(void)
if(!ob && !ob->pose) return;
if(ob==G.obedit || (ob->flag & OB_POSEMODE)==0) return;
- nr= pupmenu("Specials%t|Select Constraint Target%x1|Flip Left-Right Names%x2|Calculate Paths%x3|Clear All Paths%x4");
+ nr= pupmenu("Specials%t|Select Constraint Target%x1|Flip Left-Right Names%x2|Calculate Paths%x3|Clear All Paths%x4|Clear Pose %x5");
if(nr==1) {
pose_select_constraint_target();
}
@@ -336,6 +336,11 @@ void pose_special_editmenu(void)
else if(nr==4) {
pose_clear_paths(ob);
}
+ else if(nr==5) {
+ rest_pose(ob->pose);
+ DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
+ BIF_undo_push("Clear Pose");
+ }
}
void pose_add_IK(void)
diff --git a/source/blender/src/space.c b/source/blender/src/space.c
index 059f4959f76..26720f825b3 100644
--- a/source/blender/src/space.c
+++ b/source/blender/src/space.c
@@ -1783,6 +1783,8 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
}
else if(G.qual==LR_ALTKEY)
clear_parent();
+ else if(G.qual==(LR_ALTKEY|LR_CTRLKEY))
+ make_proxy();
else if((G.qual==0) && (OBACT) && (OBACT->type==OB_ARMATURE) && (OBACT->flag & OB_POSEMODE))
select_bone_parent();
else if((G.qual==0)) {
diff --git a/source/blender/src/transform_generics.c b/source/blender/src/transform_generics.c
index 8b75586442b..f9e75d2336a 100755
--- a/source/blender/src/transform_generics.c
+++ b/source/blender/src/transform_generics.c
@@ -322,21 +322,23 @@ void recalcData(TransInfo *t)
}
else {
for(base= FIRSTBASE; base; base= base->next) {
+ Object *ob= base->object;
+
/* this flag is from depgraph, was stored in nitialize phase, handled in drawview.c */
if(base->flag & BA_HAS_RECALC_OB)
- base->object->recalc |= OB_RECALC_OB;
+ ob->recalc |= OB_RECALC_OB;
if(base->flag & BA_HAS_RECALC_DATA)
- base->object->recalc |= OB_RECALC_DATA;
+ ob->recalc |= OB_RECALC_DATA;
/* thanks to ob->ctime usage, ipos are not called in where_is_object,
unless we edit ipokeys */
if(base->flag & BA_DO_IPO) {
- if(base->object->ipo) {
+ if(ob->ipo) {
IpoCurve *icu;
- base->object->ctime= -1234567.0;
+ ob->ctime= -1234567.0;
- icu= base->object->ipo->curve.first;
+ icu= ob->ipo->curve.first;
while(icu) {
calchandles_ipocurve(icu);
icu= icu->next;
@@ -345,10 +347,14 @@ void recalcData(TransInfo *t)
}
/* softbody exception */
- if(modifiers_isSoftbodyEnabled(base->object)) {
- if(base->object->recalc & OB_RECALC_DATA)
- base->object->softflag |= OB_SB_REDO;
+ if(modifiers_isSoftbodyEnabled(ob)) {
+ if(ob->recalc & OB_RECALC_DATA)
+ ob->softflag |= OB_SB_REDO;
}
+
+ /* proxy exception */
+ if(ob->proxy)
+ ob->proxy->recalc |= ob->recalc;
}
}