Exemplo n.º 1
0
static void edbm_inset_exit(bContext *C, wmOperator *op)
{
    InsetData *opdata;
    ScrArea *sa = CTX_wm_area(C);

    opdata = op->customdata;

    if (opdata->is_modal) {
        View3D *v3d = CTX_wm_view3d(C);
        ARegion *ar = CTX_wm_region(C);
        EDBM_redo_state_free(&opdata->mesh_backup, NULL, false);
        ED_region_draw_cb_exit(ar->type, opdata->draw_handle_pixel);
        v3d->twtype = opdata->twtype;
        G.moving = 0;
    }

    if (sa) {
        ED_area_headerprint(sa, NULL);
    }
    MEM_freeN(op->customdata);
}
Exemplo n.º 2
0
static bool ED_view3d_snap_ray(bContext *C, float r_co[3],
                               const float ray_start[3], const float ray_normal[3])
{
	float dist_px = MVAL_MAX_PX_DIST;  /* snap dist */
	float r_no_dummy[3];
	float ray_dist = TRANSFORM_DIST_MAX_RAY;
	bool ret;

	Scene *scene = CTX_data_scene(C);
	View3D *v3d = CTX_wm_view3d(C);
	ARegion *ar = CTX_wm_region(C);
	struct Object *obedit = CTX_data_edit_object(C);

	/* try snap edge, then face if it fails */
	ret = snapObjectsRayEx(scene, NULL, v3d, ar, obedit, SCE_SNAP_MODE_FACE,
	                       NULL, NULL,
	                       ray_start, ray_normal, &ray_dist,
	                       NULL, &dist_px, r_co, r_no_dummy, SNAP_ALL);

	return ret;
}
Exemplo n.º 3
0
static int depthdropper_init(bContext *C, wmOperator *op)
{
	DepthDropper *ddr;
	int index_dummy;

	SpaceType *st;
	ARegionType *art;

	st = BKE_spacetype_from_id(SPACE_VIEW3D);
	art = BKE_regiontype_from_id(st, RGN_TYPE_WINDOW);

	op->customdata = ddr = MEM_callocN(sizeof(DepthDropper), "DepthDropper");

	UI_context_active_but_prop_get(C, &ddr->ptr, &ddr->prop, &index_dummy);

	/* fallback to the active camera's dof */
	if (ddr->prop == NULL) {
		RegionView3D *rv3d = CTX_wm_region_view3d(C);
		if (rv3d && rv3d->persp == RV3D_CAMOB) {
			View3D *v3d = CTX_wm_view3d(C);
			if (v3d->camera && v3d->camera->data && (((ID *)v3d->camera->data)->lib == NULL)) {
				RNA_id_pointer_create(v3d->camera->data, &ddr->ptr);
				ddr->prop = RNA_struct_find_property(&ddr->ptr, "dof_distance");
			}
		}
	}

	if ((ddr->ptr.data == NULL) ||
	    (ddr->prop == NULL) ||
	    (RNA_property_editable(&ddr->ptr, ddr->prop) == false) ||
	    (RNA_property_type(ddr->prop) != PROP_FLOAT))
	{
		return false;
	}

	ddr->art = art;
	ddr->draw_handle_pixel = ED_region_draw_cb_activate(art, depthdropper_draw_cb, ddr, REGION_DRAW_POST_PIXEL);

	return true;
}
Exemplo n.º 4
0
static bool edbm_inset_init(bContext *C, wmOperator *op, const bool is_modal)
{
	InsetData *opdata;
	Scene *scene = CTX_data_scene(C);
	Object *obedit = CTX_data_edit_object(C);
	BMEditMesh *em = BKE_editmesh_from_object(obedit);

	if (em->bm->totvertsel == 0) {
		return false;
	}

	op->customdata = opdata = MEM_mallocN(sizeof(InsetData), "inset_operator_data");

	opdata->old_thickness = 0.01;
	opdata->old_depth = 0.0;
	opdata->modify_depth = false;
	opdata->shift = false;
	opdata->shift_amount = 0.0f;
	opdata->is_modal = is_modal;
	opdata->em = em;

	initNumInput(&opdata->num_input);
	opdata->num_input.idx_max = 1; /* Two elements. */
	opdata->num_input.unit_sys = scene->unit.system;
	opdata->num_input.unit_type[0] = B_UNIT_LENGTH;
	opdata->num_input.unit_type[1] = B_UNIT_LENGTH;

	if (is_modal) {
		View3D *v3d = CTX_wm_view3d(C);
		ARegion *ar = CTX_wm_region(C);

		opdata->mesh_backup = EDBM_redo_state_store(em);
		opdata->draw_handle_pixel = ED_region_draw_cb_activate(ar->type, ED_region_draw_mouse_line_cb, opdata->mcenter, REGION_DRAW_POST_PIXEL);
		G.moving = G_TRANSFORM_EDIT;
		opdata->twtype = v3d->twtype;
		v3d->twtype = 0;
	}

	return true;
}
Exemplo n.º 5
0
/* unlike VIEW3D_OT_view_selected this is for framing a render and not
 * meant to take into account vertex/bone selection for eg. */
static int view3d_camera_to_view_selected_exec(bContext *C, wmOperator *op)
{
	Scene *scene = CTX_data_scene(C);
	View3D *v3d = CTX_wm_view3d(C);  /* can be NULL */
	Object *camera_ob = v3d ? v3d->camera : scene->camera;

	float r_co[3]; /* the new location to apply */
	float r_scale; /* only for ortho cameras */

	if (camera_ob == NULL) {
		BKE_report(op->reports, RPT_ERROR, "No active camera");
		return OPERATOR_CANCELLED;
	}

	/* this function does all the important stuff */
	if (BKE_camera_view_frame_fit_to_scene(scene, v3d, camera_ob, r_co, &r_scale)) {
		ObjectTfmProtectedChannels obtfm;
		float obmat_new[4][4];

		if ((camera_ob->type == OB_CAMERA) && (((Camera *)camera_ob->data)->type == CAM_ORTHO)) {
			((Camera *)camera_ob->data)->ortho_scale = r_scale;
		}

		copy_m4_m4(obmat_new, camera_ob->obmat);
		copy_v3_v3(obmat_new[3], r_co);

		/* only touch location */
		BKE_object_tfm_protected_backup(camera_ob, &obtfm);
		BKE_object_apply_mat4(camera_ob, obmat_new, true, true);
		BKE_object_tfm_protected_restore(camera_ob, &obtfm, OB_LOCK_SCALE | OB_LOCK_ROT4D);

		/* notifiers */
		DAG_id_tag_update(&camera_ob->id, OB_RECALC_OB);
		WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, camera_ob);
		return OPERATOR_FINISHED;
	}
	else {
		return OPERATOR_CANCELLED;
	}
}
Exemplo n.º 6
0
static bool rna_Object_visible_get(
    Object *ob, bContext *C, ReportList *reports, ViewLayer *view_layer, View3D *v3d)
{
  if (view_layer == NULL) {
    view_layer = CTX_data_view_layer(C);
  }
  if (v3d == NULL) {
    v3d = CTX_wm_view3d(C);
  }
  Base *base = BKE_view_layer_base_find(view_layer, ob);

  if (!base) {
    BKE_reportf(reports,
                RPT_ERROR,
                "Object '%s' not in View Layer '%s'!",
                ob->id.name + 2,
                view_layer->name);
    return false;
  }

  return BASE_VISIBLE(v3d, base);
}
Exemplo n.º 7
0
static int snap_curs_to_grid_exec(bContext *C, wmOperator *UNUSED(op))
{
	Scene *scene = CTX_data_scene(C);
	RegionView3D *rv3d = CTX_wm_region_data(C);
	View3D *v3d = CTX_wm_view3d(C);
	float gridf, *curs;

	if (v3d->flag3 & V3D_LOCK_CURSOR) { // bfa - lock cursor
		return OPERATOR_CANCELLED;
	}

	gridf = rv3d->gridview;
	curs = ED_view3d_cursor3d_get(scene, v3d);

	curs[0] = gridf * floorf(0.5f + curs[0] / gridf);
	curs[1] = gridf * floorf(0.5f + curs[1] / gridf);
	curs[2] = gridf * floorf(0.5f + curs[2] / gridf);
	
	WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);  /* hrm */

	return OPERATOR_FINISHED;
}
Exemplo n.º 8
0
static int create_orientation_exec(bContext *C, wmOperator *op)
{
	char name[MAX_NAME];
	const bool use = RNA_boolean_get(op->ptr, "use");
	const bool overwrite = RNA_boolean_get(op->ptr, "overwrite");
	const bool use_view = RNA_boolean_get(op->ptr, "use_view");
	View3D *v3d = CTX_wm_view3d(C);

	RNA_string_get(op->ptr, "name", name);

	if (use && !v3d) {
		BKE_report(op->reports, RPT_ERROR, "Create Orientation's 'use' parameter only valid in a 3DView context");
		return OPERATOR_CANCELLED;
	}

	BIF_createTransformOrientation(C, op->reports, name, use_view, use, overwrite);

	WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
	WM_event_add_notifier(C, NC_SCENE | NA_EDITED, CTX_data_scene(C));
	
	return OPERATOR_FINISHED;
}
Exemplo n.º 9
0
/* convert the coordinates from the given stroke point into 3d-coordinates 
 *	- assumes that the active space is the 3D-View
 */
static void gp_strokepoint_convertcoords(bContext *C, bGPDstroke *gps, bGPDspoint *pt, float p3d[3], rctf *subrect)
{
	Scene *scene = CTX_data_scene(C);
	View3D *v3d = CTX_wm_view3d(C);
	ARegion *ar = CTX_wm_region(C);
	
	if (gps->flag & GP_STROKE_3DSPACE) {
		/* directly use 3d-coordinates */
		copy_v3_v3(p3d, &pt->x);
	}
	else {
		const float *fp = give_cursor(scene, v3d);
		float mvalf[2];
		
		/* get screen coordinate */
		if (gps->flag & GP_STROKE_2DSPACE) {
			int mvali[2];
			View2D *v2d = &ar->v2d;
			UI_view2d_view_to_region(v2d, pt->x, pt->y, mvali, mvali + 1);
			VECCOPY2D(mvalf, mvali);
		}
		else {
			if (subrect) {
				mvalf[0] = (((float)pt->x / 100.0f) * BLI_rctf_size_x(subrect)) + subrect->xmin;
				mvalf[1] = (((float)pt->y / 100.0f) * BLI_rctf_size_y(subrect)) + subrect->ymin;
			}
			else {
				mvalf[0] = (float)pt->x / 100.0f * ar->winx;
				mvalf[1] = (float)pt->y / 100.0f * ar->winy;
			}
		}
		
		/* convert screen coordinate to 3d coordinates 
		 *	- method taken from editview.c - mouse_cursor() 
		 */
		ED_view3d_win_to_3d(ar, fp, mvalf, p3d);
	}
}
Exemplo n.º 10
0
/* XXX quickly ported across */
static void handle_view3d_lock(bContext *C)
{
	Main *bmain = CTX_data_main(C);
	Scene *scene = CTX_data_scene(C);
	ScrArea *sa = CTX_wm_area(C);
	View3D *v3d = CTX_wm_view3d(C);
	
	if (v3d != NULL && sa != NULL) {
		if (v3d->localvd == NULL && v3d->scenelock && sa->spacetype == SPACE_VIEW3D) {
			/* copy to scene */
			scene->lay = v3d->lay;
			scene->layact = v3d->layact;
			scene->camera = v3d->camera;

			/* not through notifier, listener don't have context
			 * and non-open screens or spaces need to be updated too */
			BKE_screen_view3d_main_sync(&bmain->screen, scene);
			
			/* notifiers for scene update */
			WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
		}
	}
}
Exemplo n.º 11
0
static int view3d_setobjectascamera_exec(bContext *C, wmOperator *UNUSED(op))
{
	View3D *v3d = CTX_wm_view3d(C);
	ARegion *ar= ED_view3d_context_region_unlock(C);
	RegionView3D *rv3d= ar->regiondata; /* no NULL check is needed, poll checks */
	Scene *scene= CTX_data_scene(C);
	Object *ob = CTX_data_active_object(C);

	if(ob) {
		Object *camera_old= (rv3d->persp == RV3D_CAMOB) ? V3D_CAMERA_SCENE(scene, v3d) : NULL;
		rv3d->persp= RV3D_CAMOB;
		v3d->camera= ob;
		if(v3d->scenelock)
			scene->camera= ob;

		if(camera_old != ob) /* unlikely but looks like a glitch when set to the same */
			smooth_view(C, v3d, ar, camera_old, v3d->camera, rv3d->ofs, rv3d->viewquat, &rv3d->dist, &v3d->lens);

		WM_event_add_notifier(C, NC_SCENE|ND_RENDER_OPTIONS|NC_OBJECT|ND_DRAW, CTX_data_scene(C));
	}
	
	return OPERATOR_FINISHED;
}
Exemplo n.º 12
0
static int object_armature_add_exec(bContext *C, wmOperator *op)
{
	Object *obedit= CTX_data_edit_object(C);
	View3D *v3d= CTX_wm_view3d(C);
	RegionView3D *rv3d= CTX_wm_region_view3d(C);
	int newob= 0;
	int enter_editmode;
	unsigned int layer;
	float loc[3], rot[3];
	
	object_add_generic_invoke_options(C, op); // XXX these props don't get set right when only exec() is called
	if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer))
		return OPERATOR_CANCELLED;
	
	if ((obedit==NULL) || (obedit->type != OB_ARMATURE)) {
		obedit= ED_object_add_type(C, OB_ARMATURE, loc, rot, TRUE, layer);
		ED_object_enter_editmode(C, 0);
		newob = 1;
	}
	else DAG_id_tag_update(&obedit->id, OB_RECALC_DATA);
	
	if(obedit==NULL) {
		BKE_report(op->reports, RPT_ERROR, "Cannot create editmode armature.");
		return OPERATOR_CANCELLED;
	}
	
	/* v3d and rv3d are allowed to be NULL */
	add_primitive_bone(CTX_data_scene(C), v3d, rv3d);

	/* userdef */
	if (newob && !enter_editmode)
		ED_object_exit_editmode(C, EM_FREEDATA);
	
	WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, obedit);
	
	return OPERATOR_FINISHED;
}
Exemplo n.º 13
0
static bool edbm_bevel_init(bContext *C, wmOperator *op, const bool is_modal)
{
	Object *obedit = CTX_data_edit_object(C);
	Scene *scene = CTX_data_scene(C);
	BMEditMesh *em = BKE_editmesh_from_object(obedit);
	BevelData *opdata;

	if (em->bm->totvertsel == 0) {
		return false;
	}

	op->customdata = opdata = MEM_mallocN(sizeof(BevelData), "beveldata_mesh_operator");

	opdata->em = em;
	opdata->is_modal = is_modal;
	opdata->shift_factor = -1.0f;

	initNumInput(&opdata->num_input);
	opdata->num_input.idx_max = 0;
	opdata->num_input.val_flag[0] |= NUM_NO_NEGATIVE;
	opdata->num_input.unit_sys = scene->unit.system;
	opdata->num_input.unit_type[0] = B_UNIT_NONE;  /* Not sure this is a factor or a unit? */

	/* avoid the cost of allocating a bm copy */
	if (is_modal) {
		View3D *v3d = CTX_wm_view3d(C);
		ARegion *ar = CTX_wm_region(C);

		opdata->mesh_backup = EDBM_redo_state_store(em);
		opdata->draw_handle_pixel = ED_region_draw_cb_activate(ar->type, ED_region_draw_mouse_line_cb, opdata->mcenter, REGION_DRAW_POST_PIXEL);
		G.moving = G_TRANSFORM_EDIT;
		opdata->twtype = v3d->twtype;
		v3d->twtype = 0;
	}

	return true;
}
Exemplo n.º 14
0
static bool initFlyInfo(bContext *C, FlyInfo *fly, wmOperator *op, const wmEvent *event)
{
	wmWindow *win = CTX_wm_window(C);
	float upvec[3]; /* tmp */
	float mat[3][3];

	fly->rv3d = CTX_wm_region_view3d(C);
	fly->v3d = CTX_wm_view3d(C);
	fly->ar = CTX_wm_region(C);
	fly->scene = CTX_data_scene(C);

#ifdef NDOF_FLY_DEBUG
	puts("\n-- fly begin --");
#endif

	/* sanity check: for rare but possible case (if lib-linking the camera fails) */
	if ((fly->rv3d->persp == RV3D_CAMOB) && (fly->v3d->camera == NULL)) {
		fly->rv3d->persp = RV3D_PERSP;
	}

	if (fly->rv3d->persp == RV3D_CAMOB && fly->v3d->camera->id.lib) {
		BKE_report(op->reports, RPT_ERROR, "Cannot fly a camera from an external library");
		return false;
	}

	if (ED_view3d_offset_lock_check(fly->v3d, fly->rv3d)) {
		BKE_report(op->reports, RPT_ERROR, "Cannot fly when the view offset is locked");
		return false;
	}

	if (fly->rv3d->persp == RV3D_CAMOB && fly->v3d->camera->constraints.first) {
		BKE_report(op->reports, RPT_ERROR, "Cannot fly an object with constraints");
		return false;
	}

	fly->state = FLY_RUNNING;
	fly->speed = 0.0f;
	fly->axis = 2;
	fly->pan_view = false;
	fly->xlock = FLY_AXISLOCK_STATE_OFF;
	fly->zlock = FLY_AXISLOCK_STATE_OFF;
	fly->xlock_momentum = 0.0f;
	fly->zlock_momentum = 0.0f;
	fly->grid = 1.0f;
	fly->use_precision = false;
	fly->use_freelook = false;

#ifdef NDOF_FLY_DRAW_TOOMUCH
	fly->redraw = 1;
#endif
	zero_v3(fly->dvec_prev);

	fly->timer = WM_event_add_timer(CTX_wm_manager(C), win, TIMER, 0.01f);

	copy_v2_v2_int(fly->mval, event->mval);
	fly->ndof = NULL;

	fly->time_lastdraw = fly->time_lastwheel = PIL_check_seconds_timer();

	fly->draw_handle_pixel = ED_region_draw_cb_activate(fly->ar->type, drawFlyPixel, fly, REGION_DRAW_POST_PIXEL);

	fly->rv3d->rflag |= RV3D_NAVIGATING; /* so we draw the corner margins */

	/* detect weather to start with Z locking */
	upvec[0] = 1.0f;
	upvec[1] = 0.0f;
	upvec[2] = 0.0f;
	copy_m3_m4(mat, fly->rv3d->viewinv);
	mul_m3_v3(mat, upvec);
	if (fabsf(upvec[2]) < 0.1f) {
		fly->zlock = FLY_AXISLOCK_STATE_IDLE;
	}
	upvec[0] = 0;
	upvec[1] = 0;
	upvec[2] = 0;

	fly->persp_backup = fly->rv3d->persp;
	fly->dist_backup = fly->rv3d->dist;

	/* check for flying ortho camera - which we cant support well
	 * we _could_ also check for an ortho camera but this is easier */
	if ((fly->rv3d->persp == RV3D_CAMOB) &&
	    (fly->rv3d->is_persp == false))
	{
		((Camera *)fly->v3d->camera->data)->type = CAM_PERSP;
		fly->is_ortho_cam = true;
	}

	if (fly->rv3d->persp == RV3D_CAMOB) {
		Object *ob_back;
		if ((U.uiflag & USER_CAM_LOCK_NO_PARENT) == 0 && (fly->root_parent = fly->v3d->camera->parent)) {
			while (fly->root_parent->parent)
				fly->root_parent = fly->root_parent->parent;
			ob_back = fly->root_parent;
		}
		else {
			ob_back = fly->v3d->camera;
		}

		/* store the original camera loc and rot */
		fly->obtfm = BKE_object_tfm_backup(ob_back);

		BKE_object_where_is_calc(fly->scene, fly->v3d->camera);
		negate_v3_v3(fly->rv3d->ofs, fly->v3d->camera->obmat[3]);

		fly->rv3d->dist = 0.0;
	}
	else {
		/* perspective or ortho */
		if (fly->rv3d->persp == RV3D_ORTHO)
			fly->rv3d->persp = RV3D_PERSP;  /* if ortho projection, make perspective */

		copy_qt_qt(fly->rot_backup, fly->rv3d->viewquat);
		copy_v3_v3(fly->ofs_backup, fly->rv3d->ofs);

		/* the dist defines a vector that is infront of the offset
		 * to rotate the view about.
		 * this is no good for fly mode because we
		 * want to rotate about the viewers center.
		 * but to correct the dist removal we must
		 * alter offset so the view doesn't jump. */

		fly->rv3d->dist = 0.0f;

		upvec[2] = fly->dist_backup; /* x and y are 0 */
		mul_m3_v3(mat, upvec);
		sub_v3_v3(fly->rv3d->ofs, upvec);
		/* Done with correcting for the dist */
	}

	/* center the mouse, probably the UI mafia are against this but without its quite annoying */
	WM_cursor_warp(win, fly->ar->winrct.xmin + fly->ar->winx / 2, fly->ar->winrct.ymin + fly->ar->winy / 2);

	return 1;
}
Exemplo n.º 15
0
static int view3d_ruler_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
	bool do_draw = false;
	int exit_code = OPERATOR_RUNNING_MODAL;
	RulerInfo *ruler_info = op->customdata;
	ScrArea *sa = ruler_info->sa;
	ARegion *ar = ruler_info->ar;
	RegionView3D *rv3d = ar->regiondata;

	/* its possible to change  spaces while running the operator [#34894] */
	if (UNLIKELY(ar != CTX_wm_region(C))) {
		exit_code = OPERATOR_FINISHED;
		goto exit;
	}

	switch (event->type) {
		case LEFTMOUSE:
			if (event->val == KM_RELEASE) {
				if (ruler_info->state == RULER_STATE_DRAG) {
					/* rubber-band angle removal */
					RulerItem *ruler_item = ruler_item_active_get(ruler_info);
					if (ruler_item && (ruler_item->co_index == 1) && (ruler_item->flag & RULERITEM_USE_ANGLE)) {
						if (!BLI_rcti_isect_pt_v(&ar->winrct, &event->x)) {
							ruler_item->flag &= ~RULERITEM_USE_ANGLE;
							do_draw = true;
						}
					}
					if (ruler_info->snap_flag & RULER_SNAP_OK) {
						ruler_info->snap_flag &= ~RULER_SNAP_OK;
						do_draw = true;
					}
					ruler_info->state = RULER_STATE_NORMAL;
				}
			}
			else {
				if (ruler_info->state == RULER_STATE_NORMAL) {

					if (event->ctrl ||
					    /* weak - but user friendly */
					    BLI_listbase_is_empty(&ruler_info->items))
					{
						View3D *v3d = CTX_wm_view3d(C);
						const bool use_depth = (v3d->drawtype >= OB_SOLID);

						/* Create new line */
						RulerItem *ruler_item_prev = ruler_item_active_get(ruler_info);
						RulerItem *ruler_item;
						/* check if we want to drag an existing point or add a new one */
						ruler_info->state = RULER_STATE_DRAG;

						ruler_item = ruler_item_add(ruler_info);
						ruler_item_active_set(ruler_info, ruler_item);

						if (use_depth) {
							/* snap the first point added, not essential but handy */
							ruler_item->co_index = 0;
							view3d_ruler_item_mousemove(C, ruler_info, event->mval, false, true);
							copy_v3_v3(ruler_info->drag_start_co, ruler_item->co[ruler_item->co_index]);
						}
						else {
							/* initial depth either previous ruler, view offset */
							if (ruler_item_prev) {
								copy_v3_v3(ruler_info->drag_start_co, ruler_item_prev->co[ruler_item_prev->co_index]);
							}
							else {
								negate_v3_v3(ruler_info->drag_start_co, rv3d->ofs);
							}

							copy_v3_v3(ruler_item->co[0], ruler_info->drag_start_co);
							view3d_ruler_item_project(ruler_info, ruler_item->co[0], event->mval);
						}

						copy_v3_v3(ruler_item->co[2], ruler_item->co[0]);
						ruler_item->co_index = 2;

						do_draw = true;
					}
					else {
						float mval_fl[2] = {UNPACK2(event->mval)};
						RulerItem *ruler_item_pick;
						int co_index;

						/* select and drag */
						if (view3d_ruler_pick(ruler_info, mval_fl, &ruler_item_pick, &co_index)) {
							if (co_index == -1) {
								if ((ruler_item_pick->flag & RULERITEM_USE_ANGLE) == 0) {
									/* Add Center Point */
									ruler_item_active_set(ruler_info, ruler_item_pick);
									ruler_item_pick->flag |= RULERITEM_USE_ANGLE;
									ruler_item_pick->co_index = 1;
									ruler_info->state = RULER_STATE_DRAG;

									/* find the factor */
									{
										float co_ss[2][2];
										float fac;

										ED_view3d_project_float_global(ar, ruler_item_pick->co[0], co_ss[0], V3D_PROJ_TEST_NOP);
										ED_view3d_project_float_global(ar, ruler_item_pick->co[2], co_ss[1], V3D_PROJ_TEST_NOP);

										fac = line_point_factor_v2(mval_fl, co_ss[0], co_ss[1]);
										CLAMP(fac, 0.0f, 1.0f);

										interp_v3_v3v3(ruler_item_pick->co[1],
										               ruler_item_pick->co[0],
										               ruler_item_pick->co[2], fac);
									}

									/* update the new location */
									view3d_ruler_item_mousemove(C, ruler_info, event->mval,
									                            event->shift != 0, event->ctrl != 0);
									do_draw = true;
								}
							}
							else {
								ruler_item_active_set(ruler_info, ruler_item_pick);
								ruler_item_pick->co_index = co_index;
								ruler_info->state = RULER_STATE_DRAG;

								/* store the initial depth */
								copy_v3_v3(ruler_info->drag_start_co, ruler_item_pick->co[ruler_item_pick->co_index]);

								do_draw = true;
							}
						}
						else {
							exit_code = OPERATOR_PASS_THROUGH;
						}

					}
				}
			}
			break;
		case CKEY:
		{
			if (event->ctrl) {
				RulerItem *ruler_item = ruler_item_active_get(ruler_info);
				if (ruler_item) {
					const int prec = 8;
					char numstr[256];
					Scene *scene = CTX_data_scene(C);
					UnitSettings *unit = &scene->unit;

					ruler_item_as_string(ruler_item, unit, numstr, sizeof(numstr), prec);
					WM_clipboard_text_set((void *) numstr, false);
				}
			}
			break;
		}
		case RIGHTCTRLKEY:
		case LEFTCTRLKEY:
		{
			WM_event_add_mousemove(C);
			break;
		}
		case MOUSEMOVE:
		{
			if (ruler_info->state == RULER_STATE_DRAG) {
				if (view3d_ruler_item_mousemove(C, ruler_info, event->mval,
				                                event->shift != 0, event->ctrl != 0))
				{
					do_draw = true;
				}
			}
			break;
		}
		case ESCKEY:
		{
			do_draw = true;
			exit_code = OPERATOR_CANCELLED;
			break;
		}
		case RETKEY:
		{
			view3d_ruler_to_gpencil(C, ruler_info);
			do_draw = true;
			exit_code = OPERATOR_FINISHED;
			break;
		}
		case DELKEY:
		{
			if (event->val == KM_PRESS) {
				if (ruler_info->state == RULER_STATE_NORMAL) {
					RulerItem *ruler_item = ruler_item_active_get(ruler_info);
					if (ruler_item) {
						RulerItem *ruler_item_other = ruler_item->prev ? ruler_item->prev : ruler_item->next;
						ruler_item_remove(ruler_info, ruler_item);
						ruler_item_active_set(ruler_info, ruler_item_other);
						do_draw = true;
					}
				}
			}
			break;
		}
		default:
			exit_code = OPERATOR_PASS_THROUGH;
			break;

	}

	if (do_draw) {
		view3d_ruler_header_update(sa);

		/* all 3d views draw rulers */
		WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL);
	}

exit:
	if (ELEM(exit_code, OPERATOR_FINISHED, OPERATOR_CANCELLED)) {
		WM_cursor_modal_restore(ruler_info->win);

		view3d_ruler_end(C, ruler_info);
		view3d_ruler_free(ruler_info);
		op->customdata = NULL;

		ED_area_headerprint(sa, NULL);
	}

	return exit_code;
}
Exemplo n.º 16
0
static bool snap_curs_to_sel_ex(bContext *C, float cursor[3])
{
	Object *obedit = CTX_data_edit_object(C);
	Scene *scene = CTX_data_scene(C);
	View3D *v3d = CTX_wm_view3d(C);
	TransVertStore tvs = {NULL};
	TransVert *tv;
	float bmat[3][3], vec[3], min[3], max[3], centroid[3];
	int count, a;

	count = 0;
	INIT_MINMAX(min, max);
	zero_v3(centroid);

	if (obedit) {

		if (ED_transverts_check_obedit(obedit))
			ED_transverts_create_from_obedit(&tvs, obedit, TM_ALL_JOINTS | TM_SKIP_HANDLES);

		if (tvs.transverts_tot == 0) {
			return false;
		}

		copy_m3_m4(bmat, obedit->obmat);
		
		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]);
			add_v3_v3(centroid, vec);
			minmax_v3v3_v3(min, max, vec);
		}
		
		if (v3d->around == V3D_AROUND_CENTER_MEAN) {
			mul_v3_fl(centroid, 1.0f / (float)tvs.transverts_tot);
			copy_v3_v3(cursor, centroid);
		}
		else {
			mid_v3_v3v3(cursor, min, max);
		}

		ED_transverts_free(&tvs);
	}
	else {
		Object *obact = CTX_data_active_object(C);
		
		if (obact && (obact->mode & OB_MODE_POSE)) {
			bArmature *arm = obact->data;
			bPoseChannel *pchan;
			for (pchan = obact->pose->chanbase.first; pchan; pchan = pchan->next) {
				if (arm->layer & pchan->bone->layer) {
					if (pchan->bone->flag & BONE_SELECTED) {
						copy_v3_v3(vec, pchan->pose_head);
						mul_m4_v3(obact->obmat, vec);
						add_v3_v3(centroid, vec);
						minmax_v3v3_v3(min, max, vec);
						count++;
					}
				}
			}
		}
		else {
			CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
			{
				copy_v3_v3(vec, ob->obmat[3]);

				/* special case for camera -- snap to bundles */
				if (ob->type == OB_CAMERA) {
					/* snap to bundles should happen only when bundles are visible */
					if (v3d->flag2 & V3D_SHOW_RECONSTRUCTION) {
						bundle_midpoint(scene, ob, vec);
					}
				}

				add_v3_v3(centroid, vec);
				minmax_v3v3_v3(min, max, vec);
				count++;
			}
			CTX_DATA_END;
		}

		if (count == 0) {
			return false;
		}

		if (v3d->around == V3D_AROUND_CENTER_MEAN) {
			mul_v3_fl(centroid, 1.0f / (float)count);
			copy_v3_v3(cursor, centroid);
		}
		else {
			mid_v3_v3v3(cursor, min, max);
		}
	}
Exemplo n.º 17
0
static int snap_selected_to_location(bContext *C, const float snap_target_global[3], const bool use_offset)
{
	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];
	float center_global[3];
	float offset_global[3];
	int a;

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

	if (obedit) {
		float snap_target_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(snap_target_local, snap_target_global, obedit->obmat[3]);
		mul_m3_v3(imat, snap_target_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, snap_target_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 snap_target_local[3];

		invert_m4_m4(obact->imat, obact->obmat);
		mul_v3_m4v3(snap_target_local, obact->imat, snap_target_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, snap_target_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, snap_target_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;
}
/* convert a given grease-pencil layer to a 3d-curve representation (using current view if appropriate) */
static void gp_layer_to_curve(bContext *C, ReportList *reports, bGPdata *gpd, bGPDlayer *gpl, const int mode,
                              const bool norm_weights, const float rad_fac, const bool link_strokes, tGpTimingData *gtd)
{
	struct Main *bmain = CTX_data_main(C);
	View3D *v3d = CTX_wm_view3d(C);  /* may be NULL */
	Scene *scene = CTX_data_scene(C);
	bGPDframe *gpf = gpencil_layer_getframe(gpl, CFRA, 0);
	bGPDstroke *gps, *prev_gps = NULL;
	Object *ob;
	Curve *cu;
	Nurb *nu = NULL;
	Base *base_orig = BASACT, *base_new = NULL;
	float minmax_weights[2] = {1.0f, 0.0f};
	
	/* camera framing */
	rctf subrect, *subrect_ptr = NULL;
	
	/* error checking */
	if (ELEM(NULL, gpd, gpl, gpf))
		return;
	
	/* only convert if there are any strokes on this layer's frame to convert */
	if (BLI_listbase_is_empty(&gpf->strokes))
		return;
	
	/* initialize camera framing */
	if (gp_camera_view_subrect(C, &subrect)) {
		subrect_ptr = &subrect;
	}
	
	/* init the curve object (remove rotation and get curve data from it)
	 *	- must clear transforms set on object, as those skew our results
	 */
	ob = BKE_object_add_only_object(bmain, OB_CURVE, gpl->info);
	cu = ob->data = BKE_curve_add(bmain, gpl->info, OB_CURVE);
	base_new = BKE_scene_base_add(scene, ob);
	
	cu->flag |= CU_3D;
	
	gtd->inittime = ((bGPDstroke *)gpf->strokes.first)->inittime;
	
	/* add points to curve */
	for (gps = gpf->strokes.first; gps; gps = gps->next) {
		const bool add_start_point = (link_strokes && !(prev_gps));
		const bool add_end_point = (link_strokes && !(gps->next));
		
		/* Detect new strokes created because of GP_STROKE_BUFFER_MAX reached, and stitch them to previous one. */
		bool stitch = false;
		if (prev_gps) {
			bGPDspoint *pt1 = &prev_gps->points[prev_gps->totpoints - 1];
			bGPDspoint *pt2 = &gps->points[0];
			
			if ((pt1->x == pt2->x) && (pt1->y == pt2->y)) {
				stitch = true;
			}
		}
		
		/* Decide whether we connect this stroke to previous one */
		if (!(stitch || link_strokes)) {
			nu = NULL;
		}
		
		switch (mode) {
			case GP_STROKECONVERT_PATH:
				gp_stroke_to_path(C, gpl, gps, cu, subrect_ptr, &nu, minmax_weights, rad_fac, stitch,
				                  add_start_point, add_end_point, gtd);
				break;
			case GP_STROKECONVERT_CURVE:
			case GP_STROKECONVERT_POLY:  /* convert after */
				gp_stroke_to_bezier(C, gpl, gps, cu, subrect_ptr, &nu, minmax_weights, rad_fac, stitch,
				                    add_start_point, add_end_point, gtd);
				break;
			default:
				BLI_assert(!"invalid mode");
				break;
		}
		prev_gps = gps;
	}
	
	/* If link_strokes, be sure first and last points have a zero weight/size! */
	if (link_strokes) {
		gp_stroke_finalize_curve_endpoints(cu);
	}
	
	/* Update curve's weights, if needed */
	if (norm_weights && ((minmax_weights[0] > 0.0f) || (minmax_weights[1] < 1.0f))) {
		gp_stroke_norm_curve_weights(cu, minmax_weights);
	}
	
	/* Create the path animation, if needed */
	gp_stroke_path_animation(C, reports, cu, gtd);
	
	if (mode == GP_STROKECONVERT_POLY) {
		for (nu = cu->nurb.first; nu; nu = nu->next) {
			BKE_nurb_type_convert(nu, CU_POLY, false);
		}
	}
	
	/* set the layer and select */
	base_new->lay  = ob->lay  = base_orig ? base_orig->lay : BKE_screen_view3d_layer_active(v3d, scene);
	base_new->flag = ob->flag = base_new->flag | SELECT;
}
Exemplo n.º 19
0
/* the ctrl-click method */
static int armature_click_extrude_exec(bContext *C, wmOperator *UNUSED(op))
{
	View3D *v3d;
	bArmature *arm;
	EditBone *ebone, *newbone, *flipbone;
	float mat[3][3], imat[3][3];
	const float *curs;
	int a, to_root = 0;
	Object *obedit;
	Scene *scene;

	scene = CTX_data_scene(C);
	v3d = CTX_wm_view3d(C);
	obedit = CTX_data_edit_object(C);
	arm = obedit->data;
	
	/* find the active or selected bone */
	for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
		if (EBONE_VISIBLE(arm, ebone)) {
			if (ebone->flag & BONE_TIPSEL || arm->act_edbone == ebone)
				break;
		}
	}
	
	if (ebone == NULL) {
		for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
			if (EBONE_VISIBLE(arm, ebone)) {
				if (ebone->flag & BONE_ROOTSEL || arm->act_edbone == ebone)
					break;
			}
		}
		if (ebone == NULL) 
			return OPERATOR_CANCELLED;
		
		to_root = 1;
	}
	
	ED_armature_deselect_all(obedit);
	
	/* we re-use code for mirror editing... */
	flipbone = NULL;
	if (arm->flag & ARM_MIRROR_EDIT)
		flipbone = ED_armature_bone_get_mirrored(arm->edbo, ebone);

	for (a = 0; a < 2; a++) {
		if (a == 1) {
			if (flipbone == NULL)
				break;
			else {
				SWAP(EditBone *, flipbone, ebone);
			}
		}
		
		newbone = ED_armature_edit_bone_add(arm, ebone->name);
		arm->act_edbone = newbone;
		
		if (to_root) {
			copy_v3_v3(newbone->head, ebone->head);
			newbone->rad_head = ebone->rad_tail;
			newbone->parent = ebone->parent;
		}
		else {
			copy_v3_v3(newbone->head, ebone->tail);
			newbone->rad_head = ebone->rad_tail;
			newbone->parent = ebone;
			newbone->flag |= BONE_CONNECTED;
		}
		
		curs = ED_view3d_cursor3d_get(scene, v3d);
		copy_v3_v3(newbone->tail, curs);
		sub_v3_v3v3(newbone->tail, newbone->tail, obedit->obmat[3]);
		
		if (a == 1)
			newbone->tail[0] = -newbone->tail[0];
		
		copy_m3_m4(mat, obedit->obmat);
		invert_m3_m3(imat, mat);
		mul_m3_v3(imat, newbone->tail);
		
		newbone->length = len_v3v3(newbone->head, newbone->tail);
		newbone->rad_tail = newbone->length * 0.05f;
		newbone->dist = newbone->length * 0.25f;
		
	}
	
	ED_armature_sync_selection(arm->edbo);

	WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
	
	return OPERATOR_FINISHED;
}
Exemplo n.º 20
0
static bool render_view3d_flag_changed(RenderEngine *engine, const bContext *C)
{
	RegionView3D *rv3d = CTX_wm_region_view3d(C);
	View3D *v3d = CTX_wm_view3d(C);
	ARegion *ar = CTX_wm_region(C);
	Scene *scene = CTX_data_scene(C);
	Render *re;
	rctf viewplane;
	rcti disprect;
	float clipsta, clipend;
	bool orth;
	int job_update_flag = 0;
	char name[32];
	
	/* ensure render engine exists */
	re = engine->re;

	if (!re) {
		sprintf(name, "View3dPreview %p", (void *)ar);
		re = engine->re = RE_GetRender(name);
		if (!re)
			re = engine->re = RE_NewRender(name);

		engine->update_flag |= RE_ENGINE_UPDATE_DATABASE;
	}

	/* check update_flag */
	if (engine->update_flag & RE_ENGINE_UPDATE_MA)
		job_update_flag |= PR_UPDATE_MATERIAL;
	
	if (engine->update_flag & RE_ENGINE_UPDATE_OTHER)
		job_update_flag |= PR_UPDATE_MATERIAL;
	
	if (engine->update_flag & RE_ENGINE_UPDATE_DATABASE) {
		job_update_flag |= PR_UPDATE_DATABASE;

		/* load editmesh */
		if (scene->obedit)
			ED_object_editmode_load(scene->obedit);
	}
	
	engine->update_flag = 0;
	
	/* check if viewport changed */
	if (engine->last_winx != ar->winx || engine->last_winy != ar->winy) {
		engine->last_winx = ar->winx;
		engine->last_winy = ar->winy;
		job_update_flag |= PR_UPDATE_RENDERSIZE;
	}

	if (compare_m4m4(engine->last_viewmat, rv3d->viewmat, 0.00001f) == 0) {
		copy_m4_m4(engine->last_viewmat, rv3d->viewmat);
		job_update_flag |= PR_UPDATE_VIEW;
	}
	
	render_view3d_get_rects(ar, v3d, rv3d, &viewplane, engine, &clipsta, &clipend, NULL, &orth);
	
	if (BLI_rctf_compare(&viewplane, &engine->last_viewplane, 0.00001f) == 0) {
		engine->last_viewplane = viewplane;
		job_update_flag |= PR_UPDATE_VIEW;
	}
	
	render_view3d_disprect(scene, ar, v3d, rv3d, &disprect);
	if (BLI_rcti_compare(&disprect, &engine->last_disprect) == 0) {
		engine->last_disprect = disprect;
		job_update_flag |= PR_UPDATE_RENDERSIZE;
	}

	/* any changes? go ahead and rerender */
	if (job_update_flag) {
		engine->job_update_flag |= job_update_flag;
		return true;
	}

	return false;
}
Exemplo n.º 21
0
/* bone adding between selected joints */
static int armature_fill_bones_exec(bContext *C, wmOperator *op)
{
	Object *obedit = CTX_data_edit_object(C);
	bArmature *arm = (obedit) ? obedit->data : NULL;
	Scene *scene = CTX_data_scene(C);
	View3D *v3d = CTX_wm_view3d(C);
	ListBase points = {NULL, NULL};
	int count;

	/* sanity checks */
	if (ELEM(NULL, obedit, arm))
		return OPERATOR_CANCELLED;

	/* loop over all bones, and only consider if visible */
	CTX_DATA_BEGIN(C, EditBone *, ebone, visible_bones)
	{
		if (!(ebone->flag & BONE_CONNECTED) && (ebone->flag & BONE_ROOTSEL))
			fill_add_joint(ebone, 0, &points);
		if (ebone->flag & BONE_TIPSEL) 
			fill_add_joint(ebone, 1, &points);
	}
	CTX_DATA_END;
	
	/* the number of joints determines how we fill:
	 *  1) between joint and cursor (joint=head, cursor=tail)
	 *  2) between the two joints (order is dependent on active-bone/hierachy)
	 *  3+) error (a smarter method involving finding chains needs to be worked out
	 */
	count = BLI_countlist(&points);
	
	if (count == 0) {
		BKE_report(op->reports, RPT_ERROR, "No joints selected");
		return OPERATOR_CANCELLED;
	}
	else if (count == 1) {
		EditBonePoint *ebp;
		float curs[3];
		
		/* Get Points - selected joint */
		ebp = (EditBonePoint *)points.first;
		
		/* Get points - cursor (tail) */
		invert_m4_m4(obedit->imat, obedit->obmat);
		mul_v3_m4v3(curs, obedit->imat, give_cursor(scene, v3d));
		
		/* Create a bone */
		/* newbone = */ add_points_bone(obedit, ebp->vec, curs);
	}
	else if (count == 2) {
		EditBonePoint *ebp, *ebp2;
		float head[3], tail[3];
		short headtail = 0;
		
		/* check that the points don't belong to the same bone */
		ebp = (EditBonePoint *)points.first;
		ebp2 = ebp->next;
		
		if ((ebp->head_owner == ebp2->tail_owner) && (ebp->head_owner != NULL)) {
			BKE_report(op->reports, RPT_ERROR, "Same bone selected...");
			BLI_freelistN(&points);
			return OPERATOR_CANCELLED;
		}
		if ((ebp->tail_owner == ebp2->head_owner) && (ebp->tail_owner != NULL)) {
			BKE_report(op->reports, RPT_ERROR, "Same bone selected...");
			BLI_freelistN(&points);
			return OPERATOR_CANCELLED;
		}
		
		/* find which one should be the 'head' */
		if ((ebp->head_owner && ebp2->head_owner) || (ebp->tail_owner && ebp2->tail_owner)) {
			/* rule: whichever one is closer to 3d-cursor */
			float curs[3];
			float vecA[3], vecB[3];
			float distA, distB;
			
			/* get cursor location */
			invert_m4_m4(obedit->imat, obedit->obmat);
			mul_v3_m4v3(curs, obedit->imat, give_cursor(scene, v3d));
			
			/* get distances */
			sub_v3_v3v3(vecA, ebp->vec, curs);
			sub_v3_v3v3(vecB, ebp2->vec, curs);
			distA = len_v3(vecA);
			distB = len_v3(vecB);
			
			/* compare distances - closer one therefore acts as direction for bone to go */
			headtail = (distA < distB) ? 2 : 1;
		}
		else if (ebp->head_owner) {
			headtail = 1;
		}
		else if (ebp2->head_owner) {
			headtail = 2;
		}
		
		/* assign head/tail combinations */
		if (headtail == 2) {
			copy_v3_v3(head, ebp->vec);
			copy_v3_v3(tail, ebp2->vec);
		}
		else if (headtail == 1) {
			copy_v3_v3(head, ebp2->vec);
			copy_v3_v3(tail, ebp->vec);
		}
		
		/* add new bone and parent it to the appropriate end */
		if (headtail) {
			EditBone *newbone = add_points_bone(obedit, head, tail);
			
			/* do parenting (will need to set connected flag too) */
			if (headtail == 2) {
				/* ebp tail or head - tail gets priority */
				if (ebp->tail_owner)
					newbone->parent = ebp->tail_owner;
				else
					newbone->parent = ebp->head_owner;
			}
			else {
				/* ebp2 tail or head - tail gets priority */
				if (ebp2->tail_owner)
					newbone->parent = ebp2->tail_owner;
				else
					newbone->parent = ebp2->head_owner;
			}
			
			newbone->flag |= BONE_CONNECTED;
		}
	}
	else {
		/* FIXME.. figure out a method for multiple bones */
		BKE_reportf(op->reports, RPT_ERROR, "Too many points selected: %d", count);
		BLI_freelistN(&points);
		return OPERATOR_CANCELLED;
	}
	
	/* updates */
	WM_event_add_notifier(C, NC_OBJECT | ND_POSE, obedit);
	
	/* free points */
	BLI_freelistN(&points);
	
	return OPERATOR_FINISHED;
}
Exemplo n.º 22
0
static int armature_calc_roll_exec(bContext *C, wmOperator *op) 
{
	Object *ob = CTX_data_edit_object(C);
	const short type = RNA_enum_get(op->ptr, "type");
	const short axis_only = RNA_boolean_get(op->ptr, "axis_only");
	const short axis_flip = RNA_boolean_get(op->ptr, "axis_flip");

	float imat[3][3];

	bArmature *arm = ob->data;
	EditBone *ebone;

	copy_m3_m4(imat, ob->obmat);
	invert_m3(imat);

	if (type == CALC_ROLL_CURSOR) { /* Cursor */
		Scene *scene = CTX_data_scene(C);
		View3D *v3d = CTX_wm_view3d(C); /* can be NULL */
		float cursor_local[3];
		const float   *cursor = give_cursor(scene, v3d);
		
		
		copy_v3_v3(cursor_local, cursor);
		mul_m3_v3(imat, cursor_local);
		
		/* cursor */
		for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
			if (EBONE_VISIBLE(arm, ebone) && EBONE_EDITABLE(ebone)) {
				float cursor_rel[3];
				sub_v3_v3v3(cursor_rel, cursor_local, ebone->head);
				if (axis_flip) negate_v3(cursor_rel);
				ebone->roll = ED_rollBoneToVector(ebone, cursor_rel, axis_only);
			}
		}
	}
	else {
		float vec[3] = {0.0f, 0.0f, 0.0f};
		if (type == CALC_ROLL_VIEW) { /* View */
			RegionView3D *rv3d = CTX_wm_region_view3d(C);
			if (rv3d == NULL) {
				BKE_report(op->reports, RPT_ERROR, "No region view3d available");
				return OPERATOR_CANCELLED;
			}
			
			copy_v3_v3(vec, rv3d->viewinv[2]);
			mul_m3_v3(imat, vec);
		}
		else if (type == CALC_ROLL_ACTIVE) {
			float mat[3][3], nor[3];
			ebone = (EditBone *)arm->act_edbone;
			if (ebone == NULL) {
				BKE_report(op->reports, RPT_ERROR, "No active bone set");
				return OPERATOR_CANCELLED;
			}
			
			sub_v3_v3v3(nor, ebone->tail, ebone->head);
			vec_roll_to_mat3(nor, ebone->roll, mat);
			copy_v3_v3(vec, mat[2]);
		}
		else { /* Axis */
			assert(type >= 0 && type <= 5);
			if (type < 3) vec[type] = 1.0f;
			else vec[type - 2] = -1.0f;
			mul_m3_v3(imat, vec);
		}
		
		if (axis_flip) negate_v3(vec);
		
		for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
			if (EBONE_VISIBLE(arm, ebone) && EBONE_EDITABLE(ebone)) {
				/* roll func is a callback which assumes that all is well */
				ebone->roll = ED_rollBoneToVector(ebone, vec, axis_only);
			}
		}
	}
	
	if (arm->flag & ARM_MIRROR_EDIT) {
		for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
			if ((EBONE_VISIBLE(arm, ebone) && EBONE_EDITABLE(ebone)) == 0) {
				EditBone *ebone_mirr = ED_armature_bone_get_mirrored(arm->edbo, ebone);
				if (ebone_mirr && (EBONE_VISIBLE(arm, ebone_mirr) && EBONE_EDITABLE(ebone_mirr))) {
					ebone->roll = -ebone_mirr->roll;
				}
			}
		}
	}
	
	/* note, notifier might evolve */
	WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
	
	return OPERATOR_FINISHED;
}
Exemplo n.º 23
0
/* 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;
	View3D *v3d = CTX_wm_view3d(C);
	Render *re;
	wmJob *wm_job;
	RenderJob *rj;
	Image *ima;
	int jobflag;
	const short is_animation = RNA_boolean_get(op->ptr, "animation");
	const short is_write_still = RNA_boolean_get(op->ptr, "write_still");
	struct Object *camera_override = v3d ? V3D_CAMERA_LOCAL(v3d) : NULL;
	const char *name;
	Object *active_object = CTX_data_active_object(C);
	
	/* 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_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 multires changes (for sculpt) */
	multires_force_render_update(active_object);

	/* flush changes from dynamic topology sculpt */
	sculptsession_bm_to_me_for_render(active_object);

	/* 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();

	/* get editmode results */
	ED_object_editmode_load(CTX_data_edit_object(C));

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

	/* ensure at least 1 area shows result */
	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->win = CTX_wm_window(C);
	rj->srl = srl;
	rj->camera_override = camera_override;
	rj->lay = scene->lay;
	rj->anim = is_animation;
	rj->write_still = is_write_still && !is_animation;
	rj->iuser.scene = scene;
	rj->iuser.ok = 1;
	rj->reports = op->reports;

	if (v3d) {
		rj->lay = v3d->lay;

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

	/* 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_draw_cb(re, rj, image_rect_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;
}
Exemplo n.º 24
0
static int view3d_layers_poll(bContext *C)
{
	return (ED_operator_view3d_active(C) && CTX_wm_view3d(C)->localvd == NULL);
}
Exemplo n.º 25
0
/* using context, starts job */
static int screen_render_invoke(bContext *C, wmOperator *op, wmEvent *event)
{
	/* new render clears all callbacks */
	Main *mainp;
	Scene *scene= CTX_data_scene(C);
	SceneRenderLayer *srl=NULL;
	bScreen *screen= CTX_wm_screen(C);
	View3D *v3d= CTX_wm_view3d(C);
	Render *re;
	wmJob *steve;
	RenderJob *rj;
	Image *ima;
	int jobflag;
	const short is_animation= RNA_boolean_get(op->ptr, "animation");
	const short is_write_still= RNA_boolean_get(op->ptr, "write_still");
	struct Object *camera_override= v3d ? V3D_CAMERA_LOCAL(v3d) : NULL;
	
	/* only one render job at a time */
	if(WM_jobs_test(CTX_wm_manager(C), scene))
		return OPERATOR_CANCELLED;

	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.imtype)) {
		BKE_report(op->reports, RPT_ERROR, "Can't write a single file with an animation format selected.");
		return OPERATOR_CANCELLED;
	}	
	
	/* stop all running jobs, currently previews frustrate Render */
	WM_jobs_stop_all(CTX_wm_manager(C));

	/* get main */
	if(G.rt == 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 (screen->animtimer)
		ED_screen_animation_play(C, 0, 0);
	
	/* handle UI stuff */
	WM_cursor_wait(1);

	/* flush multires changes (for sculpt) */
	multires_force_render_update(CTX_data_active_object(C));

	/* 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) */
	seq_stripelem_cache_cleanup();

	/* get editmode results */
	ED_object_exit_editmode(C, 0);	/* 0 = does not exit editmode */

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

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

	jobflag= WM_JOB_EXCL_RENDER|WM_JOB_PRIORITY|WM_JOB_PROGRESS;
	
	/* single layer re-render */
	if(RNA_property_is_set(op->ptr, "layer")) {
		SceneRenderLayer *rl;
		Scene *scn;
		char scene_name[MAX_ID_NAME-2], rl_name[RE_MAXNAME];

		RNA_string_get(op->ptr, "layer", rl_name);
		RNA_string_get(op->ptr, "scene", scene_name);

		scn = (Scene *)BLI_findstring(&mainp->scene, scene_name, offsetof(ID, name) + 2);
		rl = (SceneRenderLayer *)BLI_findstring(&scene->r.layers, rl_name, offsetof(SceneRenderLayer, name));
		
		if (scn && rl) {
			/* camera switch wont have updated */
			scn->r.cfra= scene->r.cfra;
			scene_camera_switch_update(scn);

			scene = scn;
			srl = rl;
		}
		jobflag |= WM_JOB_SUSPEND;
	}

	/* job custom data */
	rj= MEM_callocN(sizeof(RenderJob), "render job");
	rj->main= mainp;
	rj->scene= scene;
	rj->win= CTX_wm_window(C);
	rj->srl = srl;
	rj->camera_override = camera_override;
	rj->lay = (v3d)? v3d->lay: scene->lay;
	rj->anim= is_animation;
	rj->write_still= is_write_still && !is_animation;
	rj->iuser.scene= scene;
	rj->iuser.ok= 1;
	rj->reports= op->reports;

	/* setup job */
	steve= WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, "Render", jobflag);
	WM_jobs_customdata(steve, rj, render_freejob);
	WM_jobs_timer(steve, 0.2, NC_SCENE|ND_RENDER_RESULT, 0);
	WM_jobs_callbacks(steve, 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_draw_cb(re, rj, image_rect_update);
	RE_stats_draw_cb(re, rj, image_renderinfo_cb);
	RE_progress_cb(re, rj, render_progress_update);

	rj->re= re;
	G.afbreek= 0;

	WM_jobs_start(CTX_wm_manager(C), steve);

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

	/* we set G.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.rendering = 1;

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

	return OPERATOR_RUNNING_MODAL;
}
Exemplo n.º 26
0
/* Draw the contents for a grease-pencil panel*/
static void draw_gpencil_panel(bContext *C, uiLayout *layout, bGPdata *gpd, PointerRNA *ctx_ptr)
{
	PointerRNA gpd_ptr;
	bGPDlayer *gpl;
	uiLayout *col, *row;
	SpaceClip *sc = CTX_wm_space_clip(C);
	short v3d_stroke_opts = STROKE_OPTS_NORMAL;
	const short is_v3d = CTX_wm_view3d(C) != NULL;
	
	/* make new PointerRNA for Grease Pencil block */
	RNA_id_pointer_create((ID *)gpd, &gpd_ptr);
	
	/* draw gpd settings first ------------------------------------- */
	col = uiLayoutColumn(layout, FALSE);

	/* current Grease Pencil block */
	/* TODO: show some info about who owns this? */
	uiTemplateID(col, C, ctx_ptr, "grease_pencil", "GPENCIL_OT_data_add", NULL, "GPENCIL_OT_data_unlink");
	
	/* add new layer button - can be used even when no data, since it can add a new block too */
	uiItemO(col, IFACE_("New Layer"), ICON_NONE, "GPENCIL_OT_layer_add");
	row = uiLayoutRow(col, TRUE);
	uiItemO(row, IFACE_("Delete Frame"), ICON_NONE, "GPENCIL_OT_active_frame_delete");
	uiItemO(row, IFACE_("Convert"), ICON_NONE, "GPENCIL_OT_convert");
	
	/* sanity checks... */
	if (gpd == NULL)
		return;
	
	/* draw each layer --------------------------------------------- */
	for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
		col = uiLayoutColumn(layout, TRUE);
		gp_drawui_layer(col, gpd, gpl, is_v3d);
	}
	
	/* draw gpd drawing settings first ------------------------------------- */
	col = uiLayoutColumn(layout, TRUE);
	/* label */
	uiItemL(col, IFACE_("Drawing Settings:"), ICON_NONE);
		
	/* check whether advanced 3D-View drawing space options can be used */
	if (is_v3d) {
		if (gpd->flag & (GP_DATA_DEPTH_STROKE | GP_DATA_DEPTH_VIEW))
			v3d_stroke_opts = STROKE_OPTS_V3D_ON;
		else
			v3d_stroke_opts = STROKE_OPTS_V3D_OFF;
	}
		
	/* drawing space options */
	row = uiLayoutRow(col, TRUE);
	uiItemEnumR_string(row, &gpd_ptr, "draw_mode", "VIEW", NULL, ICON_NONE);
	uiItemEnumR_string(row, &gpd_ptr, "draw_mode", "CURSOR", NULL, ICON_NONE);

	if (sc == NULL) {
		row = uiLayoutRow(col, TRUE);
		uiLayoutSetActive(row, v3d_stroke_opts);
		uiItemEnumR_string(row, &gpd_ptr, "draw_mode", "SURFACE", NULL, ICON_NONE);
		uiItemEnumR_string(row, &gpd_ptr, "draw_mode", "STROKE", NULL, ICON_NONE);

		row = uiLayoutRow(col, FALSE);
		uiLayoutSetActive(row, v3d_stroke_opts == STROKE_OPTS_V3D_ON);
		uiItemR(row, &gpd_ptr, "use_stroke_endpoints", 0, NULL, ICON_NONE);
	}
}
extern "C" void StartKetsjiShell(struct bContext *C, struct ARegion *ar, rcti *cam_frame, int always_use_expand_framing)
{
	/* context values */
	struct wmWindowManager *wm= CTX_wm_manager(C);
	struct wmWindow *win= CTX_wm_window(C);
	struct Scene *startscene= CTX_data_scene(C);
	struct Main* maggie1= CTX_data_main(C);


	RAS_Rect area_rect;
	area_rect.SetLeft(cam_frame->xmin);
	area_rect.SetBottom(cam_frame->ymin);
	area_rect.SetRight(cam_frame->xmax);
	area_rect.SetTop(cam_frame->ymax);

	int exitrequested = KX_EXIT_REQUEST_NO_REQUEST;
	Main* blenderdata = maggie1;

	char* startscenename = startscene->id.name+2;
	char pathname[FILE_MAXDIR+FILE_MAXFILE], oldsce[FILE_MAXDIR+FILE_MAXFILE];
	STR_String exitstring = "";
	BlendFileData *bfd= NULL;

	BLI_strncpy(pathname, blenderdata->name, sizeof(pathname));
	BLI_strncpy(oldsce, G.main->name, sizeof(oldsce));
#ifdef WITH_PYTHON
	resetGamePythonPath(); // need this so running a second time wont use an old blendfiles path
	setGamePythonPath(G.main->name);

	// Acquire Python's GIL (global interpreter lock)
	// so we can safely run Python code and API calls
	PyGILState_STATE gilstate = PyGILState_Ensure();
	
	PyObject *pyGlobalDict = PyDict_New(); /* python utility storage, spans blend file loading */
#endif
	
	bgl::InitExtensions(true);

	// VBO code for derived mesh is not compatible with BGE (couldn't find why), so disable
	int disableVBO = (U.gameflags & USER_DISABLE_VBO);
	U.gameflags |= USER_DISABLE_VBO;

	// Globals to be carried on over blender files
	GlobalSettings gs;
	gs.matmode= startscene->gm.matmode;
	gs.glslflag= startscene->gm.flag;

	do
	{
		View3D *v3d= CTX_wm_view3d(C);
		RegionView3D *rv3d= CTX_wm_region_view3d(C);

		// get some preferences
		SYS_SystemHandle syshandle = SYS_GetSystem();
		bool properties	= (SYS_GetCommandLineInt(syshandle, "show_properties", 0) != 0);
		bool usefixed = (SYS_GetCommandLineInt(syshandle, "fixedtime", 0) != 0);
		bool profile = (SYS_GetCommandLineInt(syshandle, "show_profile", 0) != 0);
		bool frameRate = (SYS_GetCommandLineInt(syshandle, "show_framerate", 0) != 0);
		bool animation_record = (SYS_GetCommandLineInt(syshandle, "animation_record", 0) != 0);
		bool displaylists = (SYS_GetCommandLineInt(syshandle, "displaylists", 0) != 0) && GPU_display_list_support();
#ifdef WITH_PYTHON
		bool nodepwarnings = (SYS_GetCommandLineInt(syshandle, "ignore_deprecation_warnings", 0) != 0);
#endif
		// bool novertexarrays = (SYS_GetCommandLineInt(syshandle, "novertexarrays", 0) != 0);
		bool mouse_state = (startscene->gm.flag & GAME_SHOW_MOUSE) != 0;
		bool restrictAnimFPS = (startscene->gm.flag & GAME_RESTRICT_ANIM_UPDATES) != 0;

		short drawtype = v3d->drawtype;
		
		/* we do not support material mode in game engine, force change to texture mode */
		if (drawtype == OB_MATERIAL) drawtype = OB_TEXTURE;
		if (animation_record) usefixed= false; /* override since you don't want to run full-speed for sim recording */

		// create the canvas and rasterizer
		RAS_ICanvas* canvas = new KX_BlenderCanvas(wm, win, area_rect, ar);
		
		// default mouse state set on render panel
		if (mouse_state)
			canvas->SetMouseState(RAS_ICanvas::MOUSE_NORMAL);
		else
			canvas->SetMouseState(RAS_ICanvas::MOUSE_INVISIBLE);

		// Setup vsync
		int previous_vsync = 0;
		canvas->GetSwapInterval(previous_vsync);
		if (startscene->gm.vsync == VSYNC_ADAPTIVE)
			canvas->SetSwapInterval(-1);
		else
			canvas->SetSwapInterval((startscene->gm.vsync == VSYNC_ON) ? 1 : 0);

		RAS_IRasterizer* rasterizer = NULL;
		//Don't use displaylists with VBOs
		//If auto starts using VBOs, make sure to check for that here
		if (displaylists && startscene->gm.raster_storage != RAS_STORE_VBO)
			rasterizer = new RAS_ListRasterizer(canvas, true, startscene->gm.raster_storage);
		else
			rasterizer = new RAS_OpenGLRasterizer(canvas, startscene->gm.raster_storage);

		RAS_IRasterizer::MipmapOption mipmapval = rasterizer->GetMipmapping();

		
		// create the inputdevices
		KX_BlenderKeyboardDevice* keyboarddevice = new KX_BlenderKeyboardDevice();
		KX_BlenderMouseDevice* mousedevice = new KX_BlenderMouseDevice();
		
		// create a networkdevice
		NG_NetworkDeviceInterface* networkdevice = new
			NG_LoopBackNetworkDeviceInterface();

		//
		// create a ketsji/blendersystem (only needed for timing and stuff)
		KX_BlenderSystem* kxsystem = new KX_BlenderSystem();
		
		// create the ketsjiengine
		KX_KetsjiEngine* ketsjiengine = new KX_KetsjiEngine(kxsystem);
		
		// set the devices
		ketsjiengine->SetKeyboardDevice(keyboarddevice);
		ketsjiengine->SetMouseDevice(mousedevice);
		ketsjiengine->SetNetworkDevice(networkdevice);
		ketsjiengine->SetCanvas(canvas);
		ketsjiengine->SetRasterizer(rasterizer);
		ketsjiengine->SetUseFixedTime(usefixed);
		ketsjiengine->SetTimingDisplay(frameRate, profile, properties);
		ketsjiengine->SetRestrictAnimationFPS(restrictAnimFPS);
		KX_KetsjiEngine::SetExitKey(ConvertKeyCode(startscene->gm.exitkey));

		//set the global settings (carried over if restart/load new files)
		ketsjiengine->SetGlobalSettings(&gs);

#ifdef WITH_PYTHON
		CValue::SetDeprecationWarnings(nodepwarnings);
#endif

		//lock frame and camera enabled - storing global values
		int tmp_lay= startscene->lay;
		Object *tmp_camera = startscene->camera;

		if (v3d->scenelock==0) {
			startscene->lay= v3d->lay;
			startscene->camera= v3d->camera;
		}

		// some blender stuff
		float camzoom;
		int draw_letterbox = 0;
		
		if (rv3d->persp==RV3D_CAMOB) {
			if (startscene->gm.framing.type == SCE_GAMEFRAMING_BARS) { /* Letterbox */
				camzoom = 1.0f;
				draw_letterbox = 1;
			}
			else {
				camzoom = 1.0f / BKE_screen_view3d_zoom_to_fac(rv3d->camzoom);
			}
		}
		else {
			camzoom = 2.0;
		}

		rasterizer->SetDrawingMode(drawtype);
		ketsjiengine->SetCameraZoom(camzoom);
		
		// if we got an exitcode 3 (KX_EXIT_REQUEST_START_OTHER_GAME) load a different file
		if (exitrequested == KX_EXIT_REQUEST_START_OTHER_GAME || exitrequested == KX_EXIT_REQUEST_RESTART_GAME)
		{
			exitrequested = KX_EXIT_REQUEST_NO_REQUEST;
			if (bfd) BLO_blendfiledata_free(bfd);
			
			char basedpath[FILE_MAX];
			// base the actuator filename with respect
			// to the original file working directory

			if (exitstring != "")
				BLI_strncpy(basedpath, exitstring.ReadPtr(), sizeof(basedpath));

			// load relative to the last loaded file, this used to be relative
			// to the first file but that makes no sense, relative paths in
			// blend files should be relative to that file, not some other file
			// that happened to be loaded first
			BLI_path_abs(basedpath, pathname);
			bfd = load_game_data(basedpath);
			
			// if it wasn't loaded, try it forced relative
			if (!bfd)
			{
				// just add "//" in front of it
				char temppath[FILE_MAX] = "//";
				BLI_strncpy(temppath + 2, basedpath, FILE_MAX - 2);
				
				BLI_path_abs(temppath, pathname);
				bfd = load_game_data(temppath);
			}
			
			// if we got a loaded blendfile, proceed
			if (bfd)
			{
				blenderdata = bfd->main;
				startscenename = bfd->curscene->id.name + 2;

				if (blenderdata) {
					BLI_strncpy(G.main->name, blenderdata->name, sizeof(G.main->name));
					BLI_strncpy(pathname, blenderdata->name, sizeof(pathname));
#ifdef WITH_PYTHON
					setGamePythonPath(G.main->name);
#endif
				}
			}
			// else forget it, we can't find it
			else
			{
				exitrequested = KX_EXIT_REQUEST_QUIT_GAME;
			}
		}

		Scene *scene= bfd ? bfd->curscene : (Scene *)BLI_findstring(&blenderdata->scene, startscenename, offsetof(ID, name) + 2);

		if (scene)
		{
			int startFrame = scene->r.cfra;
			ketsjiengine->SetAnimRecordMode(animation_record, startFrame);
			
			// Quad buffered needs a special window.
			if (scene->gm.stereoflag == STEREO_ENABLED) {
				if (scene->gm.stereomode != RAS_IRasterizer::RAS_STEREO_QUADBUFFERED)
					rasterizer->SetStereoMode((RAS_IRasterizer::StereoMode) scene->gm.stereomode);

				rasterizer->SetEyeSeparation(scene->gm.eyeseparation);
			}

			rasterizer->SetBackColor(scene->gm.framing.col);
		}
		
		if (exitrequested != KX_EXIT_REQUEST_QUIT_GAME)
		{
			if (rv3d->persp != RV3D_CAMOB)
			{
				ketsjiengine->EnableCameraOverride(startscenename);
				ketsjiengine->SetCameraOverrideUseOrtho((rv3d->persp == RV3D_ORTHO));
				ketsjiengine->SetCameraOverrideProjectionMatrix(MT_CmMatrix4x4(rv3d->winmat));
				ketsjiengine->SetCameraOverrideViewMatrix(MT_CmMatrix4x4(rv3d->viewmat));
				ketsjiengine->SetCameraOverrideClipping(v3d->near, v3d->far);
				ketsjiengine->SetCameraOverrideLens(v3d->lens);
			}
			
			// create a scene converter, create and convert the startingscene
			KX_ISceneConverter* sceneconverter = new KX_BlenderSceneConverter(blenderdata, ketsjiengine);
			ketsjiengine->SetSceneConverter(sceneconverter);
			if (always_use_expand_framing)
				sceneconverter->SetAlwaysUseExpandFraming(true);

			bool usemat = false, useglslmat = false;

			if (GLEW_ARB_multitexture && GLEW_VERSION_1_1)
				usemat = true;

			if (GPU_glsl_support())
				useglslmat = true;
			else if (gs.matmode == GAME_MAT_GLSL)
				usemat = false;

			if (usemat)
				sceneconverter->SetMaterials(true);
			if (useglslmat && (gs.matmode == GAME_MAT_GLSL))
				sceneconverter->SetGLSLMaterials(true);
			if (scene->gm.flag & GAME_NO_MATERIAL_CACHING)
				sceneconverter->SetCacheMaterials(false);
					
			KX_Scene* startscene = new KX_Scene(keyboarddevice,
				mousedevice,
				networkdevice,
				startscenename,
				scene,
				canvas);

#ifdef WITH_PYTHON
			// some python things
			PyObject *gameLogic, *gameLogic_keys;
			setupGamePython(ketsjiengine, startscene, blenderdata, pyGlobalDict, &gameLogic, &gameLogic_keys, 0, NULL);
#endif // WITH_PYTHON

			//initialize Dome Settings
			if (scene->gm.stereoflag == STEREO_DOME)
				ketsjiengine->InitDome(scene->gm.dome.res, scene->gm.dome.mode, scene->gm.dome.angle, scene->gm.dome.resbuf, scene->gm.dome.tilt, scene->gm.dome.warptext);

			// initialize 3D Audio Settings
			AUD_I3DDevice* dev = AUD_get3DDevice();
			if (dev)
			{
				dev->setSpeedOfSound(scene->audio.speed_of_sound);
				dev->setDopplerFactor(scene->audio.doppler_factor);
				dev->setDistanceModel(AUD_DistanceModel(scene->audio.distance_model));
			}

			// from see blender.c:
			// FIXME: this version patching should really be part of the file-reading code,
			// but we still get too many unrelated data-corruption crashes otherwise...
			if (blenderdata->versionfile < 250)
				do_versions_ipos_to_animato(blenderdata);

			if (sceneconverter)
			{
				// convert and add scene
				sceneconverter->ConvertScene(
					startscene,
				    rasterizer,
					canvas);
				ketsjiengine->AddScene(startscene);
				
				// init the rasterizer
				rasterizer->Init();
				
				// start the engine
				ketsjiengine->StartEngine(true);
				

				// Set the animation playback rate for ipo's and actions
				// the framerate below should patch with FPS macro defined in blendef.h
				// Could be in StartEngine set the framerate, we need the scene to do this
				ketsjiengine->SetAnimFrameRate(FPS);
				
#ifdef WITH_PYTHON
				char *python_main = NULL;
				pynextframestate.state = NULL;
				pynextframestate.func = NULL;
				python_main = KX_GetPythonMain(scene);

				// the mainloop
				printf("\nBlender Game Engine Started\n");
				if (python_main) {
					char *python_code = KX_GetPythonCode(blenderdata, python_main);
					if (python_code) {
						ketsjinextframestate.ketsjiengine = ketsjiengine;
						ketsjinextframestate.C = C;
						ketsjinextframestate.win = win;
						ketsjinextframestate.scene = scene;
						ketsjinextframestate.ar = ar;
						ketsjinextframestate.keyboarddevice = keyboarddevice;
						ketsjinextframestate.mousedevice = mousedevice;
						ketsjinextframestate.draw_letterbox = draw_letterbox;
			
						pynextframestate.state = &ketsjinextframestate;
						pynextframestate.func = &BL_KetsjiPyNextFrame;
						printf("Yielding control to Python script '%s'...\n", python_main);
						PyRun_SimpleString(python_code);
						printf("Exit Python script '%s'\n", python_main);
						MEM_freeN(python_code);
					}
				}
				else
#endif  /* WITH_PYTHON */
				{
					while (!exitrequested)
					{
						exitrequested = BL_KetsjiNextFrame(ketsjiengine, C, win, scene, ar, keyboarddevice, mousedevice, draw_letterbox);
					}
				}
				printf("Blender Game Engine Finished\n");
				exitstring = ketsjiengine->GetExitString();
#ifdef WITH_PYTHON
				if (python_main) MEM_freeN(python_main);
#endif  /* WITH_PYTHON */

				gs = *(ketsjiengine->GetGlobalSettings());

				// when exiting the mainloop
#ifdef WITH_PYTHON
				// Clears the dictionary by hand:
				// This prevents, extra references to global variables
				// inside the GameLogic dictionary when the python interpreter is finalized.
				// which allows the scene to safely delete them :)
				// see: (space.c)->start_game
				
				//PyDict_Clear(PyModule_GetDict(gameLogic));
				
				// Keep original items, means python plugins will autocomplete members
				PyObject *gameLogic_keys_new = PyDict_Keys(PyModule_GetDict(gameLogic));
				const Py_ssize_t numitems= PyList_GET_SIZE(gameLogic_keys_new);
				Py_ssize_t listIndex;
				for (listIndex=0; listIndex < numitems; listIndex++) {
					PyObject *item = PyList_GET_ITEM(gameLogic_keys_new, listIndex);
					if (!PySequence_Contains(gameLogic_keys, item)) {
						PyDict_DelItem(	PyModule_GetDict(gameLogic), item);
					}
				}
				Py_DECREF(gameLogic_keys_new);
				gameLogic_keys_new = NULL;
#endif
				ketsjiengine->StopEngine();
#ifdef WITH_PYTHON
				exitGamePythonScripting();
#endif
				networkdevice->Disconnect();
			}
			if (sceneconverter)
			{
				delete sceneconverter;
				sceneconverter = NULL;
			}

#ifdef WITH_PYTHON
			Py_DECREF(gameLogic_keys);
			gameLogic_keys = NULL;
#endif
		}
		//lock frame and camera enabled - restoring global values
		if (v3d->scenelock==0) {
			startscene->lay= tmp_lay;
			startscene->camera= tmp_camera;
		}

		if (exitrequested != KX_EXIT_REQUEST_OUTSIDE)
		{
			// set the cursor back to normal
			canvas->SetMouseState(RAS_ICanvas::MOUSE_NORMAL);

			// set mipmap setting back to its original value
			rasterizer->SetMipmapping(mipmapval);
		}
		
		// clean up some stuff
		if (ketsjiengine)
		{
			delete ketsjiengine;
			ketsjiengine = NULL;
		}
		if (kxsystem)
		{
			delete kxsystem;
			kxsystem = NULL;
		}
		if (networkdevice)
		{
			delete networkdevice;
			networkdevice = NULL;
		}
		if (keyboarddevice)
		{
			delete keyboarddevice;
			keyboarddevice = NULL;
		}
		if (mousedevice)
		{
			delete mousedevice;
			mousedevice = NULL;
		}
		if (rasterizer)
		{
			delete rasterizer;
			rasterizer = NULL;
		}
		if (canvas)
		{
			canvas->SetSwapInterval(previous_vsync); // Set the swap interval back
			delete canvas;
			canvas = NULL;
		}

		// stop all remaining playing sounds
		AUD_getDevice()->stopAll();
	
	} while (exitrequested == KX_EXIT_REQUEST_RESTART_GAME || exitrequested == KX_EXIT_REQUEST_START_OTHER_GAME);
	
	if (!disableVBO)
		U.gameflags &= ~USER_DISABLE_VBO;

	if (bfd) BLO_blendfiledata_free(bfd);

	BLI_strncpy(G.main->name, oldsce, sizeof(G.main->name));

#ifdef WITH_PYTHON
	Py_DECREF(pyGlobalDict);

	// Release Python's GIL
	PyGILState_Release(gilstate);
#endif

}
Exemplo n.º 28
0
static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op)
{
	wmWindow *win = CTX_wm_window(C);

	walk->rv3d = CTX_wm_region_view3d(C);
	walk->v3d = CTX_wm_view3d(C);
	walk->ar = CTX_wm_region(C);
	walk->scene = CTX_data_scene(C);

#ifdef NDOF_WALK_DEBUG
	puts("\n-- walk begin --");
#endif

	/* sanity check: for rare but possible case (if lib-linking the camera fails) */
	if ((walk->rv3d->persp == RV3D_CAMOB) && (walk->v3d->camera == NULL)) {
		walk->rv3d->persp = RV3D_PERSP;
	}

	if (walk->rv3d->persp == RV3D_CAMOB && walk->v3d->camera->id.lib) {
		BKE_report(op->reports, RPT_ERROR, "Cannot navigate a camera from an external library");
		return false;
	}

	if (ED_view3d_offset_lock_check(walk->v3d, walk->rv3d)) {
		BKE_report(op->reports, RPT_ERROR, "Cannot navigate when the view offset is locked");
		return false;
	}

	if (walk->rv3d->persp == RV3D_CAMOB && walk->v3d->camera->constraints.first) {
		BKE_report(op->reports, RPT_ERROR, "Cannot navigate an object with constraints");
		return false;
	}

	walk->state = WALK_RUNNING;

	if (fabsf(U.walk_navigation.walk_speed - userdef_speed) > 0.1f) {
		base_speed = U.walk_navigation.walk_speed;
		userdef_speed = U.walk_navigation.walk_speed;
	}

	walk->speed = 0.0f;
	walk->is_fast = false;
	walk->is_slow = false;
	walk->grid = (walk->scene->unit.system == USER_UNIT_NONE) ? 1.f : 1.f / walk->scene->unit.scale_length;

	/* user preference settings */
	walk->teleport.duration = U.walk_navigation.teleport_time;
	walk->mouse_speed = U.walk_navigation.mouse_speed;

	if ((U.walk_navigation.flag & USER_WALK_GRAVITY))
		walk_navigation_mode_set(C, op, walk, WALK_MODE_GRAVITY);
	else
		walk_navigation_mode_set(C, op, walk, WALK_MODE_FREE);

	walk->view_height = U.walk_navigation.view_height;
	walk->jump_height = U.walk_navigation.jump_height;
	walk->speed = U.walk_navigation.walk_speed;
	walk->speed_factor = U.walk_navigation.walk_speed_factor;

	walk->gravity_state = WALK_GRAVITY_STATE_OFF;

	if ((walk->scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY)) {
		walk->gravity = fabsf(walk->scene->physics_settings.gravity[2]);
	}
	else {
		walk->gravity = 9.80668f; /* m/s2 */
	}

	walk->is_reversed = ((U.walk_navigation.flag & USER_WALK_MOUSE_REVERSE) != 0);

#ifdef USE_TABLET_SUPPORT
	walk->is_cursor_first = true;

	walk->is_cursor_absolute = false;
#endif

	walk->active_directions = 0;

#ifdef NDOF_WALK_DRAW_TOOMUCH
	walk->redraw = 1;
#endif
	zero_v3(walk->dvec_prev);

	walk->timer = WM_event_add_timer(CTX_wm_manager(C), win, TIMER, 0.01f);

	walk->ndof = NULL;

	walk->time_lastdraw = PIL_check_seconds_timer();

	walk->draw_handle_pixel = ED_region_draw_cb_activate(walk->ar->type, drawWalkPixel, walk, REGION_DRAW_POST_PIXEL);

	walk->rv3d->rflag |= RV3D_NAVIGATING;


	walk->v3d_camera_control = ED_view3d_cameracontrol_acquire(
	        walk->scene, walk->v3d, walk->rv3d,
	        (U.uiflag & USER_CAM_LOCK_NO_PARENT) == 0);

	/* center the mouse */
	walk->center_mval[0] = walk->ar->winx * 0.5f;
	walk->center_mval[1] = walk->ar->winy * 0.5f;

#ifdef USE_PIXELSIZE_NATIVE_SUPPORT
	walk->center_mval[0] += walk->ar->winrct.xmin;
	walk->center_mval[1] += walk->ar->winrct.ymin;

	WM_cursor_compatible_xy(win, &walk->center_mval[0], &walk->center_mval[1]);

	walk->center_mval[0] -= walk->ar->winrct.xmin;
	walk->center_mval[1] -= walk->ar->winrct.ymin;
#endif

	copy_v2_v2_int(walk->prev_mval, walk->center_mval);

	WM_cursor_warp(win,
	               walk->ar->winrct.xmin + walk->center_mval[0],
	               walk->ar->winrct.ymin + walk->center_mval[1]);

	/* remove the mouse cursor temporarily */
	WM_cursor_modal_set(win, CURSOR_NONE);

	return 1;
}
Exemplo n.º 29
0
extern "C" void StartKetsjiShell(struct bContext *C, struct ARegion *ar, rcti *cam_frame, int always_use_expand_framing)
{
	/* context values */
	struct wmWindow *win= CTX_wm_window(C);
	struct Scene *startscene= CTX_data_scene(C);
	struct Main* maggie1= CTX_data_main(C);


	RAS_Rect area_rect;
	area_rect.SetLeft(cam_frame->xmin);
	area_rect.SetBottom(cam_frame->ymin);
	area_rect.SetRight(cam_frame->xmax);
	area_rect.SetTop(cam_frame->ymax);

	int exitrequested = KX_EXIT_REQUEST_NO_REQUEST;
	Main* blenderdata = maggie1;

	char* startscenename = startscene->id.name+2;
	char pathname[FILE_MAXDIR+FILE_MAXFILE], oldsce[FILE_MAXDIR+FILE_MAXFILE];
	STR_String exitstring = "";
	BlendFileData *bfd= NULL;

	BLI_strncpy(pathname, blenderdata->name, sizeof(pathname));
	BLI_strncpy(oldsce, G.main->name, sizeof(oldsce));
#ifdef WITH_PYTHON
	resetGamePythonPath(); // need this so running a second time wont use an old blendfiles path
	setGamePythonPath(G.main->name);

	// Acquire Python's GIL (global interpreter lock)
	// so we can safely run Python code and API calls
	PyGILState_STATE gilstate = PyGILState_Ensure();
	
	PyObject *pyGlobalDict = PyDict_New(); /* python utility storage, spans blend file loading */
#endif
	
	bgl::InitExtensions(true);

	// VBO code for derived mesh is not compatible with BGE (couldn't find why), so disable
	int disableVBO = (U.gameflags & USER_DISABLE_VBO);
	U.gameflags |= USER_DISABLE_VBO;

	// Globals to be carried on over blender files
	GlobalSettings gs;
	gs.matmode= startscene->gm.matmode;
	gs.glslflag= startscene->gm.flag;

	do
	{
		View3D *v3d= CTX_wm_view3d(C);
		RegionView3D *rv3d= CTX_wm_region_view3d(C);

		// get some preferences
		SYS_SystemHandle syshandle = SYS_GetSystem();
		bool properties	= (SYS_GetCommandLineInt(syshandle, "show_properties", 0) != 0);
		bool usefixed = (SYS_GetCommandLineInt(syshandle, "fixedtime", 0) != 0);
		bool profile = (SYS_GetCommandLineInt(syshandle, "show_profile", 0) != 0);
		bool frameRate = (SYS_GetCommandLineInt(syshandle, "show_framerate", 0) != 0);
		bool animation_record = (SYS_GetCommandLineInt(syshandle, "animation_record", 0) != 0);
		bool displaylists = (SYS_GetCommandLineInt(syshandle, "displaylists", 0) != 0);
#ifdef WITH_PYTHON
		bool nodepwarnings = (SYS_GetCommandLineInt(syshandle, "ignore_deprecation_warnings", 0) != 0);
#endif
		bool novertexarrays = (SYS_GetCommandLineInt(syshandle, "novertexarrays", 0) != 0);
		bool mouse_state = startscene->gm.flag & GAME_SHOW_MOUSE;
		bool restrictAnimFPS = startscene->gm.flag & GAME_RESTRICT_ANIM_UPDATES;

		if(animation_record) usefixed= true; /* override since you's always want fixed time for sim recording */

		// create the canvas, rasterizer and rendertools
		RAS_ICanvas* canvas = new KX_BlenderCanvas(win, area_rect, ar);
		
		// default mouse state set on render panel
		if (mouse_state)
			canvas->SetMouseState(RAS_ICanvas::MOUSE_NORMAL);
		else
			canvas->SetMouseState(RAS_ICanvas::MOUSE_INVISIBLE);
		RAS_IRenderTools* rendertools = new KX_BlenderRenderTools();
		RAS_IRasterizer* rasterizer = NULL;
		
		if(displaylists) {
			if (GLEW_VERSION_1_1 && !novertexarrays)
				rasterizer = new RAS_ListRasterizer(canvas, true, true);
			else
				rasterizer = new RAS_ListRasterizer(canvas);
		}
		else if (GLEW_VERSION_1_1 && !novertexarrays)
			rasterizer = new RAS_VAOpenGLRasterizer(canvas, false);
		else
			rasterizer = new RAS_OpenGLRasterizer(canvas);
		
		// create the inputdevices
		KX_BlenderKeyboardDevice* keyboarddevice = new KX_BlenderKeyboardDevice();
		KX_BlenderMouseDevice* mousedevice = new KX_BlenderMouseDevice();
		
		// create a networkdevice
		NG_NetworkDeviceInterface* networkdevice = new
			NG_LoopBackNetworkDeviceInterface();

		//
		// create a ketsji/blendersystem (only needed for timing and stuff)
		KX_BlenderSystem* kxsystem = new KX_BlenderSystem();
		
		// create the ketsjiengine
		KX_KetsjiEngine* ketsjiengine = new KX_KetsjiEngine(kxsystem);
		
		// set the devices
		ketsjiengine->SetKeyboardDevice(keyboarddevice);
		ketsjiengine->SetMouseDevice(mousedevice);
		ketsjiengine->SetNetworkDevice(networkdevice);
		ketsjiengine->SetCanvas(canvas);
		ketsjiengine->SetRenderTools(rendertools);
		ketsjiengine->SetRasterizer(rasterizer);
		ketsjiengine->SetUseFixedTime(usefixed);
		ketsjiengine->SetTimingDisplay(frameRate, profile, properties);
		ketsjiengine->SetRestrictAnimationFPS(restrictAnimFPS);
		KX_KetsjiEngine::SetExitKey(ConvertKeyCode(startscene->gm.exitkey));

		//set the global settings (carried over if restart/load new files)
		ketsjiengine->SetGlobalSettings(&gs);

#ifdef WITH_PYTHON
		CValue::SetDeprecationWarnings(nodepwarnings);
#endif

		//lock frame and camera enabled - storing global values
		int tmp_lay= startscene->lay;
		Object *tmp_camera = startscene->camera;

		if (v3d->scenelock==0){
			startscene->lay= v3d->lay;
			startscene->camera= v3d->camera;
		}

		// some blender stuff
		float camzoom;
		int draw_letterbox = 0;
		
		if(rv3d->persp==RV3D_CAMOB) {
			if(startscene->gm.framing.type == SCE_GAMEFRAMING_BARS) { /* Letterbox */
				camzoom = 1.0f;
				draw_letterbox = 1;
			}
			else {
				camzoom = 1.0 / BKE_screen_view3d_zoom_to_fac(rv3d->camzoom);
			}
		}
		else {
			camzoom = 2.0;
		}


		ketsjiengine->SetDrawType(v3d->drawtype);
		ketsjiengine->SetCameraZoom(camzoom);
		
		// if we got an exitcode 3 (KX_EXIT_REQUEST_START_OTHER_GAME) load a different file
		if (exitrequested == KX_EXIT_REQUEST_START_OTHER_GAME || exitrequested == KX_EXIT_REQUEST_RESTART_GAME)
		{
			exitrequested = KX_EXIT_REQUEST_NO_REQUEST;
			if (bfd) BLO_blendfiledata_free(bfd);
			
			char basedpath[FILE_MAX];
			// base the actuator filename with respect
			// to the original file working directory

			if (exitstring != "")
				strcpy(basedpath, exitstring.Ptr());

			// load relative to the last loaded file, this used to be relative
			// to the first file but that makes no sense, relative paths in
			// blend files should be relative to that file, not some other file
			// that happened to be loaded first
			BLI_path_abs(basedpath, pathname);
			bfd = load_game_data(basedpath);
			
			// if it wasn't loaded, try it forced relative
			if (!bfd)
			{
				// just add "//" in front of it
				char temppath[242];
				strcpy(temppath, "//");
				strcat(temppath, basedpath);
				
				BLI_path_abs(temppath, pathname);
				bfd = load_game_data(temppath);
			}
			
			// if we got a loaded blendfile, proceed
			if (bfd)
			{
				blenderdata = bfd->main;
				startscenename = bfd->curscene->id.name + 2;

				if(blenderdata) {
					BLI_strncpy(G.main->name, blenderdata->name, sizeof(G.main->name));
					BLI_strncpy(pathname, blenderdata->name, sizeof(pathname));
#ifdef WITH_PYTHON
					setGamePythonPath(G.main->name);
#endif
				}
			}
			// else forget it, we can't find it
			else
			{
				exitrequested = KX_EXIT_REQUEST_QUIT_GAME;
			}
		}

		Scene *scene= bfd ? bfd->curscene : (Scene *)BLI_findstring(&blenderdata->scene, startscenename, offsetof(ID, name) + 2);

		if (scene)
		{
			int startFrame = scene->r.cfra;
			ketsjiengine->SetAnimRecordMode(animation_record, startFrame);
			
			// Quad buffered needs a special window.
			if(scene->gm.stereoflag == STEREO_ENABLED){
				if (scene->gm.stereomode != RAS_IRasterizer::RAS_STEREO_QUADBUFFERED)
					rasterizer->SetStereoMode((RAS_IRasterizer::StereoMode) scene->gm.stereomode);

				rasterizer->SetEyeSeparation(scene->gm.eyeseparation);
			}

			rasterizer->SetBackColor(scene->gm.framing.col[0], scene->gm.framing.col[1], scene->gm.framing.col[2], 0.0f);
		}
		
		if (exitrequested != KX_EXIT_REQUEST_QUIT_GAME)
		{
			if (rv3d->persp != RV3D_CAMOB)
			{
				ketsjiengine->EnableCameraOverride(startscenename);
				ketsjiengine->SetCameraOverrideUseOrtho((rv3d->persp == RV3D_ORTHO));
				ketsjiengine->SetCameraOverrideProjectionMatrix(MT_CmMatrix4x4(rv3d->winmat));
				ketsjiengine->SetCameraOverrideViewMatrix(MT_CmMatrix4x4(rv3d->viewmat));
				if(rv3d->persp == RV3D_ORTHO)
				{
					ketsjiengine->SetCameraOverrideClipping(-v3d->far, v3d->far);
				}
				else
				{
					ketsjiengine->SetCameraOverrideClipping(v3d->near, v3d->far);
				}
				ketsjiengine->SetCameraOverrideLens(v3d->lens);
			}
			
			// create a scene converter, create and convert the startingscene
			KX_ISceneConverter* sceneconverter = new KX_BlenderSceneConverter(blenderdata, ketsjiengine);
			ketsjiengine->SetSceneConverter(sceneconverter);
			sceneconverter->addInitFromFrame=false;
			if (always_use_expand_framing)
				sceneconverter->SetAlwaysUseExpandFraming(true);

			bool usemat = false, useglslmat = false;

			if(GLEW_ARB_multitexture && GLEW_VERSION_1_1)
				usemat = true;

			if(GPU_glsl_support())
				useglslmat = true;
			else if(gs.matmode == GAME_MAT_GLSL)
				usemat = false;

			if(usemat && (gs.matmode != GAME_MAT_TEXFACE))
				sceneconverter->SetMaterials(true);
			if(useglslmat && (gs.matmode == GAME_MAT_GLSL))
				sceneconverter->SetGLSLMaterials(true);
					
			KX_Scene* startscene = new KX_Scene(keyboarddevice,
				mousedevice,
				networkdevice,
				startscenename,
				scene,
				canvas);

#ifdef WITH_PYTHON
			// some python things
			PyObject *gameLogic, *gameLogic_keys;
			setupGamePython(ketsjiengine, startscene, blenderdata, pyGlobalDict, &gameLogic, &gameLogic_keys, 0, NULL);
#endif // WITH_PYTHON

			//initialize Dome Settings
			if(scene->gm.stereoflag == STEREO_DOME)
				ketsjiengine->InitDome(scene->gm.dome.res, scene->gm.dome.mode, scene->gm.dome.angle, scene->gm.dome.resbuf, scene->gm.dome.tilt, scene->gm.dome.warptext);

			// initialize 3D Audio Settings
			AUD_I3DDevice* dev = AUD_get3DDevice();
			if(dev)
			{
				dev->setSpeedOfSound(scene->audio.speed_of_sound);
				dev->setDopplerFactor(scene->audio.doppler_factor);
				dev->setDistanceModel(AUD_DistanceModel(scene->audio.distance_model));
			}

			// from see blender.c:
			// FIXME: this version patching should really be part of the file-reading code,
			// but we still get too many unrelated data-corruption crashes otherwise...
			if (blenderdata->versionfile < 250)
				do_versions_ipos_to_animato(blenderdata);

			if (sceneconverter)
			{
				// convert and add scene
				sceneconverter->ConvertScene(
					startscene,
					rendertools,
					canvas);
				ketsjiengine->AddScene(startscene);
				
				// init the rasterizer
				rasterizer->Init();
				
				// start the engine
				ketsjiengine->StartEngine(true);
				

				// Set the animation playback rate for ipo's and actions
				// the framerate below should patch with FPS macro defined in blendef.h
				// Could be in StartEngine set the framerate, we need the scene to do this
				ketsjiengine->SetAnimFrameRate(FPS);
				
				// the mainloop
				printf("\nBlender Game Engine Started\n");
				while (!exitrequested)
				{
					// first check if we want to exit
					exitrequested = ketsjiengine->GetExitCode();
					
					// kick the engine
					bool render = ketsjiengine->NextFrame();
					
					if (render)
					{
						if(draw_letterbox) {
							// Clear screen to border color
							// We do this here since we set the canvas to be within the frames. This means the engine
							// itself is unaware of the extra space, so we clear the whole region for it.
							glClearColor(scene->gm.framing.col[0], scene->gm.framing.col[1], scene->gm.framing.col[2], 1.0f);
							glViewport(ar->winrct.xmin, ar->winrct.ymin,
								ar->winrct.xmax - ar->winrct.xmin, ar->winrct.ymax - ar->winrct.ymin);
							glClear(GL_COLOR_BUFFER_BIT);
						}

						// render the frame
						ketsjiengine->Render();
					}
					
					wm_window_process_events_nosleep();
					
					// test for the ESC key
					//XXX while (qtest())
					while(wmEvent *event= (wmEvent *)win->queue.first)
					{
						short val = 0;
						//unsigned short event = 0; //XXX extern_qread(&val);
						
						if (keyboarddevice->ConvertBlenderEvent(event->type,event->val))
							exitrequested = KX_EXIT_REQUEST_BLENDER_ESC;
						
							/* Coordinate conversion... where
							* should this really be?
						*/
						if (event->type==MOUSEMOVE) {
							/* Note, not nice! XXX 2.5 event hack */
							val = event->x - ar->winrct.xmin;
							mousedevice->ConvertBlenderEvent(MOUSEX, val);
							
							val = ar->winy - (event->y - ar->winrct.ymin) - 1;
							mousedevice->ConvertBlenderEvent(MOUSEY, val);
						}
						else {
							mousedevice->ConvertBlenderEvent(event->type,event->val);
						}
						
						BLI_remlink(&win->queue, event);
						wm_event_free(event);
					}
					
					if(win != CTX_wm_window(C)) {
						exitrequested= KX_EXIT_REQUEST_OUTSIDE; /* window closed while bge runs */
					}
				}
				printf("Blender Game Engine Finished\n");
				exitstring = ketsjiengine->GetExitString();
				gs = *(ketsjiengine->GetGlobalSettings());


				// when exiting the mainloop
#ifdef WITH_PYTHON
				// Clears the dictionary by hand:
				// This prevents, extra references to global variables
				// inside the GameLogic dictionary when the python interpreter is finalized.
				// which allows the scene to safely delete them :)
				// see: (space.c)->start_game
				
				//PyDict_Clear(PyModule_GetDict(gameLogic));
				
				// Keep original items, means python plugins will autocomplete members
				PyObject *gameLogic_keys_new = PyDict_Keys(PyModule_GetDict(gameLogic));
				const Py_ssize_t numitems= PyList_GET_SIZE(gameLogic_keys_new);
				Py_ssize_t listIndex;
				for (listIndex=0; listIndex < numitems; listIndex++)  {
					PyObject* item = PyList_GET_ITEM(gameLogic_keys_new, listIndex);
					if (!PySequence_Contains(gameLogic_keys, item)) {
						PyDict_DelItem(	PyModule_GetDict(gameLogic), item);
					}
				}
				Py_DECREF(gameLogic_keys_new);
				gameLogic_keys_new = NULL;
#endif
				ketsjiengine->StopEngine();
#ifdef WITH_PYTHON
				exitGamePythonScripting();
#endif
				networkdevice->Disconnect();
			}
			if (sceneconverter)
			{
				delete sceneconverter;
				sceneconverter = NULL;
			}

#ifdef WITH_PYTHON
			Py_DECREF(gameLogic_keys);
			gameLogic_keys = NULL;
#endif
		}
		//lock frame and camera enabled - restoring global values
		if (v3d->scenelock==0){
			startscene->lay= tmp_lay;
			startscene->camera= tmp_camera;
		}

		if(exitrequested != KX_EXIT_REQUEST_OUTSIDE)
		{
			// set the cursor back to normal
			canvas->SetMouseState(RAS_ICanvas::MOUSE_NORMAL);
		}
		
		// clean up some stuff
		if (ketsjiengine)
		{
			delete ketsjiengine;
			ketsjiengine = NULL;
		}
		if (kxsystem)
		{
			delete kxsystem;
			kxsystem = NULL;
		}
		if (networkdevice)
		{
			delete networkdevice;
			networkdevice = NULL;
		}
		if (keyboarddevice)
		{
			delete keyboarddevice;
			keyboarddevice = NULL;
		}
		if (mousedevice)
		{
			delete mousedevice;
			mousedevice = NULL;
		}
		if (rasterizer)
		{
			delete rasterizer;
			rasterizer = NULL;
		}
		if (rendertools)
		{
			delete rendertools;
			rendertools = NULL;
		}
		if (canvas)
		{
			delete canvas;
			canvas = NULL;
		}

		// stop all remaining playing sounds
		AUD_getDevice()->stopAll();
	
	} while (exitrequested == KX_EXIT_REQUEST_RESTART_GAME || exitrequested == KX_EXIT_REQUEST_START_OTHER_GAME);
	
	if (!disableVBO)
		U.gameflags &= ~USER_DISABLE_VBO;

	if (bfd) BLO_blendfiledata_free(bfd);

	BLI_strncpy(G.main->name, oldsce, sizeof(G.main->name));

#ifdef WITH_PYTHON
	Py_DECREF(pyGlobalDict);

	// Release Python's GIL
	PyGILState_Release(gilstate);
#endif

}
Exemplo n.º 30
0
/* executes blocking blensor */
static int screen_blensor_exec(bContext *C, wmOperator *op)
{
	Scene *scene= CTX_data_scene(C);
	static Render *re=NULL;
	Image *ima;
	View3D *v3d= CTX_wm_view3d(C);
	Main *mainp= CTX_data_main(C);
	unsigned int lay= (v3d)? v3d->lay: scene->lay;
  float *rays;
  float *returns;
  char ray_ptr_str[17];
  char return_ptr_str[17];

    /* add modal handler for ESC */

	const int raycount= RNA_int_get(op->ptr, "raycount");
	const int elements_per_ray= RNA_int_get(op->ptr, "elements_per_ray");
	const int keep_render_setup = RNA_boolean_get(op->ptr, "keep_render_setup");
	const int shading = RNA_boolean_get(op->ptr, "shading");

	const float maximum_distance =RNA_float_get(op->ptr, "maximum_distance");
	struct Object *camera_override= v3d ? V3D_CAMERA_LOCAL(v3d) : NULL;

  RNA_string_get(op->ptr, "vector_strptr", ray_ptr_str);
  RNA_string_get(op->ptr, "return_vector_strptr", return_ptr_str);
  rays = (float *)convert_str_to_ptr(ray_ptr_str);
  returns = (float *)convert_str_to_ptr(return_ptr_str);
      
  if (raycount > 0)
  {
        
      printf ("Raycount: %d\n",raycount);
      
	    if(re==NULL) {
		    re = RE_NewRender(scene->id.name);
	    }
	
  
      G.is_break = FALSE;
	    //RE_test_break_cb(re, NULL, (int (*)(void *)) blender_test_break);

	    ima= BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result");
	    BKE_image_signal(ima, NULL, IMA_SIGNAL_FREE);
	    BKE_image_backup_render(scene, ima);

      /* 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();

      RE_SetReports(re, op->reports);

	    RE_BlensorFrame(re, mainp, scene, NULL, camera_override, lay, scene->r.cfra, 0, rays, raycount, elements_per_ray, returns, maximum_distance, keep_render_setup, shading);

    	RE_SetReports(re, NULL);

	    // no redraw needed, we leave state as we entered it
	    ED_update_for_newframe(mainp, scene, 1);

	    WM_event_add_notifier(C, NC_SCENE|ND_RENDER_RESULT, scene);
      if (keep_render_setup == 0)
      {
        re = NULL;
      }

  }
	return OPERATOR_FINISHED;
}