Exemple #1
0
int join_mesh_exec(bContext *C, wmOperator *op)
{
    Main *bmain= CTX_data_main(C);
    Scene *scene= CTX_data_scene(C);
    Object *ob= CTX_data_active_object(C);
    Material **matar, *ma;
    Mesh *me;
    MVert *mvert, *mv;
    MEdge *medge = NULL;
    MFace *mface = NULL;
    Key *key, *nkey=NULL;
    KeyBlock *kb, *okb, *kbn;
    float imat[4][4], cmat[4][4], *fp1, *fp2, curpos;
    int a, b, totcol, totmat=0, totedge=0, totvert=0, totface=0, ok=0;
    int vertofs, *matmap=NULL;
    int	i, j, index, haskey=0, edgeofs, faceofs;
    bDeformGroup *dg, *odg;
    MDeformVert *dvert;
    CustomData vdata, edata, fdata;

    if(scene->obedit) {
        BKE_report(op->reports, RPT_WARNING, "Cant join while in editmode");
        return OPERATOR_CANCELLED;
    }

    /* ob is the object we are adding geometry to */
    if(!ob || ob->type!=OB_MESH) {
        BKE_report(op->reports, RPT_WARNING, "Active object is not a mesh");
        return OPERATOR_CANCELLED;
    }

    /* count & check */
    CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
        if(base->object->type==OB_MESH) {
            me= base->object->data;

            totvert+= me->totvert;
            totedge+= me->totedge;
            totface+= me->totface;
            totmat+= base->object->totcol;

            if(base->object == ob)
                ok= 1;

            /* check for shapekeys */
            if(me->key)
                haskey++;
        }
    }
    CTX_DATA_END;

    /* that way the active object is always selected */
    if(ok==0) {
        BKE_report(op->reports, RPT_WARNING, "Active object is not a selected mesh");
        return OPERATOR_CANCELLED;
    }

    /* only join meshes if there are verts to join, there aren't too many, and we only had one mesh selected */
    me= (Mesh *)ob->data;
    key= me->key;

    if(totvert==0 || totvert==me->totvert) {
        BKE_report(op->reports, RPT_WARNING, "No mesh data to join");
        return OPERATOR_CANCELLED;
    }

    if(totvert > MESH_MAX_VERTS) {
        BKE_reportf(op->reports, RPT_WARNING, "Joining results in %d vertices, limit is " STRINGIFY(MESH_MAX_VERTS), totvert);
        return OPERATOR_CANCELLED;
    }

    /* new material indices and material array */
    matar= MEM_callocN(sizeof(void*)*totmat, "join_mesh matar");
    if (totmat) matmap= MEM_callocN(sizeof(int)*totmat, "join_mesh matmap");
    totcol= ob->totcol;

    /* obact materials in new main array, is nicer start! */
    for(a=0; a<ob->totcol; a++) {
        matar[a]= give_current_material(ob, a+1);
        id_us_plus((ID *)matar[a]);
        /* increase id->us : will be lowered later */
    }

    /* - if destination mesh had shapekeys, move them somewhere safe, and set up placeholders
     * 	with arrays that are large enough to hold shapekey data for all meshes
     * -	if destination mesh didn't have shapekeys, but we encountered some in the meshes we're
     *	joining, set up a new keyblock and assign to the mesh
     */
    if(key) {
        /* make a duplicate copy that will only be used here... (must remember to free it!) */
        nkey= copy_key(key);

        /* for all keys in old block, clear data-arrays */
        for(kb= key->block.first; kb; kb= kb->next) {
            if(kb->data) MEM_freeN(kb->data);
            kb->data= MEM_callocN(sizeof(float)*3*totvert, "join_shapekey");
            kb->totelem= totvert;
            kb->weights= NULL;
        }
    }
    else if(haskey) {
        /* add a new key-block and add to the mesh */
        key= me->key= add_key((ID *)me);
        key->type = KEY_RELATIVE;
    }

    /* first pass over objects - copying materials and vertexgroups across */
    CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
        /* only act if a mesh, and not the one we're joining to */
        if((ob!=base->object) && (base->object->type==OB_MESH)) {
            me= base->object->data;

            /* Join this object's vertex groups to the base one's */
            for(dg=base->object->defbase.first; dg; dg=dg->next) {
                /* See if this group exists in the object (if it doesn't, add it to the end) */
                if(!defgroup_find_name(ob, dg->name)) {
                    odg = MEM_callocN(sizeof(bDeformGroup), "join deformGroup");
                    memcpy(odg, dg, sizeof(bDeformGroup));
                    BLI_addtail(&ob->defbase, odg);
                }
            }
            if(ob->defbase.first && ob->actdef==0)
                ob->actdef=1;


            if(me->totvert) {
                /* Add this object's materials to the base one's if they don't exist already (but only if limits not exceeded yet) */
                if(totcol < MAXMAT-1) {
                    for(a=1; a<=base->object->totcol; a++) {
                        ma= give_current_material(base->object, a);

                        for(b=0; b<totcol; b++) {
                            if(ma == matar[b]) break;
                        }
                        if(b==totcol) {
                            matar[b]= ma;
                            if(ma) {
                                id_us_plus(&ma->id);
                            }
                            totcol++;
                        }
                        if(totcol>=MAXMAT-1)
                            break;
                    }
                }

                /* if this mesh has shapekeys, check if destination mesh already has matching entries too */
                if(me->key && key) {
                    for(kb= me->key->block.first; kb; kb= kb->next) {
                        /* if key doesn't exist in destination mesh, add it */
                        if(key_get_named_keyblock(key, kb->name) == NULL) {
                            /* copy this existing one over to the new shapekey block */
                            kbn= MEM_dupallocN(kb);
                            kbn->prev= kbn->next= NULL;

                            /* adjust adrcode and other settings to fit (allocate a new data-array) */
                            kbn->data= MEM_callocN(sizeof(float)*3*totvert, "joined_shapekey");
                            kbn->totelem= totvert;
                            kbn->weights= NULL;

                            okb= key->block.last;
                            curpos= (okb) ? okb->pos : -0.1f;
                            if(key->type == KEY_RELATIVE)
                                kbn->pos= curpos + 0.1f;
                            else
                                kbn->pos= curpos;

                            BLI_addtail(&key->block, kbn);
                            kbn->adrcode= key->totkey;
                            key->totkey++;
                            if(key->totkey==1) key->refkey= kbn;

                            // XXX 2.5 Animato
#if 0
                            /* also, copy corresponding ipo-curve to ipo-block if applicable */
                            if(me->key->ipo && key->ipo) {
                                // FIXME... this is a luxury item!
                                puts("FIXME: ignoring IPO's when joining shapekeys on Meshes for now...");
                            }
#endif
                        }
                    }
                }
            }
        }
    }
    CTX_DATA_END;

    /* setup new data for destination mesh */
    memset(&vdata, 0, sizeof(vdata));
    memset(&edata, 0, sizeof(edata));
    memset(&fdata, 0, sizeof(fdata));

    mvert= CustomData_add_layer(&vdata, CD_MVERT, CD_CALLOC, NULL, totvert);
    medge= CustomData_add_layer(&edata, CD_MEDGE, CD_CALLOC, NULL, totedge);
    mface= CustomData_add_layer(&fdata, CD_MFACE, CD_CALLOC, NULL, totface);

    vertofs= 0;
    edgeofs= 0;
    faceofs= 0;

    /* inverse transform for all selected meshes in this object */
    invert_m4_m4(imat, ob->obmat);

    CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
        /* only join if this is a mesh */
        if(base->object->type==OB_MESH) {
            me= base->object->data;

            if(me->totvert) {
                /* standard data */
                CustomData_merge(&me->vdata, &vdata, CD_MASK_MESH, CD_DEFAULT, totvert);
                CustomData_copy_data(&me->vdata, &vdata, 0, vertofs, me->totvert);

                /* vertex groups */
                dvert= CustomData_get(&vdata, vertofs, CD_MDEFORMVERT);

                /* NB: vertex groups here are new version */
                if(dvert) {
                    for(i=0; i<me->totvert; i++) {
                        for(j=0; j<dvert[i].totweight; j++) {
                            /*	Find the old vertex group */
                            odg = BLI_findlink(&base->object->defbase, dvert[i].dw[j].def_nr);
                            if(odg) {
                                /*	Search for a match in the new object, and set new index */
                                for(dg=ob->defbase.first, index=0; dg; dg=dg->next, index++) {
                                    if(!strcmp(dg->name, odg->name)) {
                                        dvert[i].dw[j].def_nr = index;
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }

                /* if this is the object we're merging into, no need to do anything */
                if(base->object != ob) {
                    /* watch this: switch matmul order really goes wrong */
                    mul_m4_m4m4(cmat, base->object->obmat, imat);

                    /* transform vertex coordinates into new space */
                    for(a=0, mv=mvert; a < me->totvert; a++, mv++) {
                        mul_m4_v3(cmat, mv->co);
                    }

                    /* for each shapekey in destination mesh:
                     *	- if there's a matching one, copy it across (will need to transform vertices into new space...)
                     *	- otherwise, just copy own coordinates of mesh (no need to transform vertex coordinates into new space)
                     */
                    if(key) {
                        /* if this mesh has any shapekeys, check first, otherwise just copy coordinates */
                        for(kb= key->block.first; kb; kb= kb->next) {
                            /* get pointer to where to write data for this mesh in shapekey's data array */
                            fp1= ((float *)kb->data) + (vertofs*3);

                            /* check if this mesh has such a shapekey */
                            okb= key_get_named_keyblock(me->key, kb->name);
                            if(okb) {
                                /* copy this mesh's shapekey to the destination shapekey (need to transform first) */
                                fp2= ((float *)(okb->data));
                                for(a=0; a < me->totvert; a++, fp1+=3, fp2+=3) {
                                    VECCOPY(fp1, fp2);
                                    mul_m4_v3(cmat, fp1);
                                }
                            }
                            else {
                                /* copy this mesh's vertex coordinates to the destination shapekey */
                                mv= mvert;
                                for(a=0; a < me->totvert; a++, fp1+=3, mv++) {
                                    VECCOPY(fp1, mv->co);
                                }
                            }
                        }
                    }
                }
                else {
                    /* for each shapekey in destination mesh:
                     *	- if it was an 'original', copy the appropriate data from nkey
                     *	- otherwise, copy across plain coordinates (no need to transform coordinates)
                     */
                    if(key) {
                        for(kb= key->block.first; kb; kb= kb->next) {
                            /* get pointer to where to write data for this mesh in shapekey's data array */
                            fp1= ((float *)kb->data) + (vertofs*3);

                            /* check if this was one of the original shapekeys */
                            okb= key_get_named_keyblock(nkey, kb->name);
                            if(okb) {
                                /* copy this mesh's shapekey to the destination shapekey */
                                fp2= ((float *)(okb->data));
                                for(a=0; a < me->totvert; a++, fp1+=3, fp2+=3) {
                                    VECCOPY(fp1, fp2);
                                }
                            }
                            else {
                                /* copy base-coordinates to the destination shapekey */
                                mv= mvert;
                                for(a=0; a < me->totvert; a++, fp1+=3, mv++) {
                                    VECCOPY(fp1, mv->co);
                                }
                            }
                        }
                    }
                }

                /* advance mvert pointer to end of base mesh's data */
                mvert+= me->totvert;
            }

            if(me->totface) {
                /* make mapping for materials */
                for(a=1; a<=base->object->totcol; a++) {
                    ma= give_current_material(base->object, a);

                    for(b=0; b<totcol; b++) {
                        if(ma == matar[b]) {
                            matmap[a-1]= b;
                            break;
                        }
                    }
                }

                if(base->object!=ob)
                    multiresModifier_prepare_join(scene, base->object, ob);

                CustomData_merge(&me->fdata, &fdata, CD_MASK_MESH, CD_DEFAULT, totface);
                CustomData_copy_data(&me->fdata, &fdata, 0, faceofs, me->totface);

                for(a=0; a<me->totface; a++, mface++) {
                    mface->v1+= vertofs;
                    mface->v2+= vertofs;
                    mface->v3+= vertofs;
                    if(mface->v4) mface->v4+= vertofs;

                    if (matmap)
                        mface->mat_nr= matmap[(int)mface->mat_nr];
                    else
                        mface->mat_nr= 0;
                }

                faceofs += me->totface;
            }

            if(me->totedge) {
                CustomData_merge(&me->edata, &edata, CD_MASK_MESH, CD_DEFAULT, totedge);
                CustomData_copy_data(&me->edata, &edata, 0, edgeofs, me->totedge);

                for(a=0; a<me->totedge; a++, medge++) {
                    medge->v1+= vertofs;
                    medge->v2+= vertofs;
                }

                edgeofs += me->totedge;
            }

            /* vertofs is used to help newly added verts be reattached to their edge/face
             * (cannot be set earlier, or else reattaching goes wrong)
             */
            vertofs += me->totvert;

            /* free base, now that data is merged */
            if(base->object != ob)
                ED_base_object_free_and_unlink(bmain, scene, base);
        }
    }
    CTX_DATA_END;

    /* return to mesh we're merging to */
    me= ob->data;

    CustomData_free(&me->vdata, me->totvert);
    CustomData_free(&me->edata, me->totedge);
    CustomData_free(&me->fdata, me->totface);

    me->totvert= totvert;
    me->totedge= totedge;
    me->totface= totface;

    me->vdata= vdata;
    me->edata= edata;
    me->fdata= fdata;

    mesh_update_customdata_pointers(me);

    /* old material array */
    for(a=1; a<=ob->totcol; a++) {
        ma= ob->mat[a-1];
        if(ma) ma->id.us--;
    }
    for(a=1; a<=me->totcol; a++) {
        ma= me->mat[a-1];
        if(ma) ma->id.us--;
    }
    if(ob->mat) MEM_freeN(ob->mat);
    if(ob->matbits) MEM_freeN(ob->matbits);
    if(me->mat) MEM_freeN(me->mat);
    ob->mat= me->mat= NULL;
    ob->matbits= NULL;

    if(totcol) {
        me->mat= matar;
        ob->mat= MEM_callocN(sizeof(void *)*totcol, "join obmatar");
        ob->matbits= MEM_callocN(sizeof(char)*totcol, "join obmatbits");
    }
    else
        MEM_freeN(matar);

    ob->totcol= me->totcol= totcol;
    ob->colbits= 0;

    if (matmap) MEM_freeN(matmap);

    /* other mesh users */
    test_object_materials((ID *)me);

    /* free temp copy of destination shapekeys (if applicable) */
    if(nkey) {
        // XXX 2.5 Animato
#if 0
        /* free it's ipo too - both are not actually freed from memory yet as ID-blocks */
        if(nkey->ipo) {
            free_ipo(nkey->ipo);
            BLI_remlink(&bmain->ipo, nkey->ipo);
            MEM_freeN(nkey->ipo);
        }
#endif

        free_key(nkey);
        BLI_remlink(&bmain->key, nkey);
        MEM_freeN(nkey);
    }

    DAG_scene_sort(bmain, scene);	// removed objects, need to rebuild dag before editmode call

#if 0
    ED_object_enter_editmode(C, EM_WAITCURSOR);
    ED_object_exit_editmode(C, EM_FREEDATA|EM_WAITCURSOR|EM_DO_UNDO);
#else
    /* toggle editmode using lower level functions so this can be called from python */
    make_editMesh(scene, ob);
    load_editMesh(scene, ob);
    free_editMesh(me->edit_mesh);
    MEM_freeN(me->edit_mesh);
    me->edit_mesh= NULL;
    DAG_id_tag_update(&ob->id, OB_RECALC_OB|OB_RECALC_DATA);
#endif
    WM_event_add_notifier(C, NC_SCENE|ND_OB_ACTIVE, scene);

    return OPERATOR_FINISHED;
}
Exemple #2
0
static int border_select_exec(bContext *C, wmOperator *op)
{
	ScrArea *sa = CTX_wm_area(C);
	ARegion *ar = CTX_wm_region(C);

	Mask *mask = CTX_data_edit_mask(C);
	MaskLayer *masklay;
	int i;

	rcti rect;
	rctf rectf;
	bool changed = false;
	const bool select = !RNA_boolean_get(op->ptr, "deselect");
	const bool extend = RNA_boolean_get(op->ptr, "extend");

	/* get rectangle from operator */
	WM_operator_properties_border_to_rcti(op, &rect);

	ED_mask_point_pos(sa, ar, rect.xmin, rect.ymin, &rectf.xmin, &rectf.ymin);
	ED_mask_point_pos(sa, ar, rect.xmax, rect.ymax, &rectf.xmax, &rectf.ymax);

	/* do actual selection */
	for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
		MaskSpline *spline;

		if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
			continue;
		}

		for (spline = masklay->splines.first; spline; spline = spline->next) {
			MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);

			for (i = 0; i < spline->tot_point; i++) {
				MaskSplinePoint *point = &spline->points[i];
				MaskSplinePoint *point_deform = &points_array[i];

				/* TODO: handles? */
				/* TODO: uw? */

				if (BLI_rctf_isect_pt_v(&rectf, point_deform->bezt.vec[1])) {
					BKE_mask_point_select_set(point, select);
					BKE_mask_point_select_set_handle(point, MASK_WHICH_HANDLE_BOTH, select);
				}
				else if (!extend) {
					BKE_mask_point_select_set(point, false);
					BKE_mask_point_select_set_handle(point, MASK_WHICH_HANDLE_BOTH, false);
				}

				changed = true;
			}
		}
	}

	if (changed) {
		ED_mask_select_flush_all(mask);

		WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);

		return OPERATOR_FINISHED;
	}

	return OPERATOR_CANCELLED;
}
Exemple #3
0
static int mask_select_more_less(bContext *C, bool more)
{
	Mask *mask = CTX_data_edit_mask(C);
	MaskLayer *masklay;

	for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
		MaskSpline *spline;

		if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
			continue;
		}

		for (spline = masklay->splines.first; spline; spline = spline->next) {
			const bool cyclic = (spline->flag & MASK_SPLINE_CYCLIC) != 0;
			bool start_sel, end_sel, prev_sel, cur_sel;
			int i;

			/* reselect point if any handle is selected to make the result more predictable */
			for (i = 0; i < spline->tot_point; i++) {
				BKE_mask_point_select_set(spline->points + i, MASKPOINT_ISSEL_ANY(spline->points + i));
			}

			/* select more/less does not affect empty/single point splines */
			if (spline->tot_point < 2) {
				continue;
			}

			if (cyclic) {
				start_sel = !!MASKPOINT_ISSEL_KNOT(spline->points);
				end_sel = !!MASKPOINT_ISSEL_KNOT(&spline->points[spline->tot_point - 1]);
			}
			else {
				start_sel = false;
				end_sel = false;
			}

			for (i = 0; i < spline->tot_point; i++) {
				if (i == 0 && !cyclic) {
					continue;
				}

				prev_sel = (i > 0) ? !!MASKPOINT_ISSEL_KNOT(&spline->points[i - 1]) : end_sel;
				cur_sel = !!MASKPOINT_ISSEL_KNOT(&spline->points[i]);

				if (cur_sel != more) {
					if (prev_sel == more) {
						BKE_mask_point_select_set(&spline->points[i], more);
					}
					i++;
				}
			}

			for (i = spline->tot_point - 1; i >= 0; i--) {
				if (i == spline->tot_point - 1 && !cyclic) {
					continue;
				}

				prev_sel = (i < spline->tot_point - 1) ? !!MASKPOINT_ISSEL_KNOT(&spline->points[i + 1]) : start_sel;
				cur_sel = !!MASKPOINT_ISSEL_KNOT(&spline->points[i]);

				if (cur_sel != more) {
					if (prev_sel == more) {
						BKE_mask_point_select_set(&spline->points[i], more);
					}
					i--;
				}
			}
		}
	}

	WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);

	return OPERATOR_FINISHED;
}
Exemple #4
0
/* create new expression for button (i.e. a "scripted driver"), if it can be created... */
int ui_but_anim_expression_create(uiBut *but, const char *str)
{
	bContext *C = but->block->evil_C;
	ID *id;
	FCurve *fcu;
	char *path;
	short ok=0;
	
	/* button must have RNA-pointer to a numeric-capable property */
	if (ELEM(NULL, but->rnapoin.data, but->rnaprop)) {
		if (G.f & G_DEBUG) 
			printf("ERROR: create expression failed - button has no RNA info attached\n");
		return 0;
	}
	
	/* make sure we have animdata for this */
	// FIXME: until materials can be handled by depsgraph, don't allow drivers to be created for them
	id = (ID *)but->rnapoin.id.data;
	if ((id == NULL) || (GS(id->name)==ID_MA) || (GS(id->name)==ID_TE)) {
		if (G.f & G_DEBUG)
			printf("ERROR: create expression failed - invalid id-datablock for adding drivers (%p)\n", id);
		return 0;
	}
	
	/* get path */
	path = RNA_path_from_ID_to_property(&but->rnapoin, but->rnaprop);
	
	/* create driver */
	fcu = verify_driver_fcurve(id, path, but->rnaindex, 1);
	if (fcu) {
		ChannelDriver *driver= fcu->driver;
		
		if (driver) {
			/* set type of driver */
			driver->type = DRIVER_TYPE_PYTHON;
			
			/* set the expression */
			// TODO: need some way of identifying variables used
			BLI_strncpy(driver->expression, str, sizeof(driver->expression));
			
			/* FIXME: for now, assume that 
			 * 	- for expressions, users are likely to be using "frame" -> current frame" as a variable
			 *	- driver_add_new_variable() adds a single-prop variable by default
			 */
			{
				DriverVar *dvar;
				DriverTarget *dtar;
				
				dvar = driver_add_new_variable(driver);
				BLI_strncpy(dvar->name, "frame", sizeof(dvar->name));
				
				dtar = &dvar->targets[0];
				dtar->id = (ID *)CTX_data_scene(C); // XXX: should we check that C is valid first?
				dtar->rna_path = BLI_sprintfN("frame_current");
			}
			
			/* updates */
			driver->flag |= DRIVER_FLAG_RECOMPILE;
			WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME, NULL);
		}
	}
	
	MEM_freeN(path);
	
	return ok;
}
static int curvesurf_prim_add(bContext *C, wmOperator *op, int type, int isSurf)
{
	Object *obedit = CTX_data_edit_object(C);
	ListBase *editnurb;
	Nurb *nu;
	bool newob = false;
	bool enter_editmode;
	unsigned int layer;
	float dia;
	float loc[3], rot[3];
	float mat[4][4];

	WM_operator_view3d_unit_defaults(C, op);

	if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &layer, NULL))
		return OPERATOR_CANCELLED;

	if (!isSurf) { /* adding curve */
		if (obedit == NULL || obedit->type != OB_CURVE) {
			Curve *cu;

			obedit = ED_object_add_type(C, OB_CURVE, loc, rot, true, layer);
			newob = true;

			cu = (Curve *)obedit->data;
			cu->flag |= CU_DEFORM_FILL;

			if (type & CU_PRIM_PATH)
				cu->flag |= CU_PATH | CU_3D;
		}
		else {
			DAG_id_tag_update(&obedit->id, OB_RECALC_DATA);
		}
	}
	else { /* adding surface */
		if (obedit == NULL || obedit->type != OB_SURF) {
			obedit = ED_object_add_type(C, OB_SURF, loc, rot, true, layer);
			newob = true;
		}
		else {
			DAG_id_tag_update(&obedit->id, OB_RECALC_DATA);
		}
	}

	/* rename here, the undo stack checks name for valid undo pushes */
	if (newob) {
		if (obedit->type == OB_CURVE) {
			rename_id((ID *)obedit, get_curve_defname(type));
			rename_id((ID *)obedit->data, get_curve_defname(type));
		}
		else {
			rename_id((ID *)obedit, get_surf_defname(type));
			rename_id((ID *)obedit->data, get_surf_defname(type));
		}
	}

	/* ED_object_add_type doesnt do an undo, is needed for redo operator on primitive */
	if (newob && enter_editmode)
		ED_undo_push(C, "Enter Editmode");

	ED_object_new_primitive_matrix(C, obedit, loc, rot, mat);
	dia = RNA_float_get(op->ptr, "radius");
	mul_mat3_m4_fl(mat, dia);

	nu = add_nurbs_primitive(C, obedit, mat, type, newob);
	editnurb = object_editcurve_get(obedit);
	BLI_addtail(editnurb, nu);

	/* userdef */
	if (newob && !enter_editmode) {
		ED_object_editmode_exit(C, EM_FREEDATA);
	}

	WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obedit);

	return OPERATOR_FINISHED;
}
Exemple #6
0
/* hardcoded to event TIMERJOBS */
void wm_jobs_timer(const bContext *C, wmWindowManager *wm, wmTimer *wt)
{
	wmJob *wm_job, *wm_jobnext;
	float total_progress = 0.f;
	float jobs_progress = 0;
	
	for (wm_job = wm->jobs.first; wm_job; wm_job = wm_jobnext) {
		wm_jobnext = wm_job->next;
		
		if (wm_job->wt == wt) {
			
			/* running threads */
			if (wm_job->threads.first) {

				/* let threads get temporary lock over main thread if needed */
				wm_job_main_thread_yield(wm_job, false);
				
				/* always call note and update when ready */
				if (wm_job->do_update || wm_job->ready) {
					if (wm_job->update)
						wm_job->update(wm_job->run_customdata);
					if (wm_job->note)
						WM_event_add_notifier(C, wm_job->note, NULL);

					if (wm_job->flag & WM_JOB_PROGRESS)
						WM_event_add_notifier(C, NC_WM | ND_JOB, NULL);
					wm_job->do_update = FALSE;
				}
				
				if (wm_job->ready) {
					if (wm_job->endjob)
						wm_job->endjob(wm_job->run_customdata);

					/* free own data */
					wm_job->run_free(wm_job->run_customdata);
					wm_job->run_customdata = NULL;
					wm_job->run_free = NULL;
					
					// if (wm_job->stop) printf("job ready but stopped %s\n", wm_job->name);
					// else printf("job finished %s\n", wm_job->name);

					if (G.debug & G_DEBUG_JOBS) {
						printf("Job '%s' finished in %f seconds\n", wm_job->name,
						       PIL_check_seconds_timer() - wm_job->start_time);
					}

					wm_job->running = FALSE;
					wm_job_main_thread_yield(wm_job, true);
					BLI_end_threads(&wm_job->threads);
					wm_job->main_thread_mutex_ending = false;
					
					if (wm_job->endnote)
						WM_event_add_notifier(C, wm_job->endnote, NULL);
					
					WM_event_add_notifier(C, NC_WM | ND_JOB, NULL);

					/* new job added for wm_job? */
					if (wm_job->customdata) {
						// printf("job restarted with new data %s\n", wm_job->name);
						WM_jobs_start(wm, wm_job);
					}
					else {
						WM_event_remove_timer(wm, wm_job->win, wm_job->wt);
						wm_job->wt = NULL;
						
						/* remove wm_job */
						wm_job_free(wm, wm_job);
					}
				}
				else if (wm_job->flag & WM_JOB_PROGRESS) {
					/* accumulate global progress for running jobs */
					jobs_progress++;
					total_progress += wm_job->progress;
				}
			}
			else if (wm_job->suspended) {
				WM_jobs_start(wm, wm_job);
			}
		}
		else if (wm_job->threads.first && !wm_job->ready) {
			if (wm_job->flag & WM_JOB_PROGRESS) {
				/* accumulate global progress for running jobs */
				jobs_progress++;
				total_progress += wm_job->progress;
			}
		}
	}
	
	/* on file load 'winactive' can be NULL, possibly it should not happen but for now do a NULL check - campbell */
	if (wm->winactive) {
		/* if there are running jobs, set the global progress indicator */
		if (jobs_progress > 0) {
			float progress = total_progress / (float)jobs_progress;
			WM_progress_set(wm->winactive, progress);
		}
		else {
			WM_progress_clear(wm->winactive);
		}
	}
}
Exemple #7
0
void WM_file_read(bContext *C, const char *filepath, ReportList *reports)
{
	int retval;

	/* so we can get the error message */
	errno = 0;

	WM_cursor_wait(1);

	BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_PRE);

	/* first try to append data from exotic file formats... */
	/* it throws error box when file doesn't exist and returns -1 */
	/* note; it should set some error message somewhere... (ton) */
	retval = wm_read_exotic(CTX_data_scene(C), filepath);
	
	/* we didn't succeed, now try to read Blender file */
	if (retval == BKE_READ_EXOTIC_OK_BLEND) {
		int G_f = G.f;
		ListBase wmbase;

		/* assume automated tasks with background, don't write recent file list */
		const int do_history = (G.background == FALSE) && (CTX_wm_manager(C)->op_undo_depth == 0);

		/* put aside screens to match with persistent windows later */
		/* also exit screens and editors */
		wm_window_match_init(C, &wmbase); 
		
		/* confusing this global... */
		G.relbase_valid = 1;
		retval = BKE_read_file(C, filepath, reports);
		/* when loading startup.blend's, we can be left with a blank path */
		if (G.main->name[0]) {
			G.save_over = 1;
		}
		else {
			G.save_over = 0;
			G.relbase_valid = 0;
		}

		/* this flag is initialized by the operator but overwritten on read.
		 * need to re-enable it here else drivers + registered scripts wont work. */
		if (G.f != G_f) {
			const int flags_keep = (G_SCRIPT_AUTOEXEC | G_SCRIPT_OVERRIDE_PREF);
			G.f = (G.f & ~flags_keep) | (G_f & flags_keep);
		}

		/* match the read WM with current WM */
		wm_window_match_do(C, &wmbase);
		WM_check(C); /* opens window(s), checks keymaps */

		if (retval == BKE_READ_FILE_OK_USERPREFS) {
			/* in case a userdef is read from regular .blend */
			wm_init_userdef(C, false);
		}
		
		if (retval != BKE_READ_FILE_FAIL) {
			if (do_history) {
				write_history();
			}
		}


		WM_event_add_notifier(C, NC_WM | ND_FILEREAD, NULL);
//		refresh_interface_font();

		CTX_wm_window_set(C, CTX_wm_manager(C)->windows.first);

		ED_editors_init(C);
		DAG_on_visible_update(CTX_data_main(C), TRUE);

#ifdef WITH_PYTHON
		/* run any texts that were loaded in and flagged as modules */
		BPY_python_reset(C);
#endif

		/* important to do before NULL'ing the context */
		BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_POST);

		if (!G.background) {
			/* in background mode this makes it hard to load
			 * a blend file and do anything since the screen
			 * won't be set to a valid value again */
			CTX_wm_window_set(C, NULL); /* exits queues */
		}

#if 0
		/* gives popups on windows but not linux, bug in report API
		 * but disable for now to stop users getting annoyed  */
		/* TODO, make this show in header info window */
		{
			Scene *sce;
			for (sce = G.main->scene.first; sce; sce = sce->id.next) {
				if (sce->r.engine[0] &&
				    BLI_findstring(&R_engines, sce->r.engine, offsetof(RenderEngineType, idname)) == NULL)
				{
					BKE_reportf(reports, RPT_ERROR, "Engine '%s' not available for scene '%s' "
					            "(an addon may need to be installed or enabled)",
					            sce->r.engine, sce->id.name + 2);
				}
			}
		}
#endif

		BKE_reset_undo();
		BKE_write_undo(C, "original");  /* save current state */
	}
	else if (retval == BKE_READ_EXOTIC_OK_OTHER)
		BKE_write_undo(C, "Import file");
	else if (retval == BKE_READ_EXOTIC_FAIL_OPEN) {
		BKE_reportf(reports, RPT_ERROR, "Cannot read file '%s': %s", filepath,
		            errno ? strerror(errno) : TIP_("unable to open the file"));
	}
	else if (retval == BKE_READ_EXOTIC_FAIL_FORMAT) {
		BKE_reportf(reports, RPT_ERROR, "File format is not supported in file '%s'", filepath);
	}
	else if (retval == BKE_READ_EXOTIC_FAIL_PATH) {
		BKE_reportf(reports, RPT_ERROR, "File path '%s' invalid", filepath);
	}
	else {
		BKE_reportf(reports, RPT_ERROR, "Unknown error loading '%s'", filepath);
		BLI_assert(!"invalid 'retval'");
	}

	WM_cursor_wait(0);

}
Exemple #8
0
static int outliner_data_operation_exec(bContext *C, wmOperator *op)
{
	SpaceOops *soops = CTX_wm_space_outliner(C);
	int scenelevel = 0, objectlevel = 0, idlevel = 0, datalevel = 0;
	eOutliner_PropDataOps event;
	
	/* check for invalid states */
	if (soops == NULL)
		return OPERATOR_CANCELLED;
	
	event = RNA_enum_get(op->ptr, "type");
	set_operation_types(soops, &soops->tree, &scenelevel, &objectlevel, &idlevel, &datalevel);
	
	switch (datalevel) {
		case TSE_POSE_CHANNEL:
		{
			outliner_do_data_operation(soops, datalevel, event, &soops->tree, pchan_cb, NULL);
			WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL);
			ED_undo_push(C, "PoseChannel operation");
		}
			break;
		
		case TSE_BONE:
		{
			outliner_do_data_operation(soops, datalevel, event, &soops->tree, bone_cb, NULL);
			WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL);
			ED_undo_push(C, "Bone operation");
		}
			break;
			
		case TSE_EBONE:
		{
			outliner_do_data_operation(soops, datalevel, event, &soops->tree, ebone_cb, NULL);
			WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL);
			ED_undo_push(C, "EditBone operation");
		}
			break;
			
		case TSE_SEQUENCE:
		{
			Scene *scene = CTX_data_scene(C);
			outliner_do_data_operation(soops, datalevel, event, &soops->tree, sequence_cb, scene);
		}
			break;
			
		case TSE_GP_LAYER:
		{
			outliner_do_data_operation(soops, datalevel, event, &soops->tree, gp_layer_cb, NULL);
			WM_event_add_notifier(C, NC_GPENCIL | ND_DATA, NULL);
			ED_undo_push(C, "Grease Pencil Layer operation");
		}
			break;
			
		case TSE_RNA_STRUCT:
			if (event == OL_DOP_SELECT_LINKED) {
				outliner_do_data_operation(soops, datalevel, event, &soops->tree, data_select_linked_cb, C);
			}
			break;
			
		default:
			BKE_report(op->reports, RPT_WARNING, "Not yet implemented");
			break;
	}
	
	return OPERATOR_FINISHED;
}
Exemple #9
0
static int outliner_object_operation_exec(bContext *C, wmOperator *op)
{
	Main *bmain = CTX_data_main(C);
	Scene *scene = CTX_data_scene(C);
	SpaceOops *soops = CTX_wm_space_outliner(C);
	int event;
	const char *str = NULL;
	
	/* check for invalid states */
	if (soops == NULL)
		return OPERATOR_CANCELLED;
	
	event = RNA_enum_get(op->ptr, "type");

	if (event == OL_OP_SELECT) {
		Scene *sce = scene;  // to be able to delete, scenes are set...
		outliner_do_object_operation(C, scene, soops, &soops->tree, object_select_cb);
		if (scene != sce) {
			ED_screen_set_scene(C, CTX_wm_screen(C), sce);
		}
		
		str = "Select Objects";
		WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
	}
	else if (event == OL_OP_SELECT_HIERARCHY) {
		Scene *sce = scene;  // to be able to delete, scenes are set...
		outliner_do_object_operation(C, scene, soops, &soops->tree, object_select_hierarchy_cb);
		if (scene != sce) {
			ED_screen_set_scene(C, CTX_wm_screen(C), sce);
		}	
		str = "Select Object Hierarchy";
		WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
	}
	else if (event == OL_OP_DESELECT) {
		outliner_do_object_operation(C, scene, soops, &soops->tree, object_deselect_cb);
		str = "Deselect Objects";
		WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
	}
	else if (event == OL_OP_DELETE) {
		outliner_do_object_operation(C, scene, soops, &soops->tree, object_delete_cb);

		/* XXX: tree management normally happens from draw_outliner(), but when
		 *      you're clicking to fast on Delete object from context menu in
		 *      outliner several mouse events can be handled in one cycle without
		 *      handling notifiers/redraw which leads to deleting the same object twice.
		 *      cleanup tree here to prevent such cases. */
		outliner_cleanup_tree(soops);

		DAG_relations_tag_update(bmain);
		str = "Delete Objects";
		WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
	}
	else if (event == OL_OP_DELETE_HIERARCHY) {
		outliner_do_object_operation(C, scene, soops, &soops->tree, object_delete_hierarchy_cb);

		/* XXX: See OL_OP_DELETE comment above. */
		outliner_cleanup_tree(soops);

		DAG_relations_tag_update(bmain);
		str = "Delete Object Hierarchy";
		WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
	}
	else if (event == OL_OP_LOCALIZED) {    /* disabled, see above enum (ton) */
		outliner_do_object_operation(C, scene, soops, &soops->tree, id_local_cb);
		str = "Localized Objects";
	}
	else if (event == OL_OP_TOGVIS) {
		outliner_do_object_operation(C, scene, soops, &soops->tree, object_toggle_visibility_cb);
		str = "Toggle Visibility";
		WM_event_add_notifier(C, NC_SCENE | ND_OB_VISIBLE, scene);
	}
	else if (event == OL_OP_TOGSEL) {
		outliner_do_object_operation(C, scene, soops, &soops->tree, object_toggle_selectability_cb);
		str = "Toggle Selectability";
		WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
	}
	else if (event == OL_OP_TOGREN) {
		outliner_do_object_operation(C, scene, soops, &soops->tree, object_toggle_renderability_cb);
		str = "Toggle Renderability";
		WM_event_add_notifier(C, NC_SCENE | ND_OB_RENDER, scene);
	}
	else if (event == OL_OP_RENAME) {
		outliner_do_object_operation(C, scene, soops, &soops->tree, item_rename_cb);
		str = "Rename Object";
	}
	else {
		BLI_assert(0);
		return OPERATOR_CANCELLED;
	}

	ED_undo_push(C, str);
	
	return OPERATOR_FINISHED;
}
Exemple #10
0
static int outliner_id_operation_exec(bContext *C, wmOperator *op)
{
	Scene *scene = CTX_data_scene(C);
	SpaceOops *soops = CTX_wm_space_outliner(C);
	int scenelevel = 0, objectlevel = 0, idlevel = 0, datalevel = 0;
	eOutlinerIdOpTypes event;
	
	/* check for invalid states */
	if (soops == NULL)
		return OPERATOR_CANCELLED;
	
	set_operation_types(soops, &soops->tree, &scenelevel, &objectlevel, &idlevel, &datalevel);
	
	event = RNA_enum_get(op->ptr, "type");
	
	switch (event) {
		case OUTLINER_IDOP_UNLINK:
		{
			/* unlink datablock from its parent */
			switch (idlevel) {
				case ID_AC:
					outliner_do_libdata_operation(C, scene, soops, &soops->tree, unlink_action_cb);
					
					WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, NULL);
					ED_undo_push(C, "Unlink action");
					break;
				case ID_MA:
					outliner_do_libdata_operation(C, scene, soops, &soops->tree, unlink_material_cb);
					
					WM_event_add_notifier(C, NC_OBJECT | ND_OB_SHADING, NULL);
					ED_undo_push(C, "Unlink material");
					break;
				case ID_TE:
					outliner_do_libdata_operation(C, scene, soops, &soops->tree, unlink_texture_cb);
					
					WM_event_add_notifier(C, NC_OBJECT | ND_OB_SHADING, NULL);
					ED_undo_push(C, "Unlink texture");
					break;
				case ID_WO:
					outliner_do_libdata_operation(C, scene, soops, &soops->tree, unlink_world_cb);
					
					WM_event_add_notifier(C, NC_SCENE | ND_WORLD, NULL);
					ED_undo_push(C, "Unlink world");
					break;
				default:
					BKE_report(op->reports, RPT_WARNING, "Not yet implemented");
					break;
			}
			break;
		}
		case OUTLINER_IDOP_LOCAL:
		{
			/* make local */
			outliner_do_libdata_operation(C, scene, soops, &soops->tree, id_local_cb);
			ED_undo_push(C, "Localized Data");
			break;
		}
		case OUTLINER_IDOP_SINGLE:
		{
			/* make single user */
			switch (idlevel) {
				case ID_AC:
					outliner_do_libdata_operation(C, scene, soops, &soops->tree, singleuser_action_cb);
					
					WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, NULL);
					ED_undo_push(C, "Single-User Action");
					break;
					
				case ID_WO:
					outliner_do_libdata_operation(C, scene, soops, &soops->tree, singleuser_world_cb);
					
					WM_event_add_notifier(C, NC_SCENE | ND_WORLD, NULL);
					ED_undo_push(C, "Single-User World");
					break;
					
				default:
					BKE_report(op->reports, RPT_WARNING, "Not yet implemented");
					break;
			}
			break;
		}
		case OUTLINER_IDOP_FAKE_ADD:
		{
			/* set fake user */
			outliner_do_libdata_operation(C, scene, soops, &soops->tree, id_fake_user_set_cb);
			
			WM_event_add_notifier(C, NC_ID | NA_EDITED, NULL);
			ED_undo_push(C, "Add Fake User");
			break;
		}
		case OUTLINER_IDOP_FAKE_CLEAR:
		{
			/* clear fake user */
			outliner_do_libdata_operation(C, scene, soops, &soops->tree, id_fake_user_clear_cb);
			
			WM_event_add_notifier(C, NC_ID | NA_EDITED, NULL);
			ED_undo_push(C, "Clear Fake User");
			break;
		}
		case OUTLINER_IDOP_RENAME:
		{
			/* rename */
			outliner_do_libdata_operation(C, scene, soops, &soops->tree, item_rename_cb);
			
			WM_event_add_notifier(C, NC_ID | NA_EDITED, NULL);
			ED_undo_push(C, "Rename");
			break;
		}
		case OUTLINER_IDOP_SELECT_LINKED:
			outliner_do_libdata_operation(C, scene, soops, &soops->tree, id_select_linked_cb);
			ED_undo_push(C, "Select");
			break;
			
		default:
			// invalid - unhandled
			break;
	}
	
	/* wrong notifier still... */
	WM_event_add_notifier(C, NC_ID | NA_EDITED, NULL);
	
	// XXX: this is just so that outliner is always up to date 
	WM_event_add_notifier(C, NC_SPACE | ND_SPACE_OUTLINER, NULL);
	
	return OPERATOR_FINISHED;
}
Exemple #11
0
static int outliner_animdata_operation_exec(bContext *C, wmOperator *op)
{
	SpaceOops *soops = CTX_wm_space_outliner(C);
	int scenelevel = 0, objectlevel = 0, idlevel = 0, datalevel = 0;
	eOutliner_AnimDataOps event;
	short updateDeps = 0;
	
	/* check for invalid states */
	if (soops == NULL)
		return OPERATOR_CANCELLED;
	
	event = RNA_enum_get(op->ptr, "type");
	set_operation_types(soops, &soops->tree, &scenelevel, &objectlevel, &idlevel, &datalevel);
	
	if (datalevel != TSE_ANIM_DATA)
		return OPERATOR_CANCELLED;
	
	/* perform the core operation */
	switch (event) {
		case OUTLINER_ANIMOP_CLEAR_ADT:
			/* Remove Animation Data - this may remove the active action, in some cases... */
			outliner_do_data_operation(soops, datalevel, event, &soops->tree, clear_animdata_cb, NULL);
			
			WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, NULL);
			ED_undo_push(C, "Clear Animation Data");
			break;
		
		case OUTLINER_ANIMOP_SET_ACT:
			/* delegate once again... */
			WM_operator_name_call(C, "OUTLINER_OT_action_set", WM_OP_INVOKE_REGION_WIN, NULL);
			break;
		
		case OUTLINER_ANIMOP_CLEAR_ACT:
			/* clear active action - using standard rules */
			outliner_do_data_operation(soops, datalevel, event, &soops->tree, unlinkact_animdata_cb, NULL);
			
			WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, NULL);
			ED_undo_push(C, "Unlink action");
			break;
			
		case OUTLINER_ANIMOP_REFRESH_DRV:
			outliner_do_data_operation(soops, datalevel, event, &soops->tree, refreshdrivers_animdata_cb, NULL);
			
			WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN, NULL);
			//ED_undo_push(C, "Refresh Drivers"); /* no undo needed - shouldn't have any impact? */
			updateDeps = 1;
			break;
			
		case OUTLINER_ANIMOP_CLEAR_DRV:
			outliner_do_data_operation(soops, datalevel, event, &soops->tree, cleardrivers_animdata_cb, NULL);
			
			WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN, NULL);
			ED_undo_push(C, "Clear Drivers");
			updateDeps = 1;
			break;
			
		default: // invalid
			break;
	}
	
	/* update dependencies */
	if (updateDeps) {
		/* rebuild depsgraph for the new deps */
		DAG_relations_tag_update(CTX_data_main(C));
	}
	
	return OPERATOR_FINISHED;
}
Exemple #12
0
static int update_reports_display_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
	wmWindowManager *wm = CTX_wm_manager(C);
	ReportList *reports = CTX_wm_reports(C);
	Report *report;
	ReportTimerInfo *rti;
	float progress = 0.0, color_progress = 0.0;
	float neutral_col[3] = {0.35, 0.35, 0.35};
	float neutral_gray = 0.6;
	float timeout = 0.0, color_timeout = 0.0;
	int send_note = 0;
	
	/* escape if not our timer */
	if ((reports->reporttimer == NULL) ||
	    (reports->reporttimer != event->customdata) ||
	    ((report = BKE_reports_last_displayable(reports)) == NULL) /* may have been deleted */
	    )
	{
		return OPERATOR_PASS_THROUGH;
	}

	rti = (ReportTimerInfo *)reports->reporttimer->customdata;
	
	timeout = (report->type & RPT_ERROR_ALL) ? ERROR_TIMEOUT : INFO_TIMEOUT;
	color_timeout = (report->type & RPT_ERROR_ALL) ? ERROR_COLOR_TIMEOUT : INFO_COLOR_TIMEOUT;
	
	/* clear the report display after timeout */
	if ((float)reports->reporttimer->duration > timeout) {
		WM_event_remove_timer(wm, NULL, reports->reporttimer);
		reports->reporttimer = NULL;
		
		WM_event_add_notifier(C, NC_SPACE | ND_SPACE_INFO, NULL);
		
		return (OPERATOR_FINISHED | OPERATOR_PASS_THROUGH);
	}

	if (rti->widthfac == 0.0f) {
		/* initialize colors based on report type */
		if (report->type & RPT_ERROR_ALL) {
			rti->col[0] = 1.0;
			rti->col[1] = 0.2;
			rti->col[2] = 0.0;
		}
		else if (report->type & RPT_WARNING_ALL) {
			rti->col[0] = 1.0;
			rti->col[1] = 1.0;
			rti->col[2] = 0.0;
		}
		else if (report->type & RPT_INFO_ALL) {
			rti->col[0] = 0.3;
			rti->col[1] = 0.45;
			rti->col[2] = 0.7;
		}
		rti->grayscale = 0.75;
		rti->widthfac = 1.0;
	}
	
	progress = (float)reports->reporttimer->duration / timeout;
	color_progress = (float)reports->reporttimer->duration / color_timeout;
	
	/* save us from too many draws */
	if (color_progress <= 1.0f) {
		send_note = 1;
		
		/* fade colors out sharply according to progress through fade-out duration */
		interp_v3_v3v3(rti->col, rti->col, neutral_col, color_progress);
		rti->grayscale = interpf(neutral_gray, rti->grayscale, color_progress);
	}

	/* collapse report at end of timeout */
	if (progress * timeout > timeout - COLLAPSE_TIMEOUT) {
		rti->widthfac = (progress * timeout - (timeout - COLLAPSE_TIMEOUT)) / COLLAPSE_TIMEOUT;
		rti->widthfac = 1.0f - rti->widthfac;
		send_note = 1;
	}
	
	if (send_note) {
		WM_event_add_notifier(C, NC_SPACE | ND_SPACE_INFO, NULL);
	}
	
	return (OPERATOR_FINISHED | OPERATOR_PASS_THROUGH);
}
Exemple #13
0
static int ED_object_shape_key_remove(bContext *C, Object *ob)
{
	Main *bmain= CTX_data_main(C);
	KeyBlock *kb, *rkb;
	Key *key;
	//IpoCurve *icu;

	key= ob_get_key(ob);
	if(key==NULL)
		return 0;
	
	kb= BLI_findlink(&key->block, ob->shapenr-1);

	if(kb) {
		for(rkb= key->block.first; rkb; rkb= rkb->next)
			if(rkb->relative == ob->shapenr-1)
				rkb->relative= 0;

		BLI_remlink(&key->block, kb);
		key->totkey--;
		if(key->refkey== kb) {
			key->refkey= key->block.first;

			if(key->refkey) {
				/* apply new basis key on original data */
				switch(ob->type) {
					case OB_MESH:
						key_to_mesh(key->refkey, ob->data);
						break;
					case OB_CURVE:
					case OB_SURF:
						key_to_curve(key->refkey, ob->data, BKE_curve_nurbs(ob->data));
						break;
					case OB_LATTICE:
						key_to_latt(key->refkey, ob->data);
						break;
				}
			}
		}
			
		if(kb->data) MEM_freeN(kb->data);
		MEM_freeN(kb);
		
		for(kb= key->block.first; kb; kb= kb->next)
			if(kb->adrcode>=ob->shapenr)
				kb->adrcode--;
		
#if 0 // XXX old animation system
		if(key->ipo) {
			
			for(icu= key->ipo->curve.first; icu; icu= icu->next) {
				if(icu->adrcode==ob->shapenr-1) {
					BLI_remlink(&key->ipo->curve, icu);
					free_ipo_curve(icu);
					break;
				}
			}
			for(icu= key->ipo->curve.first; icu; icu= icu->next) 
				if(icu->adrcode>=ob->shapenr)
					icu->adrcode--;
		}
#endif // XXX old animation system		
		
		if(ob->shapenr>1) ob->shapenr--;
	}
	
	if(key->totkey==0) {
		if(GS(key->from->name)==ID_ME) ((Mesh *)key->from)->key= NULL;
		else if(GS(key->from->name)==ID_CU) ((Curve *)key->from)->key= NULL;
		else if(GS(key->from->name)==ID_LT) ((Lattice *)key->from)->key= NULL;

		free_libblock_us(&(bmain->key), key);
	}
	
	DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
	WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);

	return 1;
}
Exemple #14
0
static int object_shape_key_mirror(bContext *C, Object *ob)
{
	KeyBlock *kb;
	Key *key;

	key= ob_get_key(ob);
	if(key==NULL)
		return 0;
	
	kb= BLI_findlink(&key->block, ob->shapenr-1);

	if(kb) {
		int i1, i2;
		float *fp1, *fp2;
		float tvec[3];
		char *tag_elem= MEM_callocN(sizeof(char) * kb->totelem, "shape_key_mirror");


		if(ob->type==OB_MESH) {
			Mesh *me= ob->data;
			MVert *mv;

			mesh_octree_table(ob, NULL, NULL, 's');

			for(i1=0, mv=me->mvert; i1<me->totvert; i1++, mv++) {
				i2= mesh_get_x_mirror_vert(ob, i1);
				if(i2==i1) {
					fp1= ((float *)kb->data) + i1*3;
					fp1[0] = -fp1[0];
					tag_elem[i1]= 1;
				}
				else if(i2 != -1) {
					if(tag_elem[i1]==0 && tag_elem[i2]==0) {
						fp1= ((float *)kb->data) + i1*3;
						fp2= ((float *)kb->data) + i2*3;

						copy_v3_v3(tvec,	fp1);
						copy_v3_v3(fp1,	fp2);
						copy_v3_v3(fp2,	tvec);

						/* flip x axis */
						fp1[0] = -fp1[0];
						fp2[0] = -fp2[0];
					}
					tag_elem[i1]= tag_elem[i2]= 1;
				}
			}

			mesh_octree_table(ob, NULL, NULL, 'e');
		}
		else if (ob->type == OB_LATTICE) {
			Lattice *lt= ob->data;
			int i1, i2;
			float *fp1, *fp2;
			int u, v, w;
			/* half but found up odd value */
			const int pntsu_half = (((lt->pntsu / 2) + (lt->pntsu % 2))) ;

			/* currently editmode isnt supported by mesh so
			 * ignore here for now too */

			/* if(lt->editlatt) lt= lt->editlatt->latt; */

			for(w=0; w<lt->pntsw; w++) {
				for(v=0; v<lt->pntsv; v++) {
					for(u=0; u<pntsu_half; u++) {
						int u_inv= (lt->pntsu - 1) - u;
						float tvec[3];
						if(u == u_inv) {
							i1= LT_INDEX(lt, u, v, w);
							fp1= ((float *)kb->data) + i1*3;
							fp1[0]= -fp1[0];
						}
						else {
							i1= LT_INDEX(lt, u, v, w);
							i2= LT_INDEX(lt, u_inv, v, w);

							fp1= ((float *)kb->data) + i1*3;
							fp2= ((float *)kb->data) + i2*3;

							copy_v3_v3(tvec, fp1);
							copy_v3_v3(fp1, fp2);
							copy_v3_v3(fp2, tvec);
							fp1[0]= -fp1[0];
							fp2[0]= -fp2[0];
						}
					}
				}
			}
		}

		MEM_freeN(tag_elem);
	}
	
	DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
	WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);

	return 1;
}
Exemple #15
0
static int snap_sel_to_curs_exec(bContext *C, wmOperator *op)
{
	Scene *scene = CTX_data_scene(C);
	Object *obedit = CTX_data_edit_object(C);
	Object *obact = CTX_data_active_object(C);
	View3D *v3d = CTX_wm_view3d(C);
	TransVertStore tvs = {NULL};
	TransVert *tv;
	float imat[3][3], bmat[3][3];
	const float *cursor_global;
	float center_global[3];
	float offset_global[3];
	int a;

	const bool use_offset = RNA_boolean_get(op->ptr, "use_offset");

	cursor_global = ED_view3d_cursor3d_get(scene, v3d);

	if (use_offset) {
		if ((v3d && v3d->around == V3D_ACTIVE) &&
		    snap_calc_active_center(C, true, center_global))
		{
			/* pass */
		}
		else {
			snap_curs_to_sel_ex(C, center_global);
		}
		sub_v3_v3v3(offset_global, cursor_global, center_global);
	}

	if (obedit) {
		float cursor_local[3];
		
		if (ED_transverts_check_obedit(obedit))
			ED_transverts_create_from_obedit(&tvs, obedit, 0);
		if (tvs.transverts_tot == 0)
			return OPERATOR_CANCELLED;

		copy_m3_m4(bmat, obedit->obmat);
		invert_m3_m3(imat, bmat);
		
		/* get the cursor in object space */
		sub_v3_v3v3(cursor_local, cursor_global, obedit->obmat[3]);
		mul_m3_v3(imat, cursor_local);

		if (use_offset) {
			float offset_local[3];

			mul_v3_m3v3(offset_local, imat, offset_global);

			tv = tvs.transverts;
			for (a = 0; a < tvs.transverts_tot; a++, tv++) {
				add_v3_v3(tv->loc, offset_local);
			}
		}
		else {
			tv = tvs.transverts;
			for (a = 0; a < tvs.transverts_tot; a++, tv++) {
				copy_v3_v3(tv->loc, cursor_local);
			}
		}
		
		ED_transverts_update_obedit(&tvs, obedit);
		ED_transverts_free(&tvs);
	}
	else if (obact && (obact->mode & OB_MODE_POSE)) {
		struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID);

		bPoseChannel *pchan;
		bArmature *arm = obact->data;
		float cursor_local[3];

		invert_m4_m4(obact->imat, obact->obmat);
		mul_v3_m4v3(cursor_local, obact->imat, cursor_global);

		for (pchan = obact->pose->chanbase.first; pchan; pchan = pchan->next) {
			if ((pchan->bone->flag & BONE_SELECTED) &&
			    (PBONE_VISIBLE(arm, pchan->bone)) &&
			    /* if the bone has a parent and is connected to the parent,
			     * don't do anything - will break chain unless we do auto-ik.
			     */
			    (pchan->bone->flag & BONE_CONNECTED) == 0)
			{
				pchan->bone->flag |= BONE_TRANSFORM;
			}
			else {
				pchan->bone->flag &= ~BONE_TRANSFORM;
			}
		}

		for (pchan = obact->pose->chanbase.first; pchan; pchan = pchan->next) {
			if ((pchan->bone->flag & BONE_TRANSFORM) &&
			    /* check that our parents not transformed (if we have one) */
			    ((pchan->bone->parent &&
			      BKE_armature_bone_flag_test_recursive(pchan->bone->parent, BONE_TRANSFORM)) == 0))
			{
				/* Get position in pchan (pose) space. */
				float cursor_pose[3];

				if (use_offset) {
					mul_v3_m4v3(cursor_pose, obact->obmat, pchan->pose_mat[3]);
					add_v3_v3(cursor_pose, offset_global);

					mul_m4_v3(obact->imat, cursor_pose);
					BKE_armature_loc_pose_to_bone(pchan, cursor_pose, cursor_pose);
				}
				else {
					BKE_armature_loc_pose_to_bone(pchan, cursor_local, cursor_pose);
				}

				/* copy new position */
				if ((pchan->protectflag & OB_LOCK_LOCX) == 0)
					pchan->loc[0] = cursor_pose[0];
				if ((pchan->protectflag & OB_LOCK_LOCY) == 0)
					pchan->loc[1] = cursor_pose[1];
				if ((pchan->protectflag & OB_LOCK_LOCZ) == 0)
					pchan->loc[2] = cursor_pose[2];

				/* auto-keyframing */
				ED_autokeyframe_pchan(C, scene, obact, pchan, ks);
			}
		}

		for (pchan = obact->pose->chanbase.first; pchan; pchan = pchan->next) {
			pchan->bone->flag &= ~BONE_TRANSFORM;
		}

		obact->pose->flag |= (POSE_LOCKED | POSE_DO_UNLOCK);

		DAG_id_tag_update(&obact->id, OB_RECALC_DATA);
	}
	else {
		struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID);
		Main *bmain = CTX_data_main(C);

		ListBase ctx_data_list;
		CollectionPointerLink *ctx_ob;
		Object *ob;

		CTX_data_selected_editable_objects(C, &ctx_data_list);

		/* reset flags */
		for (ob = bmain->object.first; ob; ob = ob->id.next) {
			ob->flag &= ~OB_DONE;
		}

		/* tag objects we're transforming */
		for (ctx_ob = ctx_data_list.first; ctx_ob; ctx_ob = ctx_ob->next) {
			ob = ctx_ob->ptr.data;
			ob->flag |= OB_DONE;
		}

		for (ctx_ob = ctx_data_list.first; ctx_ob; ctx_ob = ctx_ob->next) {
			ob = ctx_ob->ptr.data;

			if ((ob->parent && BKE_object_flag_test_recursive(ob->parent, OB_DONE)) == 0) {

				float cursor_parent[3];  /* parent-relative */

				if (use_offset) {
					add_v3_v3v3(cursor_parent, ob->obmat[3], offset_global);
				}
				else {
					copy_v3_v3(cursor_parent, cursor_global);
				}

				sub_v3_v3(cursor_parent, ob->obmat[3]);

				if (ob->parent) {
					float originmat[3][3];
					BKE_object_where_is_calc_ex(scene, NULL, ob, originmat);

					invert_m3_m3(imat, originmat);
					mul_m3_v3(imat, cursor_parent);
				}
				if ((ob->protectflag & OB_LOCK_LOCX) == 0)
					ob->loc[0] += cursor_parent[0];
				if ((ob->protectflag & OB_LOCK_LOCY) == 0)
					ob->loc[1] += cursor_parent[1];
				if ((ob->protectflag & OB_LOCK_LOCZ) == 0)
					ob->loc[2] += cursor_parent[2];

				/* auto-keyframing */
				ED_autokeyframe_object(C, scene, ob, ks);

				DAG_id_tag_update(&ob->id, OB_RECALC_OB);
			}
		}

		BLI_freelistN(&ctx_data_list);
	}

	WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
	
	return OPERATOR_FINISHED;
}
static int lattice_flip_exec(bContext *C, wmOperator *op)
{
	Object *obedit = CTX_data_edit_object(C);
	Lattice *lt;
	
	eLattice_FlipAxes axis = RNA_enum_get(op->ptr, "axis");
	int numU, numV, numW;
	int totP;
	
	float mid = 0.0f;
	short isOdd = 0;
	
	/* get lattice - we need the "edit lattice" from the lattice... confusing... */
	lt = (Lattice *)obedit->data;
	lt = lt->editlatt->latt;
	
	numU = lt->pntsu;
	numV = lt->pntsv;
	numW = lt->pntsw;
	totP = numU * numV * numW;
	
	/* First Pass: determine midpoint - used for flipping center verts if there are odd number of points on axis */
	switch (axis) {
		case LATTICE_FLIP_U:
			isOdd = numU & 1;
			break;
		case LATTICE_FLIP_V:
			isOdd = numV & 1;
			break;
		case LATTICE_FLIP_W:
			isOdd = numW & 1;
			break;
			
		default:
			printf("lattice_flip(): Unknown flipping axis (%d)\n", axis);
			return OPERATOR_CANCELLED;
	}
	
	if (isOdd) {
		BPoint *bp;
		float avgInv = 1.0f / (float)totP;
		int i;
		
		/* midpoint calculation - assuming that u/v/w are axis-aligned */
		for (i = 0, bp = lt->def; i < totP; i++, bp++) {
			mid += bp->vec[axis] * avgInv;
		}
	}
	
	/* Second Pass: swap pairs of vertices per axis, assuming they are all sorted */
	switch (axis) {
		case LATTICE_FLIP_U:
		{
			int u, v, w;
			
			/* v/w strips - front to back, top to bottom */
			for (w = 0; w < numW; w++) {
				for (v = 0; v < numV; v++) {
					/* swap coordinates of pairs of vertices on u */
					for (u = 0; u < (numU / 2); u++) {
						lattice_swap_point_pairs(lt, u, v, w, mid, axis);
					}
					
					/* flip u-coordinate of midpoint (i.e. unpaired point on u) */
					if (isOdd) {
						u = (numU / 2);
						lattice_flip_point_value(lt, u, v, w, mid, axis);
					}
				}
			}
			break;
		}
		case LATTICE_FLIP_V:
		{
			int u, v, w;
			
			/* u/w strips - front to back, left to right */
			for (w = 0; w < numW; w++) {
				for (u = 0; u < numU; u++) {
					/* swap coordinates of pairs of vertices on v */
					for (v = 0; v < (numV / 2); v++) {
						lattice_swap_point_pairs(lt, u, v, w, mid, axis);
					}
					
					/* flip v-coordinate of midpoint (i.e. unpaired point on v) */
					if (isOdd) {
						v = (numV / 2);
						lattice_flip_point_value(lt, u, v, w, mid, axis);
					}
				}
			}
			break;
		}
		case LATTICE_FLIP_W:
		{
			int u, v, w;
			
			for (v = 0; v < numV; v++) {
				for (u = 0; u < numU; u++) {
					/* swap coordinates of pairs of vertices on w */
					for (w = 0; w < (numW / 2); w++) {
						lattice_swap_point_pairs(lt, u, v, w, mid, axis);
					}
					
					/* flip w-coordinate of midpoint (i.e. unpaired point on w) */
					if (isOdd) {
						w = (numW / 2);
						lattice_flip_point_value(lt, u, v, w, mid, axis);
					}
				}
			}
			break;
		}
		default: /* shouldn't happen, but just in case */
			break;
	}
	
	/* updates */
	DAG_id_tag_update(&obedit->id, OB_RECALC_DATA);
	WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
	
	return OPERATOR_FINISHED;
}
Exemple #17
0
static int snap_sel_to_grid_exec(bContext *C, wmOperator *UNUSED(op))
{
	Object *obedit = CTX_data_edit_object(C);
	Scene *scene = CTX_data_scene(C);
	RegionView3D *rv3d = CTX_wm_region_data(C);
	TransVertStore tvs = {NULL};
	TransVert *tv;
	float gridf, imat[3][3], bmat[3][3], vec[3];
	int a;

	gridf = rv3d->gridview;

	if (obedit) {
		if (ED_transverts_check_obedit(obedit))
			ED_transverts_create_from_obedit(&tvs, obedit, 0);
		if (tvs.transverts_tot == 0)
			return OPERATOR_CANCELLED;

		copy_m3_m4(bmat, obedit->obmat);
		invert_m3_m3(imat, bmat);
		
		tv = tvs.transverts;
		for (a = 0; a < tvs.transverts_tot; a++, tv++) {
			copy_v3_v3(vec, tv->loc);
			mul_m3_v3(bmat, vec);
			add_v3_v3(vec, obedit->obmat[3]);
			vec[0] = gridf * floorf(0.5f + vec[0] / gridf);
			vec[1] = gridf * floorf(0.5f + vec[1] / gridf);
			vec[2] = gridf * floorf(0.5f + vec[2] / gridf);
			sub_v3_v3(vec, obedit->obmat[3]);
			
			mul_m3_v3(imat, vec);
			copy_v3_v3(tv->loc, vec);
		}
		
		ED_transverts_update_obedit(&tvs, obedit);
		ED_transverts_free(&tvs);
	}
	else {
		struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID);

		CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
		{
			if (ob->mode & OB_MODE_POSE) {
				bPoseChannel *pchan;
				bArmature *arm = ob->data;
				
				invert_m4_m4(ob->imat, ob->obmat);
				
				for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
					if (pchan->bone->flag & BONE_SELECTED) {
						if (pchan->bone->layer & arm->layer) {
							if ((pchan->bone->flag & BONE_CONNECTED) == 0) {
								float nLoc[3];
								
								/* get nearest grid point to snap to */
								copy_v3_v3(nLoc, pchan->pose_mat[3]);
								/* We must operate in world space! */
								mul_m4_v3(ob->obmat, nLoc);
								vec[0] = gridf * floorf(0.5f + nLoc[0] / gridf);
								vec[1] = gridf * floorf(0.5f + nLoc[1] / gridf);
								vec[2] = gridf * floorf(0.5f + nLoc[2] / gridf);
								/* Back in object space... */
								mul_m4_v3(ob->imat, vec);
								
								/* Get location of grid point in pose space. */
								BKE_armature_loc_pose_to_bone(pchan, vec, vec);
								
								/* adjust location */
								if ((pchan->protectflag & OB_LOCK_LOCX) == 0)
									pchan->loc[0] = vec[0];
								if ((pchan->protectflag & OB_LOCK_LOCY) == 0)
									pchan->loc[1] = vec[1];
								if ((pchan->protectflag & OB_LOCK_LOCZ) == 0)
									pchan->loc[2] = vec[2];

								/* auto-keyframing */
								ED_autokeyframe_pchan(C, scene, ob, pchan, ks);
							}
							/* if the bone has a parent and is connected to the parent,
							 * don't do anything - will break chain unless we do auto-ik.
							 */
						}
					}
				}
				ob->pose->flag |= (POSE_LOCKED | POSE_DO_UNLOCK);
				
				DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
			}
			else {
				vec[0] = -ob->obmat[3][0] + gridf * floorf(0.5f + ob->obmat[3][0] / gridf);
				vec[1] = -ob->obmat[3][1] + gridf * floorf(0.5f + ob->obmat[3][1] / gridf);
				vec[2] = -ob->obmat[3][2] + gridf * floorf(0.5f + ob->obmat[3][2] / gridf);
				
				if (ob->parent) {
					float originmat[3][3];
					BKE_object_where_is_calc_ex(scene, NULL, ob, originmat);
					
					invert_m3_m3(imat, originmat);
					mul_m3_v3(imat, vec);
				}
				if ((ob->protectflag & OB_LOCK_LOCX) == 0)
					ob->loc[0] += vec[0];
				if ((ob->protectflag & OB_LOCK_LOCY) == 0)
					ob->loc[1] += vec[1];
				if ((ob->protectflag & OB_LOCK_LOCZ) == 0)
					ob->loc[2] += vec[2];
				
				/* auto-keyframing */
				ED_autokeyframe_object(C, scene, ob, ks);

				DAG_id_tag_update(&ob->id, OB_RECALC_OB);
			}
		}
		CTX_DATA_END;
	}

	WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
	
	return OPERATOR_FINISHED;
}
Exemple #18
0
static int tree_element_active_texture(bContext *C, Scene *scene, SpaceOops *soops, TreeElement *te, int set)
{
	TreeElement *tep;
	TreeStoreElem /* *tselem,*/ *tselemp;
	Object *ob=OBACT;
	SpaceButs *sbuts=NULL;
	
	if(ob==NULL) return 0; // no active object
	
	/*tselem= TREESTORE(te);*/ /*UNUSED*/
	
	/* find buttons area (note, this is undefined really still, needs recode in blender) */
	/* XXX removed finding sbuts */
	
	/* where is texture linked to? */
	tep= te->parent;
	tselemp= TREESTORE(tep);
	
	if(tep->idcode==ID_WO) {
		World *wrld= (World *)tselemp->id;

		if(set) {
			if(sbuts) {
				// XXX sbuts->tabo= TAB_SHADING_TEX;	// hack from header_buttonswin.c
				// XXX sbuts->texfrom= 1;
			}
// XXX			extern_set_butspace(F6KEY, 0);	// force shading buttons texture
			wrld->texact= te->index;
		}
		else if(tselemp->id == (ID *)(scene->world)) {
			if(wrld->texact==te->index) return 1;
		}
	}
	else if(tep->idcode==ID_LA) {
		Lamp *la= (Lamp *)tselemp->id;
		if(set) {
			if(sbuts) {
				// XXX sbuts->tabo= TAB_SHADING_TEX;	// hack from header_buttonswin.c
				// XXX sbuts->texfrom= 2;
			}
// XXX			extern_set_butspace(F6KEY, 0);	// force shading buttons texture
			la->texact= te->index;
		}
		else {
			if(tselemp->id == ob->data) {
				if(la->texact==te->index) return 1;
			}
		}
	}
	else if(tep->idcode==ID_MA) {
		Material *ma= (Material *)tselemp->id;
		if(set) {
			if(sbuts) {
				//sbuts->tabo= TAB_SHADING_TEX;	// hack from header_buttonswin.c
				// XXX sbuts->texfrom= 0;
			}
// XXX			extern_set_butspace(F6KEY, 0);	// force shading buttons texture
			ma->texact= (char)te->index;
			
			/* also set active material */
			ob->actcol= tep->index+1;
		}
		else if(tep->flag & TE_ACTIVE) {	// this is active material
			if(ma->texact==te->index) return 1;
		}
	}
	
	if(set)
		WM_event_add_notifier(C, NC_TEXTURE, NULL);

	return 0;
}
Exemple #19
0
static int action_new_exec(bContext *C, wmOperator *UNUSED(op))
{
	PointerRNA ptr, idptr;
	PropertyRNA *prop;
	
	/* hook into UI */
	UI_context_active_but_prop_get_templateID(C, &ptr, &prop);
	
	if (prop) {
		bAction *action = NULL, *oldact = NULL;
		AnimData *adt = NULL;
		PointerRNA oldptr;
		
		oldptr = RNA_property_pointer_get(&ptr, prop);
		oldact = (bAction *)oldptr.id.data;
		
		/* stash the old action to prevent it from being lost */
		if (ptr.type == &RNA_AnimData) {
			adt = ptr.data;
		}
		else if (ptr.type == &RNA_SpaceDopeSheetEditor) {
			adt = ED_actedit_animdata_from_context(C);
		}
		
		/* Perform stashing operation - But only if there is an action */
		if (adt && oldact) {
			/* stash the action */
			if (BKE_nla_action_stash(adt)) {
				/* The stash operation will remove the user already
				 * (and unlink the action from the AnimData action slot).
				 * Hence, we must unset the ref to the action in the
				 * action editor too (if this is where we're being called from)
				 * first before setting the new action once it is created,
				 * or else the user gets decremented twice!
				 */
				if (ptr.type == &RNA_SpaceDopeSheetEditor) {
					SpaceAction *saction = (SpaceAction *)ptr.data;
					saction->action = NULL;
				}
			}
			else {
				//printf("WARNING: Failed to stash %s. It may already exist in the NLA stack though\n", oldact->id.name);
			}
		}
		
		/* create action */
		action = action_create_new(C, oldact);
		
		/* set this new action
		 * NOTE: we can't use actedit_change_action, as this function is also called from the NLA
		 */
		RNA_id_pointer_create(&action->id, &idptr);
		RNA_property_pointer_set(&ptr, prop, idptr);
		RNA_property_update(C, &ptr, prop);
	}
	
	/* set notifier that keyframes have changed */
	WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_ADDED, NULL);
	
	return OPERATOR_FINISHED;
}
Exemple #20
0
static int do_outliner_item_activate(bContext *C, Scene *scene, ARegion *ar, SpaceOops *soops, TreeElement *te, int extend, const float mval[2])
{
	
	if(mval[1]>te->ys && mval[1]<te->ys+UI_UNIT_Y) {
		TreeStoreElem *tselem= TREESTORE(te);
		int openclose= 0;
		
		/* open close icon */
		if((te->flag & TE_ICONROW)==0) {				// hidden icon, no open/close
			if( mval[0]>te->xs && mval[0]<te->xs+UI_UNIT_X) 
				openclose= 1;
		}
		
		if(openclose) {
			/* all below close/open? */
			if(extend) {
				tselem->flag &= ~TSE_CLOSED;
				outliner_set_flag(soops, &te->subtree, TSE_CLOSED, !outliner_has_one_flag(soops, &te->subtree, TSE_CLOSED, 1));
			}
			else {
				if(tselem->flag & TSE_CLOSED) tselem->flag &= ~TSE_CLOSED;
				else tselem->flag |= TSE_CLOSED;
				
			}
			
			return 1;
		}
		/* name and first icon */
		else if(mval[0]>te->xs+UI_UNIT_X && mval[0]<te->xend) {
			
			/* always makes active object */
			if(tselem->type!=TSE_SEQUENCE && tselem->type!=TSE_SEQ_STRIP && tselem->type!=TSE_SEQUENCE_DUP)
				tree_element_set_active_object(C, scene, soops, te, 1 + (extend!=0 && tselem->type==0));
			
			if(tselem->type==0) { // the lib blocks
				/* editmode? */
				if(te->idcode==ID_SCE) {
					if(scene!=(Scene *)tselem->id) {
						ED_screen_set_scene(C, (Scene *)tselem->id);
					}
				}
				else if(te->idcode==ID_GR) {
					Group *gr= (Group *)tselem->id;
					GroupObject *gob;
					
					if(extend) {
						int sel= BA_SELECT;
						for(gob= gr->gobject.first; gob; gob= gob->next) {
							if(gob->ob->flag & SELECT) {
								sel= BA_DESELECT;
								break;
							}
						}
						
						for(gob= gr->gobject.first; gob; gob= gob->next) {
							ED_base_object_select(object_in_scene(gob->ob, scene), sel);
						}
					}
					else {
						scene_deselect_all(scene);
						
						for(gob= gr->gobject.first; gob; gob= gob->next) {
							if((gob->ob->flag & SELECT) == 0)
								ED_base_object_select(object_in_scene(gob->ob, scene), BA_SELECT);
						}
					}
					
					WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, scene);
				}
				else if(ELEM5(te->idcode, ID_ME, ID_CU, ID_MB, ID_LT, ID_AR)) {
					WM_operator_name_call(C, "OBJECT_OT_editmode_toggle", WM_OP_INVOKE_REGION_WIN, NULL);
				} else {	// rest of types
					tree_element_active(C, scene, soops, te, 1);
				}
				
			}
			else tree_element_type_active(C, scene, soops, te, tselem, 1+(extend!=0));
			
			return 1;
		}
	}
	
	for(te= te->subtree.first; te; te= te->next) {
		if(do_outliner_item_activate(C, scene, ar, soops, te, extend, mval)) return 1;
	}
	return 0;
}
Exemple #21
0
/* custom_file can be NULL */
int wm_homefile_read(bContext *C, ReportList *reports, bool from_memory, const char *custom_file)
{
	ListBase wmbase;
	char startstr[FILE_MAX];
	char prefstr[FILE_MAX];
	int success = 0;

	/* Indicates whether user prefereneces were really load from memory.
	 *
	 * This is used for versioning code, and for this we can not rely on from_memory
	 * passed via argument. This is because there might be configuration folder
	 * exists but it might not have userpref.blend and in this case we fallback to
	 * reading home file from memory.
	 *
	 * And in this case versioning code is to be run.
	 */
	bool read_userdef_from_memory = true;

	/* options exclude eachother */
	BLI_assert((from_memory && custom_file) == 0);

	BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_PRE);

	G.relbase_valid = 0;
	if (!from_memory) {
		const char * const cfgdir = BLI_get_folder(BLENDER_USER_CONFIG, NULL);
		if (custom_file) {
			BLI_strncpy(startstr, custom_file, FILE_MAX);

			if (cfgdir) {
				BLI_make_file_string(G.main->name, prefstr, cfgdir, BLENDER_USERPREF_FILE);
			}
			else {
				prefstr[0] = '\0';
			}
		}
		else if (cfgdir) {
			BLI_make_file_string(G.main->name, startstr, cfgdir, BLENDER_STARTUP_FILE);
			BLI_make_file_string(G.main->name, prefstr, cfgdir, BLENDER_USERPREF_FILE);
		}
		else {
			startstr[0] = '\0';
			prefstr[0] = '\0';
			from_memory = 1;
		}
	}
	
	/* prevent loading no UI */
	G.fileflags &= ~G_FILE_NO_UI;
	
	/* put aside screens to match with persistent windows later */
	wm_window_match_init(C, &wmbase);
	
	if (!from_memory) {
		if (BLI_access(startstr, R_OK) == 0) {
			success = (BKE_read_file(C, startstr, NULL) != BKE_READ_FILE_FAIL);
		}
		if (U.themes.first == NULL) {
			if (G.debug & G_DEBUG)
				printf("\nNote: No (valid) '%s' found, fall back to built-in default.\n\n", startstr);
			success = 0;
		}
	}

	if (success == 0 && custom_file && reports) {
		BKE_reportf(reports, RPT_ERROR, "Could not read '%s'", custom_file);
		/*We can not return from here because wm is already reset*/
	}

	if (success == 0) {
		success = BKE_read_file_from_memory(C, datatoc_startup_blend, datatoc_startup_blend_size, NULL, true);
		if (wmbase.first == NULL) wm_clear_default_size(C);
		BLI_init_temporary_dir(U.tempdir);

#ifdef WITH_PYTHON_SECURITY
		/* use alternative setting for security nuts
		 * otherwise we'd need to patch the binary blob - startup.blend.c */
		U.flag |= USER_SCRIPT_AUTOEXEC_DISABLE;
#endif
	}
	
	/* check new prefs only after startup.blend was finished */
	if (!from_memory && BLI_exists(prefstr)) {
		int done = BKE_read_file_userdef(prefstr, NULL);
		if (done) {
			read_userdef_from_memory = false;
			printf("Read new prefs: %s\n", prefstr);
		}
	}
	
	/* prevent buggy files that had G_FILE_RELATIVE_REMAP written out by mistake. Screws up autosaves otherwise
	 * can remove this eventually, only in a 2.53 and older, now its not written */
	G.fileflags &= ~G_FILE_RELATIVE_REMAP;
	
	/* check userdef before open window, keymaps etc */
	wm_init_userdef(C, read_userdef_from_memory);
	
	/* match the read WM with current WM */
	wm_window_match_do(C, &wmbase); 
	WM_check(C); /* opens window(s), checks keymaps */

	G.main->name[0] = '\0';

	/* When loading factory settings, the reset solid OpenGL lights need to be applied. */
	if (!G.background) GPU_default_lights();
	
	/* XXX */
	G.save_over = 0;    // start with save preference untitled.blend
	G.fileflags &= ~G_FILE_AUTOPLAY;    /*  disable autoplay in startup.blend... */

//	refresh_interface_font();
	
//	undo_editmode_clear();
	BKE_reset_undo();
	BKE_write_undo(C, "original");  /* save current state */

	ED_editors_init(C);
	DAG_on_visible_update(CTX_data_main(C), TRUE);

#ifdef WITH_PYTHON
	if (CTX_py_init_get(C)) {
		/* sync addons, these may have changed from the defaults */
		BPY_string_exec(C, "__import__('addon_utils').reset_all()");

		BPY_python_reset(C);
	}
#endif

	/* important to do before NULL'ing the context */
	BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_POST);

	WM_event_add_notifier(C, NC_WM | ND_FILEREAD, NULL);

	/* in background mode the scene will stay NULL */
	if (!G.background) {
		CTX_wm_window_set(C, NULL); /* exits queues */
	}

	return TRUE;
}
/* using context, starts job */
static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
	/* new render clears all callbacks */
	Main *mainp;
	Scene *scene = CTX_data_scene(C);
	SceneRenderLayer *srl = NULL;
	Render *re;
	wmJob *wm_job;
	RenderJob *rj;
	Image *ima;
	int jobflag;
	const bool is_animation = RNA_boolean_get(op->ptr, "animation");
	const bool is_write_still = RNA_boolean_get(op->ptr, "write_still");
	const bool use_viewport = RNA_boolean_get(op->ptr, "use_viewport");
	View3D *v3d = use_viewport ? CTX_wm_view3d(C) : NULL;
	struct Object *camera_override = v3d ? V3D_CAMERA_LOCAL(v3d) : NULL;
	const char *name;
	ScrArea *sa;
	
	/* only one render job at a time */
	if (WM_jobs_test(CTX_wm_manager(C), scene, WM_JOB_TYPE_RENDER))
		return OPERATOR_CANCELLED;

	if (RE_force_single_renderlayer(scene))
		WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, NULL);

	if (!RE_is_rendering_allowed(scene, camera_override, op->reports)) {
		return OPERATOR_CANCELLED;
	}

	if (!is_animation && is_write_still && BKE_imtype_is_movie(scene->r.im_format.imtype)) {
		BKE_report(op->reports, RPT_ERROR, "Cannot write a single file with an animation format selected");
		return OPERATOR_CANCELLED;
	}
	
	/* stop all running jobs, except screen one. currently previews frustrate Render */
	WM_jobs_kill_all_except(CTX_wm_manager(C), CTX_wm_screen(C));

	/* get main */
	if (G.debug_value == 101) {
		/* thread-safety experiment, copy main from the undo buffer */
		mainp = BKE_undo_get_main(&scene);
	}
	else
		mainp = CTX_data_main(C);

	/* cancel animation playback */
	if (ED_screen_animation_playing(CTX_wm_manager(C)))
		ED_screen_animation_play(C, 0, 0);
	
	/* handle UI stuff */
	WM_cursor_wait(1);

	/* flush sculpt and editmode changes */
	ED_editors_flush_edits(C, true);

	/* cleanup sequencer caches before starting user triggered render.
	 * otherwise, invalidated cache entries can make their way into
	 * the output rendering. We can't put that into RE_BlenderFrame,
	 * since sequence rendering can call that recursively... (peter) */
	BKE_sequencer_cache_cleanup();

	// store spare
	// get view3d layer, local layer, make this nice api call to render
	// store spare

	/* ensure at least 1 area shows result */
	sa = render_view_open(C, event->x, event->y);

	jobflag = WM_JOB_EXCL_RENDER | WM_JOB_PRIORITY | WM_JOB_PROGRESS;
	
	/* custom scene and single layer re-render */
	screen_render_scene_layer_set(op, mainp, &scene, &srl);

	if (RNA_struct_property_is_set(op->ptr, "layer"))
		jobflag |= WM_JOB_SUSPEND;

	/* job custom data */
	rj = MEM_callocN(sizeof(RenderJob), "render job");
	rj->main = mainp;
	rj->scene = scene;
	rj->current_scene = rj->scene;
	rj->srl = srl;
	rj->camera_override = camera_override;
	rj->lay_override = 0;
	rj->anim = is_animation;
	rj->write_still = is_write_still && !is_animation;
	rj->iuser.scene = scene;
	rj->iuser.ok = 1;
	rj->reports = op->reports;
	rj->orig_layer = 0;
	rj->last_layer = 0;
	rj->sa = sa;

	BKE_color_managed_display_settings_copy(&rj->display_settings, &scene->display_settings);
	BKE_color_managed_view_settings_copy(&rj->view_settings, &scene->view_settings);

	if (sa) {
		SpaceImage *sima = sa->spacedata.first;
		rj->orig_layer = sima->iuser.layer;
	}

	if (v3d) {
		if (scene->lay != v3d->lay) {
			rj->lay_override = v3d->lay;
			rj->v3d_override = true;
		}
		else if (camera_override && camera_override != scene->camera)
			rj->v3d_override = true;

		if (v3d->localvd)
			rj->lay_override |= v3d->localvd->lay;
	}

	/* Lock the user interface depending on render settings. */
	if (scene->r.use_lock_interface) {
		int renderlay = rj->lay_override ? rj->lay_override : scene->lay;

		WM_set_locked_interface(CTX_wm_manager(C), true);

		/* Set flag interface need to be unlocked.
		 *
		 * This is so because we don't have copy of render settings
		 * accessible from render job and copy is needed in case
		 * of non-locked rendering, so we wouldn't try to unlock
		 * anything if option was initially unset but then was
		 * enabled during rendering.
		 */
		rj->interface_locked = true;

		/* Clean memory used by viewport? */
		clean_viewport_memory(rj->main, scene, renderlay);
	}

	/* setup job */
	if (RE_seq_render_active(scene, &scene->r)) name = "Sequence Render";
	else name = "Render";

	wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, name, jobflag, WM_JOB_TYPE_RENDER);
	WM_jobs_customdata_set(wm_job, rj, render_freejob);
	WM_jobs_timer(wm_job, 0.2, NC_SCENE | ND_RENDER_RESULT, 0);
	WM_jobs_callbacks(wm_job, render_startjob, NULL, NULL, render_endjob);

	/* get a render result image, and make sure it is empty */
	ima = BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result");
	BKE_image_signal(ima, NULL, IMA_SIGNAL_FREE);
	BKE_image_backup_render(rj->scene, ima);
	rj->image = ima;

	/* setup new render */
	re = RE_NewRender(scene->id.name);
	RE_test_break_cb(re, rj, render_breakjob);
	RE_draw_lock_cb(re, rj, render_drawlock);
	RE_display_update_cb(re, rj, image_rect_update);
	RE_current_scene_update_cb(re, rj, current_scene_update);
	RE_stats_draw_cb(re, rj, image_renderinfo_cb);
	RE_progress_cb(re, rj, render_progress_update);

	rj->re = re;
	G.is_break = false;

	/* store actual owner of job, so modal operator could check for it,
	 * the reason of this is that active scene could change when rendering
	 * several layers from compositor [#31800]
	 */
	op->customdata = scene;

	WM_jobs_start(CTX_wm_manager(C), wm_job);

	WM_cursor_wait(0);
	WM_event_add_notifier(C, NC_SCENE | ND_RENDER_RESULT, scene);

	/* we set G.is_rendering here already instead of only in the job, this ensure
	 * main loop or other scene updates are disabled in time, since they may
	 * have started before the job thread */
	G.is_rendering = true;

	/* add modal handler for ESC */
	WM_event_add_modal_handler(C, op);

	return OPERATOR_RUNNING_MODAL;
}
Exemple #23
0
static int dupli_extrude_cursor(bContext *C, wmOperator *op, wmEvent *event)
{
	ViewContext vc;
	EditVert *eve;
	float min[3], max[3];
	int done= 0;
	short use_proj;

	em_setup_viewcontext(C, &vc);

	use_proj= (vc.scene->toolsettings->snap_flag & SCE_SNAP) &&	(vc.scene->toolsettings->snap_mode==SCE_SNAP_MODE_FACE);
	
	invert_m4_m4(vc.obedit->imat, vc.obedit->obmat); 
	
	INIT_MINMAX(min, max);
	
	for(eve= vc.em->verts.first; eve; eve= eve->next) {
		if(eve->f & SELECT) {
			DO_MINMAX(eve->co, min, max);
			done= 1;
		}
	}

	/* call extrude? */
	if(done) {
		const short rot_src= RNA_boolean_get(op->ptr, "rotate_source");
		EditEdge *eed;
		float vec[3], cent[3], mat[3][3];
		float nor[3]= {0.0, 0.0, 0.0};
		
		/* 2D normal calc */
		float mval_f[2];

		mval_f[0]= (float)event->mval[0];
		mval_f[1]= (float)event->mval[1];

		done= 0;

		/* calculate the normal for selected edges */
		for(eed= vc.em->edges.first; eed; eed= eed->next) {
			if(eed->f & SELECT) {
				float co1[3], co2[3];
				mul_v3_m4v3(co1, vc.obedit->obmat, eed->v1->co);
				mul_v3_m4v3(co2, vc.obedit->obmat, eed->v2->co);
				project_float_noclip(vc.ar, co1, co1);
				project_float_noclip(vc.ar, co2, co2);
				
				/* 2D rotate by 90d while adding.
				 *  (x, y) = (y, -x)
				 *
				 * accumulate the screenspace normal in 2D,
				 * with screenspace edge length weighting the result. */
				if(line_point_side_v2(co1, co2, mval_f) >= 0.0f) {
					nor[0] +=  (co1[1] - co2[1]);
					nor[1] += -(co1[0] - co2[0]);
				}
				else {
					nor[0] +=  (co2[1] - co1[1]);
					nor[1] += -(co2[0] - co1[0]);
				}
				done= 1;
			}
		}

		if(done) {
			float view_vec[3], cross[3];

			/* convert the 2D nomal into 3D */
			mul_mat3_m4_v3(vc.rv3d->viewinv, nor); /* worldspace */
			mul_mat3_m4_v3(vc.obedit->imat, nor); /* local space */
			
			/* correct the normal to be aligned on the view plane */
			copy_v3_v3(view_vec, vc.rv3d->viewinv[2]);
			mul_mat3_m4_v3(vc.obedit->imat, view_vec);
			cross_v3_v3v3(cross, nor, view_vec);
			cross_v3_v3v3(nor, view_vec, cross);
			normalize_v3(nor);
		}
		
		/* center */
		mid_v3_v3v3(cent, min, max);
		copy_v3_v3(min, cent);
		
		mul_m4_v3(vc.obedit->obmat, min);	// view space
		view3d_get_view_aligned_coordinate(&vc, min, event->mval, TRUE);
		mul_m4_v3(vc.obedit->imat, min); // back in object space
		
		sub_v3_v3(min, cent);
		
		/* calculate rotation */
		unit_m3(mat);
		if(done) {
			float dot;
			
			copy_v3_v3(vec, min);
			normalize_v3(vec);
			dot= dot_v3v3(vec, nor);

			if( fabs(dot)<0.999) {
				float cross[3], si, q1[4];
				
				cross_v3_v3v3(cross, nor, vec);
				normalize_v3(cross);
				dot= 0.5f*saacos(dot);
				
				/* halve the rotation if its applied twice */
				if(rot_src) dot *= 0.5f;
				
				si= (float)sin(dot);
				q1[0]= (float)cos(dot);
				q1[1]= cross[0]*si;
				q1[2]= cross[1]*si;
				q1[3]= cross[2]*si;				
				quat_to_mat3( mat,q1);
			}
		}
		
		if(rot_src) {
			rotateflag(vc.em, SELECT, cent, mat);
			/* also project the source, for retopo workflow */
			if(use_proj)
				EM_project_snap_verts(C, vc.ar, vc.obedit, vc.em);
		}
		
		extrudeflag(vc.obedit, vc.em, SELECT, nor, 0);
		rotateflag(vc.em, SELECT, cent, mat);
		translateflag(vc.em, SELECT, min);
		
		recalc_editnormals(vc.em);
	}
	else if(vc.em->selectmode & SCE_SELECT_VERTEX) {

		float imat[4][4];
		const float *curs= give_cursor(vc.scene, vc.v3d);
		
		copy_v3_v3(min, curs);
		view3d_get_view_aligned_coordinate(&vc, min, event->mval, TRUE);

		eve= addvertlist(vc.em, 0, NULL);

		invert_m4_m4(imat, vc.obedit->obmat);
		mul_v3_m4v3(eve->co, imat, min);
		
		eve->f= SELECT;
	}

	if(use_proj)
		EM_project_snap_verts(C, vc.ar, vc.obedit, vc.em);

	WM_event_add_notifier(C, NC_GEOM|ND_DATA, vc.obedit->data); 
	DAG_id_tag_update(vc.obedit->data, 0);
	
	return OPERATOR_FINISHED;
}
Exemple #24
0
static void rna_NlaStrip_remove(NlaTrack *track, bContext *C, ReportList *reports, NlaStrip *strip)
{
	free_nlastrip(&track->strips, strip);

	WM_event_add_notifier(C, NC_ANIMATION|ND_NLA|NA_REMOVED, NULL);
}
Exemple #25
0
static int select_exec(bContext *C, wmOperator *op)
{
	Mask *mask = CTX_data_edit_mask(C);
	MaskLayer *masklay;
	MaskSpline *spline;
	MaskSplinePoint *point = NULL;
	float co[2];
	bool extend = RNA_boolean_get(op->ptr, "extend");
	bool deselect = RNA_boolean_get(op->ptr, "deselect");
	bool toggle = RNA_boolean_get(op->ptr, "toggle");
	eMaskWhichHandle which_handle;
	const float threshold = 19;

	RNA_float_get_array(op->ptr, "location", co);

	point = ED_mask_point_find_nearest(C, mask, co, threshold, &masklay, &spline, &which_handle, NULL);

	if (extend == false && deselect == false && toggle == false)
		ED_mask_select_toggle_all(mask, SEL_DESELECT);

	if (point) {
		if (which_handle != MASK_WHICH_HANDLE_NONE) {
			if (extend) {
				masklay->act_spline = spline;
				masklay->act_point = point;

				BKE_mask_point_select_set_handle(point, which_handle, true);
			}
			else if (deselect) {
				BKE_mask_point_select_set_handle(point, which_handle, false);
			}
			else {
				masklay->act_spline = spline;
				masklay->act_point = point;

				if (!MASKPOINT_ISSEL_HANDLE(point, which_handle)) {
					BKE_mask_point_select_set_handle(point, which_handle, true);
				}
				else if (toggle) {
					BKE_mask_point_select_set_handle(point, which_handle, false);
				}
			}
		}
		else {
			if (extend) {
				masklay->act_spline = spline;
				masklay->act_point = point;

				BKE_mask_point_select_set(point, true);
			}
			else if (deselect) {
				BKE_mask_point_select_set(point, false);
			}
			else {
				masklay->act_spline = spline;
				masklay->act_point = point;

				if (!MASKPOINT_ISSEL_ANY(point)) {
					BKE_mask_point_select_set(point, true);
				}
				else if (toggle) {
					BKE_mask_point_select_set(point, false);
				}
			}
		}

		masklay->act_spline = spline;
		masklay->act_point = point;

		ED_mask_select_flush_all(mask);

		WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);

		return OPERATOR_FINISHED;
	}
	else {
		MaskSplinePointUW *uw;

		if (ED_mask_feather_find_nearest(C, mask, co, threshold, &masklay, &spline, &point, &uw, NULL)) {

			if (extend) {
				masklay->act_spline = spline;
				masklay->act_point = point;

				if (uw) uw->flag |= SELECT;
			}
			else if (deselect) {
				if (uw) uw->flag &= ~SELECT;
			}
			else {
				masklay->act_spline = spline;
				masklay->act_point = point;

				if (uw) {
					if (!(uw->flag & SELECT)) {
						uw->flag |= SELECT;
					}
					else if (toggle) {
						uw->flag &= ~SELECT;
					}
				}
			}

			ED_mask_select_flush_all(mask);

			WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);

			return OPERATOR_FINISHED;
		}
	}

	return OPERATOR_PASS_THROUGH;
}
Exemple #26
0
/* set the current pose as the restpose */
static int apply_armature_pose2bones_exec(bContext *C, wmOperator *op)
{
	Scene *scene = CTX_data_scene(C);
	Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C)); // must be active object, not edit-object
	bArmature *arm = BKE_armature_from_object(ob);
	bPose *pose;
	bPoseChannel *pchan;
	EditBone *curbone;
	
	/* don't check if editmode (should be done by caller) */
	if (ob->type != OB_ARMATURE)
		return OPERATOR_CANCELLED;
	if (BKE_object_obdata_is_libdata(ob)) {
		BKE_report(op->reports, RPT_ERROR, "Cannot apply pose to lib-linked armature"); /* error_libdata(); */
		return OPERATOR_CANCELLED;
	}

	/* helpful warnings... */
	/* TODO: add warnings to be careful about actions, applying deforms first, etc. */
	if (ob->adt && ob->adt->action)
		BKE_report(op->reports, RPT_WARNING,
		           "Actions on this armature will be destroyed by this new rest pose as the "
		           "transforms stored are relative to the old rest pose");

	/* Get editbones of active armature to alter */
	ED_armature_to_edit(arm);
	
	/* get pose of active object and move it out of posemode */
	pose = ob->pose;
	
	for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
		curbone = ED_armature_bone_find_name(arm->edbo, pchan->name);
		
		/* simply copy the head/tail values from pchan over to curbone */
		copy_v3_v3(curbone->head, pchan->pose_head);
		copy_v3_v3(curbone->tail, pchan->pose_tail);
		
		/* fix roll:
		 *	1. find auto-calculated roll value for this bone now
		 *	2. remove this from the 'visual' y-rotation
		 */
		{
			float premat[3][3], imat[3][3], pmat[3][3], tmat[3][3];
			float delta[3], eul[3];
			
			/* obtain new auto y-rotation */
			sub_v3_v3v3(delta, curbone->tail, curbone->head);
			vec_roll_to_mat3(delta, 0.0f, premat);
			invert_m3_m3(imat, premat);
			
			/* get pchan 'visual' matrix */
			copy_m3_m4(pmat, pchan->pose_mat);
			
			/* remove auto from visual and get euler rotation */
			mul_m3_m3m3(tmat, imat, pmat);
			mat3_to_eul(eul, tmat);
			
			/* just use this euler-y as new roll value */
			curbone->roll = eul[1];
		}
		
		/* clear transform values for pchan */
		zero_v3(pchan->loc);
		zero_v3(pchan->eul);
		unit_qt(pchan->quat);
		unit_axis_angle(pchan->rotAxis, &pchan->rotAngle);
		pchan->size[0] = pchan->size[1] = pchan->size[2] = 1.0f;
		
		/* set anim lock */
		curbone->flag |= BONE_UNKEYED;
	}
	
	/* convert editbones back to bones, and then free the edit-data */
	ED_armature_from_edit(arm);
	ED_armature_edit_free(arm);
	
	/* flush positions of posebones */
	BKE_pose_where_is(scene, ob);
	
	/* fix parenting of objects which are bone-parented */
	applyarmature_fix_boneparents(scene, ob);
	
	/* note, notifier might evolve */
	WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
	
	return OPERATOR_FINISHED;
}
Exemple #27
0
static int circle_select_exec(bContext *C, wmOperator *op)
{
	ScrArea *sa = CTX_wm_area(C);
	ARegion *ar = CTX_wm_region(C);

	Mask *mask = CTX_data_edit_mask(C);
	MaskLayer *masklay;
	int i;

	float zoomx, zoomy, offset[2], ellipse[2];
	int width, height;
	bool changed = false;

	/* get operator properties */
	const int x = RNA_int_get(op->ptr, "x");
	const int y = RNA_int_get(op->ptr, "y");
	const int radius = RNA_int_get(op->ptr, "radius");

	const bool select = !RNA_boolean_get(op->ptr, "deselect");

	/* compute ellipse and position in unified coordinates */
	ED_mask_get_size(sa, &width, &height);
	ED_mask_zoom(sa, ar, &zoomx, &zoomy);
	width = height = max_ii(width, height);

	ellipse[0] = width * zoomx / radius;
	ellipse[1] = height * zoomy / radius;

	ED_mask_point_pos(sa, ar, x, y, &offset[0], &offset[1]);

	/* do actual selection */
	for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
		MaskSpline *spline;

		if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
			continue;
		}

		for (spline = masklay->splines.first; spline; spline = spline->next) {
			MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);

			for (i = 0; i < spline->tot_point; i++) {
				MaskSplinePoint *point = &spline->points[i];
				MaskSplinePoint *point_deform = &points_array[i];

				if (mask_spline_point_inside_ellipse(&point_deform->bezt, offset, ellipse)) {
					BKE_mask_point_select_set(point, select);
					BKE_mask_point_select_set_handle(point, MASK_WHICH_HANDLE_BOTH, select);

					changed = true;
				}
			}
		}
	}

	if (changed) {
		ED_mask_select_flush_all(mask);

		WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);

		return OPERATOR_FINISHED;
	}

	return OPERATOR_CANCELLED;
}
Exemple #28
0
void SkinInfo::link_armature(bContext *C, Object *ob, std::map<COLLADAFW::UniqueId, COLLADAFW::Node*>& joint_by_uid,
				   TransformReader *tm)
{
	Main *bmain = CTX_data_main(C);
	Scene *scene = CTX_data_scene(C);

	ModifierData *md = ED_object_modifier_add(NULL, bmain, scene, ob, NULL, eModifierType_Armature);
	((ArmatureModifierData *)md)->object = ob_arm;

	copy_m4_m4(ob->obmat, bind_shape_matrix);
	object_apply_mat4(ob, ob->obmat, 0, 0);
#if 1
	bc_set_parent(ob, ob_arm, C);
#else
	Object workob;
	ob->parent = ob_arm;
	ob->partype = PAROBJECT;

	what_does_parent(scene, ob, &workob);
	invert_m4_m4(ob->parentinv, workob.obmat);

	ob->recalc |= OB_RECALC_OB|OB_RECALC_DATA;

	DAG_scene_sort(bmain, scene);
	DAG_ids_flush_update(bmain, 0);
	WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
#endif

	((bArmature*)ob_arm->data)->deformflag = ARM_DEF_VGROUP;

	// create all vertex groups
	std::vector<JointData>::iterator it;
	int joint_index;
	for (it = joint_data.begin(), joint_index = 0; it != joint_data.end(); it++, joint_index++) {
		const char *name = "Group";

		// skip joints that have invalid UID
		if ((*it).joint_uid == COLLADAFW::UniqueId::INVALID) continue;
		
		// name group by joint node name
		
		if (joint_by_uid.find((*it).joint_uid) != joint_by_uid.end()) {
			name = bc_get_joint_name(joint_by_uid[(*it).joint_uid]);
		}

		ED_vgroup_add_name(ob, (char*)name);
	}

	// <vcount> - number of joints per vertex - joints_per_vertex
	// <v> - [[bone index, weight index] * joints per vertex] * vertices - weight indices
	// ^ bone index can be -1 meaning weight toward bind shape, how to express this in Blender?

	// for each vertex in weight indices
	//	for each bone index in vertex
	//		add vertex to group at group index
	//		treat group index -1 specially

	// get def group by index with BLI_findlink

	for (unsigned int vertex = 0, weight = 0; vertex < joints_per_vertex.getCount(); vertex++) {

		unsigned int limit = weight + joints_per_vertex[vertex];
		for ( ; weight < limit; weight++) {
			int joint = joint_indices[weight], joint_weight = weight_indices[weight];

			// -1 means "weight towards the bind shape", we just don't assign it to any group
			if (joint != -1) {
				bDeformGroup *def = (bDeformGroup*)BLI_findlink(&ob->defbase, joint);

				ED_vgroup_vert_add(ob, def, vertex, weights[joint_weight], WEIGHT_REPLACE);
			}
		}
	}
}
Exemple #29
0
static int apply_objects_internal(bContext *C, ReportList *reports, bool apply_loc, bool apply_rot, bool apply_scale)
{
	Main *bmain = CTX_data_main(C);
	Scene *scene = CTX_data_scene(C);
	float rsmat[3][3], obmat[3][3], iobmat[3][3], mat[4][4], scale;
	bool changed = true;
	
	/* first check if we can execute */
	CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
	{
		if (ELEM(ob->type, OB_MESH, OB_ARMATURE, OB_LATTICE, OB_MBALL, OB_CURVE, OB_SURF)) {
			ID *obdata = ob->data;
			if (ID_REAL_USERS(obdata) > 1) {
				BKE_reportf(reports, RPT_ERROR,
				            "Cannot apply to a multi user: Object \"%s\", %s \"%s\", aborting",
				            ob->id.name + 2, BKE_idcode_to_name(GS(obdata->name)), obdata->name + 2);
				changed = false;
			}

			if (obdata->lib) {
				BKE_reportf(reports, RPT_ERROR,
				            "Cannot apply to library data: Object \"%s\", %s \"%s\", aborting",
				            ob->id.name + 2, BKE_idcode_to_name(GS(obdata->name)), obdata->name + 2);
				changed = false;
			}
		}

		if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
			ID *obdata = ob->data;
			Curve *cu;

			cu = ob->data;

			if (((ob->type == OB_CURVE) && !(cu->flag & CU_3D)) && (apply_rot || apply_loc)) {
				BKE_reportf(reports, RPT_ERROR,
				            "Rotation/Location can't apply to a 2D curve: Object \"%s\", %s \"%s\", aborting",
				            ob->id.name + 2, BKE_idcode_to_name(GS(obdata->name)), obdata->name + 2);
				changed = false;
			}
			if (cu->key) {
				BKE_reportf(reports, RPT_ERROR,
				            "Can't apply to a curve with shape-keys: Object \"%s\", %s \"%s\", aborting",
				            ob->id.name + 2, BKE_idcode_to_name(GS(obdata->name)), obdata->name + 2);
				changed = false;
			}
		}
	}
	CTX_DATA_END;
	
	if (!changed)
		return OPERATOR_CANCELLED;

	changed = false;

	/* now execute */
	CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
	{

		/* calculate rotation/scale matrix */
		if (apply_scale && apply_rot)
			BKE_object_to_mat3(ob, rsmat);
		else if (apply_scale)
			BKE_object_scale_to_mat3(ob, rsmat);
		else if (apply_rot) {
			float tmat[3][3], timat[3][3];

			/* simple rotation matrix */
			BKE_object_rot_to_mat3(ob, rsmat, true);

			/* correct for scale, note mul_m3_m3m3 has swapped args! */
			BKE_object_scale_to_mat3(ob, tmat);
			invert_m3_m3(timat, tmat);
			mul_m3_m3m3(rsmat, timat, rsmat);
			mul_m3_m3m3(rsmat, rsmat, tmat);
		}
		else
			unit_m3(rsmat);

		copy_m4_m3(mat, rsmat);

		/* calculate translation */
		if (apply_loc) {
			copy_v3_v3(mat[3], ob->loc);

			if (!(apply_scale && apply_rot)) {
				float tmat[3][3];
				/* correct for scale and rotation that is still applied */
				BKE_object_to_mat3(ob, obmat);
				invert_m3_m3(iobmat, obmat);
				mul_m3_m3m3(tmat, rsmat, iobmat);
				mul_m3_v3(tmat, mat[3]);
			}
		}

		/* apply to object data */
		if (ob->type == OB_MESH) {
			Mesh *me = ob->data;

			if (apply_scale)
				multiresModifier_scale_disp(scene, ob);
			
			/* adjust data */
			BKE_mesh_transform(me, mat, true);
			
			/* update normals */
			BKE_mesh_calc_normals(me);
		}
		else if (ob->type == OB_ARMATURE) {
			ED_armature_apply_transform(ob, mat);
		}
		else if (ob->type == OB_LATTICE) {
			Lattice *lt = ob->data;

			BKE_lattice_transform(lt, mat, true);
		}
		else if (ob->type == OB_MBALL) {
			MetaBall *mb = ob->data;
			BKE_mball_transform(mb, mat);
		}
		else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
			Curve *cu = ob->data;
			scale = mat3_to_scale(rsmat);
			BKE_curve_transform_ex(cu, mat, true, scale);
		}
		else if (ob->type == OB_CAMERA) {
			MovieClip *clip = BKE_object_movieclip_get(scene, ob, false);

			/* applying scale on camera actually scales clip's reconstruction.
			 * of there's clip assigned to camera nothing to do actually.
			 */
			if (!clip)
				continue;

			if (apply_scale)
				BKE_tracking_reconstruction_scale(&clip->tracking, ob->size);
		}
		else if (ob->type == OB_EMPTY) {
			/* It's possible for empties too, even though they don't 
			 * really have obdata, since we can simply apply the maximum
			 * scaling to the empty's drawsize.
			 *
			 * Core Assumptions:
			 * 1) Most scaled empties have uniform scaling 
			 *    (i.e. for visibility reasons), AND/OR
			 * 2) Preserving non-uniform scaling is not that important,
			 *    and is something that many users would be willing to
			 *    sacrifice for having an easy way to do this.
			 */

			if ((apply_loc == false) &&
			    (apply_rot == false) &&
			    (apply_scale == true))
			{
				float max_scale = max_fff(fabsf(ob->size[0]), fabsf(ob->size[1]), fabsf(ob->size[2]));
				ob->empty_drawsize *= max_scale;
			}
		}
		else {
			continue;
		}

		if (apply_loc)
			zero_v3(ob->loc);
		if (apply_scale)
			ob->size[0] = ob->size[1] = ob->size[2] = 1.0f;
		if (apply_rot) {
			zero_v3(ob->rot);
			unit_qt(ob->quat);
			unit_axis_angle(ob->rotAxis, &ob->rotAngle);
		}

		BKE_object_where_is_calc(scene, ob);
		if (ob->type == OB_ARMATURE) {
			BKE_pose_where_is(scene, ob); /* needed for bone parents */
		}

		ignore_parent_tx(bmain, scene, ob);

		DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA);

		changed = true;
	}
	CTX_DATA_END;

	if (!changed) {
		BKE_report(reports, RPT_WARNING, "Objects have no data to transform");
		return OPERATOR_CANCELLED;
	}

	WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
	return OPERATOR_FINISHED;
}
Exemple #30
0
int join_mesh_shapes_exec(bContext *C, wmOperator *op)
{
    Scene *scene= CTX_data_scene(C);
    Object *ob= CTX_data_active_object(C);
    Mesh *me= (Mesh *)ob->data;
    Mesh *selme=NULL;
    DerivedMesh *dm=NULL;
    Key *key=me->key;
    KeyBlock *kb;
    int ok=0, nonequal_verts=0;

    CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
        if (base->object == ob) continue;

        if (base->object->type==OB_MESH) {
            selme = (Mesh *)base->object->data;

            if (selme->totvert==me->totvert)
                ok++;
            else
                nonequal_verts=1;
        }
    }
    CTX_DATA_END;

    if (!ok) {
        if (nonequal_verts)
            BKE_report(op->reports, RPT_WARNING, "Selected meshes must have equal numbers of vertices.");
        else
            BKE_report(op->reports, RPT_WARNING, "No additional selected meshes with equal vertex count to join.");
        return OPERATOR_CANCELLED;
    }

    if(key == NULL) {
        key= me->key= add_key((ID *)me);
        key->type= KEY_RELATIVE;

        /* first key added, so it was the basis. initialise it with the existing mesh */
        kb= add_keyblock(key, NULL);
        mesh_to_key(me, kb);
    }

    /* now ready to add new keys from selected meshes */
    CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
        if (base->object == ob) continue;

        if(base->object->type==OB_MESH) {
            selme = (Mesh *)base->object->data;

            if (selme->totvert==me->totvert) {
                dm = mesh_get_derived_deform(scene, base->object, CD_MASK_BAREMESH);

                if (!dm) continue;

                kb= add_keyblock(key, base->object->id.name+2);

                DM_to_meshkey(dm, me, kb);

                dm->release(dm);
            }
        }
    }
    CTX_DATA_END;

    WM_event_add_notifier(C, NC_SCENE|ND_OB_ACTIVE, scene);

    return OPERATOR_FINISHED;
}