Beispiel #1
0
static void template_texture_user_menu(bContext *C, uiLayout *layout, void *UNUSED(arg))
{
	/* callback when opening texture user selection menu, to create buttons. */
	SpaceButs *sbuts = CTX_wm_space_buts(C);
	ButsContextTexture *ct= (sbuts)? sbuts->texuser: NULL;
	ButsTextureUser *user;
	uiBlock *block = uiLayoutGetBlock(layout);
	const char *last_category = NULL;

	for(user=ct->users.first; user; user=user->next) {
		uiBut *but;
		char name[UI_MAX_NAME_STR];

		/* add label per category */
		if(!last_category || strcmp(last_category, user->category) != 0) {
			uiItemL(layout, user->category, ICON_NONE);
			but= block->buttons.last;
			but->flag= UI_TEXT_LEFT;
		}

		/* create button */
		BLI_snprintf(name, UI_MAX_NAME_STR, "  %s", user->name);

		but = uiDefIconTextBut(block, BUT, 0, user->icon, name, 0, 0, UI_UNIT_X*4, UI_UNIT_Y,
			NULL, 0.0, 0.0, 0.0, 0.0, "");
		uiButSetNFunc(but, template_texture_select, MEM_dupallocN(user), NULL);

		last_category = user->category;
	}
}
static void ui_template_node_link_menu(bContext *C, uiLayout *layout, void *but_p)
{
	Main *bmain = CTX_data_main(C);
	Scene *scene = CTX_data_scene(C);
	uiBlock *block = uiLayoutGetBlock(layout);
	uiBut *but = (uiBut *)but_p;
	uiLayout *split, *column;
	NodeLinkArg *arg = (NodeLinkArg *)but->func_argN;
	bNodeSocket *sock = arg->sock;
	bNodeTreeType *ntreetype = arg->ntree->typeinfo;

	uiBlockSetFlag(block, UI_BLOCK_NO_FLIP);
	uiBlockSetCurLayout(block, layout);
	split = uiLayoutSplit(layout, 0.0f, false);

	arg->bmain = bmain;
	arg->scene = scene;
	arg->layout = split;

	if (ntreetype && ntreetype->foreach_nodeclass)
		ntreetype->foreach_nodeclass(scene, arg, node_menu_column_foreach_cb);

	column = uiLayoutColumn(split, false);
	uiBlockSetCurLayout(block, column);

	if (sock->link) {
		uiItemL(column, IFACE_("Link"), ICON_NONE);
		but = block->buttons.last;
		but->drawflag = UI_BUT_TEXT_LEFT;

		but = uiDefBut(block, BUT, 0, IFACE_("Remove"), 0, 0, UI_UNIT_X * 4, UI_UNIT_Y,
		               NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Remove nodes connected to the input"));
		uiButSetNFunc(but, ui_node_link, MEM_dupallocN(arg), SET_INT_IN_POINTER(UI_NODE_LINK_REMOVE));

		but = uiDefBut(block, BUT, 0, IFACE_("Disconnect"), 0, 0, UI_UNIT_X * 4, UI_UNIT_Y,
		               NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Disconnect nodes connected to the input"));
		uiButSetNFunc(but, ui_node_link, MEM_dupallocN(arg), SET_INT_IN_POINTER(UI_NODE_LINK_DISCONNECT));
	}

	ui_node_menu_column(arg, NODE_CLASS_GROUP, N_("Group"));
}
/* driver settings for active F-Curve (only for 'Drivers' mode) */
static void graph_panel_drivers(const bContext *C, Panel *pa)
{
	bAnimListElem *ale;
	FCurve *fcu;
	ChannelDriver *driver;
	DriverVar *dvar;
	
	PointerRNA driver_ptr;
	uiLayout *col;
	uiBlock *block;
	uiBut *but;
	
	/* Get settings from context */
	if (!graph_panel_context(C, &ale, &fcu))
		return;
	driver = fcu->driver;
	
	/* set event handler for panel */
	block = uiLayoutGetBlock(pa->layout); // xxx?
	uiBlockSetHandleFunc(block, do_graph_region_driver_buttons, NULL);
	
	/* general actions - management */
	col = uiLayoutColumn(pa->layout, FALSE);
	block = uiLayoutGetBlock(col);
	but = uiDefBut(block, BUT, B_IPO_DEPCHANGE, IFACE_("Update Dependencies"), 0, 0, 10 * UI_UNIT_X, 22,
	               NULL, 0.0, 0.0, 0, 0, TIP_("Force updates of dependencies"));
	uiButSetFunc(but, driver_update_flags_cb, fcu, NULL);

	but = uiDefBut(block, BUT, B_IPO_DEPCHANGE, IFACE_("Remove Driver"), 0, 0, 10 * UI_UNIT_X, 18,
	               NULL, 0.0, 0.0, 0, 0, TIP_("Remove this driver"));
	uiButSetNFunc(but, driver_remove_cb, MEM_dupallocN(ale), NULL);
		
	/* driver-level settings - type, expressions, and errors */
	RNA_pointer_create(ale->id, &RNA_Driver, driver, &driver_ptr);
	
	col = uiLayoutColumn(pa->layout, TRUE);
	block = uiLayoutGetBlock(col);
	uiItemR(col, &driver_ptr, "type", 0, NULL, ICON_NONE);

	/* show expression box if doing scripted drivers, and/or error messages when invalid drivers exist */
	if (driver->type == DRIVER_TYPE_PYTHON) {
		/* expression */
		uiItemR(col, &driver_ptr, "expression", 0, IFACE_("Expr"), ICON_NONE);

		/* errors? */
		if (driver->flag & DRIVER_FLAG_INVALID)
			uiItemL(col, IFACE_("ERROR: invalid Python expression"), ICON_ERROR);
	}
	else {
		/* errors? */
		if (driver->flag & DRIVER_FLAG_INVALID)
			uiItemL(col, IFACE_("ERROR: invalid target channel(s)"), ICON_ERROR);
	}
		
	col = uiLayoutColumn(pa->layout, TRUE);
	/* debug setting */
	uiItemR(col, &driver_ptr, "show_debug_info", 0, NULL, ICON_NONE);
		
	/* value of driver */
	if (driver->flag & DRIVER_FLAG_SHOWDEBUG) {
		uiLayout *row = uiLayoutRow(col, TRUE);
		char valBuf[32];
			
		uiItemL(row, IFACE_("Driver Value:"), ICON_NONE);
			
		BLI_snprintf(valBuf, sizeof(valBuf), "%.3f", driver->curval);
		uiItemL(row, valBuf, ICON_NONE);
	}
	
	/* add driver variables */
	col = uiLayoutColumn(pa->layout, FALSE);
	block = uiLayoutGetBlock(col);
	but = uiDefBut(block, BUT, B_IPO_DEPCHANGE, IFACE_("Add Variable"), 0, 0, 10 * UI_UNIT_X, UI_UNIT_Y,
	               NULL, 0.0, 0.0, 0, 0, TIP_("Add a new target variable for this Driver"));
	uiButSetFunc(but, driver_add_var_cb, driver, NULL);
	
	/* loop over targets, drawing them */
	for (dvar = driver->variables.first; dvar; dvar = dvar->next) {
		PointerRNA dvar_ptr;
		uiLayout *box, *row;
		
		/* sub-layout column for this variable's settings */
		col = uiLayoutColumn(pa->layout, TRUE);
		
		/* header panel */
		box = uiLayoutBox(col);
		/* first row context info for driver */
		RNA_pointer_create(ale->id, &RNA_DriverVariable, dvar, &dvar_ptr);

		row = uiLayoutRow(box, FALSE);
		block = uiLayoutGetBlock(row);
		/* variable name */
		uiItemR(row, &dvar_ptr, "name", 0, "", ICON_NONE);

		/* remove button */
		uiBlockSetEmboss(block, UI_EMBOSSN);
		but = uiDefIconBut(block, BUT, B_IPO_DEPCHANGE, ICON_X, 290, 0, UI_UNIT_X, UI_UNIT_Y,
		                   NULL, 0.0, 0.0, 0.0, 0.0, IFACE_("Delete target variable"));
		uiButSetFunc(but, driver_delete_var_cb, driver, dvar);
		uiBlockSetEmboss(block, UI_EMBOSS);

		/* variable type */
		row = uiLayoutRow(box, FALSE);
		uiItemR(row, &dvar_ptr, "type", 0, "", ICON_NONE);
				
		/* variable type settings */
		box = uiLayoutBox(col);
		/* controls to draw depends on the type of variable */
		switch (dvar->type) {
			case DVAR_TYPE_SINGLE_PROP:     /* single property */
				graph_panel_driverVar__singleProp(box, ale->id, dvar);
				break;
			case DVAR_TYPE_ROT_DIFF:     /* rotational difference */
				graph_panel_driverVar__rotDiff(box, ale->id, dvar);
				break;
			case DVAR_TYPE_LOC_DIFF:     /* location difference */
				graph_panel_driverVar__locDiff(box, ale->id, dvar);
				break;
			case DVAR_TYPE_TRANSFORM_CHAN:     /* transform channel */
				graph_panel_driverVar__transChan(box, ale->id, dvar);
				break;
		}

		/* value of variable */
		if (driver->flag & DRIVER_FLAG_SHOWDEBUG) {
			char valBuf[32];

			box = uiLayoutBox(col);
			row = uiLayoutRow(box, TRUE);
			uiItemL(row, IFACE_("Value:"), ICON_NONE);

			BLI_snprintf(valBuf, sizeof(valBuf), "%.3f", dvar->curval);
			uiItemL(row, valBuf, ICON_NONE);
		}
	}
	
	/* cleanup */
	MEM_freeN(ale);
}
/* driver settings for active F-Curve (only for 'Drivers' mode) */
static void graph_panel_drivers(const bContext *C, Panel *pa)
{
	bAnimListElem *ale;
	FCurve *fcu;
	ChannelDriver *driver;
	DriverVar *dvar;
	
	PointerRNA driver_ptr;
	uiLayout *col;
	uiBlock *block;
	uiBut *but;
	
	/* Get settings from context */
	if (!graph_panel_context(C, &ale, &fcu))
		return;
	driver = fcu->driver;
	
	/* set event handler for panel */
	block = uiLayoutGetBlock(pa->layout); // xxx?
	uiBlockSetHandleFunc(block, do_graph_region_driver_buttons, NULL);
	
	/* general actions - management */
	col = uiLayoutColumn(pa->layout, false);
	block = uiLayoutGetBlock(col);
	but = uiDefIconTextBut(block, BUT, B_IPO_DEPCHANGE, ICON_FILE_REFRESH, IFACE_("Update Dependencies"),
	               0, 0, 10 * UI_UNIT_X, 22,
	               NULL, 0.0, 0.0, 0, 0,
	               TIP_("Force updates of dependencies"));
	uiButSetFunc(but, driver_update_flags_cb, fcu, NULL);

	but = uiDefIconTextBut(block, BUT, B_IPO_DEPCHANGE, ICON_ZOOMOUT, IFACE_("Remove Driver"),
	               0, 0, 10 * UI_UNIT_X, 18,
	               NULL, 0.0, 0.0, 0, 0,
	               TIP_("Remove this driver"));
	uiButSetNFunc(but, driver_remove_cb, MEM_dupallocN(ale), NULL);
		
	/* driver-level settings - type, expressions, and errors */
	RNA_pointer_create(ale->id, &RNA_Driver, driver, &driver_ptr);
	
	col = uiLayoutColumn(pa->layout, true);
	block = uiLayoutGetBlock(col);
	uiItemR(col, &driver_ptr, "type", 0, NULL, ICON_NONE);

	/* show expression box if doing scripted drivers, and/or error messages when invalid drivers exist */
	if (driver->type == DRIVER_TYPE_PYTHON) {
		bool bpy_data_expr_error = (strstr(driver->expression, "bpy.data.") != NULL);
		bool bpy_ctx_expr_error  = (strstr(driver->expression, "bpy.context.") != NULL);
		
		/* expression */
		uiItemR(col, &driver_ptr, "expression", 0, IFACE_("Expr"), ICON_NONE);
		
		/* errors? */
		if ((G.f & G_SCRIPT_AUTOEXEC) == 0) {
			uiItemL(col, IFACE_("ERROR: Python auto-execution disabled"), ICON_CANCEL);
		}
		else if (driver->flag & DRIVER_FLAG_INVALID) {
			uiItemL(col, IFACE_("ERROR: Invalid Python expression"), ICON_CANCEL);
		}
		
		/* Explicit bpy-references are evil. Warn about these to prevent errors */
		/* TODO: put these in a box? */
		if (bpy_data_expr_error || bpy_ctx_expr_error) {
			uiItemL(col, IFACE_("WARNING: Driver expression may not work correctly"), ICON_HELP);
			
			if (bpy_data_expr_error) {
				uiItemL(col, IFACE_("TIP: Use variables instead of bpy.data paths (see below)"), ICON_ERROR);
			}
			if (bpy_ctx_expr_error) {
				uiItemL(col, IFACE_("TIP: bpy.context is not safe for renderfarm usage"), ICON_ERROR);
			}
		}
	}
	else {
		/* errors? */
		if (driver->flag & DRIVER_FLAG_INVALID)
			uiItemL(col, IFACE_("ERROR: Invalid target channel(s)"), ICON_ERROR);
			
		/* Warnings about a lack of variables
		 * NOTE: The lack of variables is generally a bad thing, since it indicates
		 *       that the driver doesn't work at all. This particular scenario arises
		 *       primarily when users mistakenly try to use drivers for procedural
		 *       property animation
		 */
		if (BLI_listbase_is_empty(&driver->variables)) {
			uiItemL(col, IFACE_("ERROR: Driver is useless without any inputs"), ICON_ERROR);
			
			if (!BLI_listbase_is_empty(&fcu->modifiers)) {
				uiItemL(col, IFACE_("TIP: Use F-Curves for procedural animation instead"), ICON_INFO);
				uiItemL(col, IFACE_("F-Modifiers can generate curves for those too"), ICON_INFO);
			}
		}
	}
		
	col = uiLayoutColumn(pa->layout, true);
	/* debug setting */
	uiItemR(col, &driver_ptr, "show_debug_info", 0, NULL, ICON_NONE);
		
	/* value of driver */
	if (driver->flag & DRIVER_FLAG_SHOWDEBUG) {
		uiLayout *row = uiLayoutRow(col, true);
		char valBuf[32];
			
		uiItemL(row, IFACE_("Driver Value:"), ICON_NONE);
			
		BLI_snprintf(valBuf, sizeof(valBuf), "%.3f", driver->curval);
		uiItemL(row, valBuf, ICON_NONE);
	}
	
	/* add driver variables */
	col = uiLayoutColumn(pa->layout, false);
	block = uiLayoutGetBlock(col);
	but = uiDefIconTextBut(block, BUT, B_IPO_DEPCHANGE, ICON_ZOOMIN, IFACE_("Add Variable"),
	               0, 0, 10 * UI_UNIT_X, UI_UNIT_Y,
	               NULL, 0.0, 0.0, 0, 0,
	               TIP_("Driver variables ensure that all dependencies will be accounted for and that drivers will update correctly"));
	uiButSetFunc(but, driver_add_var_cb, driver, NULL);
	
	/* loop over targets, drawing them */
	for (dvar = driver->variables.first; dvar; dvar = dvar->next) {
		PointerRNA dvar_ptr;
		uiLayout *box, *row;
		
		/* sub-layout column for this variable's settings */
		col = uiLayoutColumn(pa->layout, true);
		
		/* header panel */
		box = uiLayoutBox(col);
		/* first row context info for driver */
		RNA_pointer_create(ale->id, &RNA_DriverVariable, dvar, &dvar_ptr);
		
		row = uiLayoutRow(box, false);
		block = uiLayoutGetBlock(row);
		/* variable name */
		uiItemR(row, &dvar_ptr, "name", 0, "", ICON_NONE);
		
		/* remove button */
		uiBlockSetEmboss(block, UI_EMBOSSN);
		but = uiDefIconBut(block, BUT, B_IPO_DEPCHANGE, ICON_X, 290, 0, UI_UNIT_X, UI_UNIT_Y,
		                   NULL, 0.0, 0.0, 0.0, 0.0, IFACE_("Delete target variable"));
		uiButSetFunc(but, driver_delete_var_cb, driver, dvar);
		uiBlockSetEmboss(block, UI_EMBOSS);
		
		/* variable type */
		row = uiLayoutRow(box, false);
		uiItemR(row, &dvar_ptr, "type", 0, "", ICON_NONE);
				
		/* variable type settings */
		box = uiLayoutBox(col);
		/* controls to draw depends on the type of variable */
		switch (dvar->type) {
			case DVAR_TYPE_SINGLE_PROP:     /* single property */
				graph_panel_driverVar__singleProp(box, ale->id, dvar);
				break;
			case DVAR_TYPE_ROT_DIFF:     /* rotational difference */
				graph_panel_driverVar__rotDiff(box, ale->id, dvar);
				break;
			case DVAR_TYPE_LOC_DIFF:     /* location difference */
				graph_panel_driverVar__locDiff(box, ale->id, dvar);
				break;
			case DVAR_TYPE_TRANSFORM_CHAN:     /* transform channel */
				graph_panel_driverVar__transChan(box, ale->id, dvar);
				break;
		}
		
		/* value of variable */
		if (driver->flag & DRIVER_FLAG_SHOWDEBUG) {
			char valBuf[32];
			
			box = uiLayoutBox(col);
			row = uiLayoutRow(box, true);
			uiItemL(row, IFACE_("Value:"), ICON_NONE);
			
			if ((dvar->type == DVAR_TYPE_ROT_DIFF) ||
			    (dvar->type == DVAR_TYPE_TRANSFORM_CHAN &&
			     dvar->targets[0].transChan >= DTAR_TRANSCHAN_ROTX &&
			     dvar->targets[0].transChan < DTAR_TRANSCHAN_SCALEX))
			{
				BLI_snprintf(valBuf, sizeof(valBuf), "%.3f (%4.1f°)", dvar->curval, RAD2DEGF(dvar->curval));
			}
			else {
				BLI_snprintf(valBuf, sizeof(valBuf), "%.3f", dvar->curval);
			}
			
			uiItemL(row, valBuf, ICON_NONE);
		}
	}
	
	/* cleanup */
	MEM_freeN(ale);
}
Beispiel #5
0
void uiTemplateMarker(uiLayout *layout, PointerRNA *ptr, const char *propname, PointerRNA *userptr,
                      PointerRNA *trackptr, int compact)
{
	PropertyRNA *prop;
	uiBlock *block;
	uiBut *bt;
	PointerRNA clipptr;
	MovieClip *clip;
	MovieClipUser *user;
	MovieTrackingTrack *track;
	MovieTrackingMarker *marker;
	MarkerUpdateCb *cb;
	const char *tip;
	float pat_min[2], pat_max[2];

	if (!ptr->data)
		return;

	prop = RNA_struct_find_property(ptr, propname);
	if (!prop) {
		printf("%s: property not found: %s.%s\n",
		       __func__, RNA_struct_identifier(ptr->type), propname);
		return;
	}

	if (RNA_property_type(prop) != PROP_POINTER) {
		printf("%s: expected pointer property for %s.%s\n",
		       __func__, RNA_struct_identifier(ptr->type), propname);
		return;
	}

	clipptr = RNA_property_pointer_get(ptr, prop);
	clip = (MovieClip *)clipptr.data;
	user = userptr->data;
	track = trackptr->data;

	marker = BKE_tracking_marker_get(track, user->framenr);

	cb = MEM_callocN(sizeof(MarkerUpdateCb), "uiTemplateMarker update_cb");
	cb->compact = compact;
	cb->clip = clip;
	cb->user = user;
	cb->track = track;
	cb->marker = marker;
	cb->marker_flag = marker->flag;
	cb->framenr = user->framenr;

	if (compact) {
		block = uiLayoutGetBlock(layout);

		if (cb->marker_flag & MARKER_DISABLED)
			tip = "Marker is disabled at current frame";
		else
			tip = "Marker is enabled at current frame";

		bt = uiDefIconButBitI(block, TOGN, MARKER_DISABLED, 0, ICON_RESTRICT_VIEW_OFF, 0, 0, 20, 20,
		                      &cb->marker_flag, 0, 0, 1, 0, tip);
		uiButSetNFunc(bt, marker_update_cb, cb, NULL);
	}
	else {
		int width, height, step, digits;
		float pat_dim[2], search_dim[2], search_pos[2];
		uiLayout *col;

		BKE_movieclip_get_size(clip, user, &width, &height);

		if (track->flag & TRACK_LOCKED) {
			uiLayoutSetActive(layout, FALSE);
			block = uiLayoutAbsoluteBlock(layout);
			uiDefBut(block, LABEL, 0, "Track is locked", 0, 0, 300, 19, NULL, 0, 0, 0, 0, "");

			return;
		}

		step = 100;
		digits = 2;

		BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max);

		sub_v2_v2v2(pat_dim, pat_max, pat_min);
		sub_v2_v2v2(search_dim, marker->search_max, marker->search_min);

		add_v2_v2v2(search_pos, marker->search_max, marker->search_min);
		mul_v2_fl(search_pos, 0.5);

		to_pixel_space(cb->marker_pos, marker->pos, width, height);
		to_pixel_space(cb->marker_pat, pat_dim, width, height);
		to_pixel_space(cb->marker_search, search_dim, width, height);
		to_pixel_space(cb->marker_search_pos, search_pos, width, height);
		to_pixel_space(cb->track_offset, track->offset, width, height);

		cb->marker_flag = marker->flag;

		block = uiLayoutAbsoluteBlock(layout);
		uiBlockSetHandleFunc(block, marker_block_handler, cb);
		uiBlockSetNFunc(block, marker_update_cb, cb, NULL);

		if (cb->marker_flag & MARKER_DISABLED)
			tip = "Marker is disabled at current frame";
		else
			tip = "Marker is enabled at current frame";

		uiDefButBitI(block, OPTIONN, MARKER_DISABLED, B_MARKER_FLAG,  "Enabled", 10, 190, 145, 19, &cb->marker_flag,
		             0, 0, 0, 0, tip);

		col = uiLayoutColumn(layout, TRUE);
		uiLayoutSetActive(col, (cb->marker_flag & MARKER_DISABLED) == 0);

		block = uiLayoutAbsoluteBlock(col);
		uiBlockBeginAlign(block);

		uiDefBut(block, LABEL, 0, "Position:", 0, 190, 300, 19, NULL, 0, 0, 0, 0, "");
		uiDefButF(block, NUM, B_MARKER_POS, "X:", 10, 171, 145, 19, &cb->marker_pos[0],
		          -10 * width, 10.0 * width, step, digits, "X-position of marker at frame in screen coordinates");
		uiDefButF(block, NUM, B_MARKER_POS, "Y:", 165, 171, 145, 19, &cb->marker_pos[1],
		          -10 * height, 10.0 * height, step, digits, "Y-position of marker at frame in screen coordinates");

		uiDefBut(block, LABEL, 0, "Offset:", 0, 152, 300, 19, NULL, 0, 0, 0, 0, "");
		uiDefButF(block, NUM, B_MARKER_OFFSET, "X:", 10, 133, 145, 19, &cb->track_offset[0],
		          -10 * width, 10.0 * width, step, digits, "X-offset to parenting point");
		uiDefButF(block, NUM, B_MARKER_OFFSET, "Y:", 165, 133, 145, 19, &cb->track_offset[1],
		          -10 * height, 10.0 * height, step, digits, "Y-offset to parenting point");

		uiDefBut(block, LABEL, 0, "Pattern Area:", 0, 114, 300, 19, NULL, 0, 0, 0, 0, "");
		uiDefButF(block, NUM, B_MARKER_PAT_DIM, "Width:", 10, 95, 300, 19, &cb->marker_pat[0], 3.0f,
		          10.0 * width, step, digits, "Width of marker's pattern in screen coordinates");
		uiDefButF(block, NUM, B_MARKER_PAT_DIM, "Height:", 10, 76, 300, 19, &cb->marker_pat[1], 3.0f,
		          10.0 * height, step, digits, "Height of marker's pattern in screen coordinates");

		uiDefBut(block, LABEL, 0, "Search Area:", 0, 57, 300, 19, NULL, 0, 0, 0, 0, "");
		uiDefButF(block, NUM, B_MARKER_SEARCH_POS, "X:", 10, 38, 145, 19, &cb->marker_search_pos[0],
		          -width, width, step, digits, "X-position of search at frame relative to marker's position");
		uiDefButF(block, NUM, B_MARKER_SEARCH_POS, "Y:", 165, 38, 145, 19, &cb->marker_search_pos[1],
		          -height, height, step, digits, "X-position of search at frame relative to marker's position");
		uiDefButF(block, NUM, B_MARKER_SEARCH_DIM, "Width:", 10, 19, 300, 19, &cb->marker_search[0], 3.0f,
		          10.0 * width, step, digits, "Width of marker's search in screen soordinates");
		uiDefButF(block, NUM, B_MARKER_SEARCH_DIM, "Height:", 10, 0, 300, 19, &cb->marker_search[1], 3.0f,
		          10.0 * height, step, digits, "Height of marker's search in screen soordinates");

		uiBlockEndAlign(block);
	}
}
/* Note: This function uses pixelspace (0, 0, winx, winy), not view2d. 
 * The controls are laid out as follows:
 *
 * -------------------------------------------
 * | Directory input               | execute |
 * -------------------------------------------
 * | Filename input        | + | - | cancel  |
 * -------------------------------------------
 *
 * The input widgets will stretch to fill any excess space.
 * When there isn't enough space for all controls to be shown, they are
 * hidden in this order: x/-, execute/cancel, input widgets.
 */
void file_draw_buttons(const bContext *C, ARegion *ar)
{
	/* Button layout. */
	const int max_x      = ar->winx - 10;
	const int line1_y    = ar->winy - (IMASEL_BUTTONS_HEIGHT / 2 + IMASEL_BUTTONS_MARGIN);
	const int line2_y    = line1_y - (IMASEL_BUTTONS_HEIGHT / 2 + IMASEL_BUTTONS_MARGIN);
	const int input_minw = 20;
	const int btn_h      = UI_UNIT_Y;
	const int btn_fn_w   = UI_UNIT_X;
	const int btn_minw   = 80;
	const int btn_margin = 20;
	const int separator  = 4;

	/* Additional locals. */
	char uiblockstr[32];
	int loadbutton;
	int fnumbuttons;
	int min_x       = 10;
	int chan_offs   = 0;
	int available_w = max_x - min_x;
	int line1_w     = available_w;
	int line2_w     = available_w;
	
	uiBut *but;
	uiBlock *block;
	SpaceFile *sfile  = CTX_wm_space_file(C);
	FileSelectParams *params = ED_fileselect_get_params(sfile);
	ARegion *artmp;
	
	/* Initialize UI block. */
	BLI_snprintf(uiblockstr, sizeof(uiblockstr), "win %p", (void *)ar);
	block = uiBeginBlock(C, ar, uiblockstr, UI_EMBOSS);

	/* exception to make space for collapsed region icon */
	for (artmp = CTX_wm_area(C)->regionbase.first; artmp; artmp = artmp->next) {
		if (artmp->regiontype == RGN_TYPE_CHANNELS && artmp->flag & RGN_FLAG_HIDDEN) {
			chan_offs = 16;
			min_x += chan_offs;
			available_w -= chan_offs;
		}
	}
	
	/* Is there enough space for the execute / cancel buttons? */
	loadbutton = UI_GetStringWidth(sfile->params->title) + btn_margin;
	if (loadbutton < btn_minw) {
		loadbutton = MAX2(btn_minw, 
		                  btn_margin + UI_GetStringWidth(params->title));
	}
	
	if (available_w <= loadbutton + separator + input_minw || params->title[0] == 0) {
		loadbutton = 0;
	}
	else {
		line1_w -= (loadbutton + separator);
		line2_w  = line1_w;
	}

	/* Is there enough space for file number increment/decrement buttons? */
	fnumbuttons = 2 * btn_fn_w;
	if (!loadbutton || line2_w <= fnumbuttons + separator + input_minw) {
		fnumbuttons = 0;
	}
	else {
		line2_w -= (fnumbuttons + separator);
	}
	
	/* Text input fields for directory and file. */
	if (available_w > 0) {
		int overwrite_alert = file_draw_check_exists(sfile);
		/* callbacks for operator check functions */
		uiBlockSetFunc(block, file_draw_check_cb, NULL, NULL);

		but = uiDefBut(block, TEX, -1, "",
		               min_x, line1_y, line1_w - chan_offs, btn_h,
		               params->dir, 0.0, (float)FILE_MAX, 0, 0,
		               TIP_("File path"));
		uiButSetCompleteFunc(but, autocomplete_directory, NULL);
		uiButSetFlag(but, UI_BUT_NO_UTF8);
		uiButClearFlag(but, UI_BUT_UNDO);
		uiButSetNFunc(but, file_directory_enter_handle, NULL, but);

		/* TODO, directory editing is non-functional while a library is loaded
		 * until this is properly supported just disable it. */
		if (sfile->files && filelist_lib(sfile->files))
			uiButSetFlag(but, UI_BUT_DISABLED);

		if ((params->flag & FILE_DIRSEL_ONLY) == 0) {
			but = uiDefBut(block, TEX, -1, "",
			               min_x, line2_y, line2_w - chan_offs, btn_h,
			               params->file, 0.0, (float)FILE_MAXFILE, 0, 0,
			               TIP_(overwrite_alert ? N_("File name, overwrite existing") : N_("File name")));
			uiButSetCompleteFunc(but, autocomplete_file, NULL);
			uiButSetFlag(but, UI_BUT_NO_UTF8);
			uiButClearFlag(but, UI_BUT_UNDO);
			/* silly workaround calling NFunc to ensure this does not get called
			 * immediate ui_apply_but_func but only after button deactivates */
			uiButSetNFunc(but, file_filename_enter_handle, NULL, but);

			/* check if this overrides a file and if the operator option is used */
			if (overwrite_alert) {
				uiButSetFlag(but, UI_BUT_REDALERT);
			}
		}
		
		/* clear func */
		uiBlockSetFunc(block, NULL, NULL, NULL);
	}
	
	/* Filename number increment / decrement buttons. */
	if (fnumbuttons && (params->flag & FILE_DIRSEL_ONLY) == 0) {
		uiBlockBeginAlign(block);
		but = uiDefIconButO(block, BUT, "FILE_OT_filenum", 0, ICON_ZOOMOUT,
		                    min_x + line2_w + separator - chan_offs, line2_y,
		                    btn_fn_w, btn_h,
		                    TIP_("Decrement the filename number"));
		RNA_int_set(uiButGetOperatorPtrRNA(but), "increment", -1);

		but = uiDefIconButO(block, BUT, "FILE_OT_filenum", 0, ICON_ZOOMIN,
		                    min_x + line2_w + separator + btn_fn_w - chan_offs, line2_y,
		                    btn_fn_w, btn_h,
		                    TIP_("Increment the filename number"));
		RNA_int_set(uiButGetOperatorPtrRNA(but), "increment", 1);
		uiBlockEndAlign(block);
	}
	
	/* Execute / cancel buttons. */
	if (loadbutton) {
		/* params->title is already translated! */
		uiDefButO(block, BUT, "FILE_OT_execute", WM_OP_EXEC_REGION_WIN, params->title,
		          max_x - loadbutton, line1_y, loadbutton, btn_h, "");
		uiDefButO(block, BUT, "FILE_OT_cancel", WM_OP_EXEC_REGION_WIN, IFACE_("Cancel"),
		          max_x - loadbutton, line2_y, loadbutton, btn_h, "");
	}
	
	uiEndBlock(C, block);
	uiDrawBlock(C, block);
}
static void ui_node_menu_column(NodeLinkArg *arg, int nclass, const char *cname)
{
	bNodeTree *ntree = arg->ntree;
	bNodeSocket *sock = arg->sock;
	uiLayout *layout = arg->layout;
	uiLayout *column = NULL;
	uiBlock *block = uiLayoutGetBlock(layout);
	uiBut *but;
	NodeLinkArg *argN;
	int first = 1;
	int compatibility = 0;
	
	if (ntree->type == NTREE_SHADER) {
		if (BKE_scene_use_new_shading_nodes(arg->scene))
			compatibility = NODE_NEW_SHADING;
		else
			compatibility = NODE_OLD_SHADING;
	}

	NODE_TYPES_BEGIN(ntype) {
		NodeLinkItem *items;
		int totitems;
		char name[UI_MAX_NAME_STR];
		const char *cur_node_name = NULL;
		int i, num = 0;
		int icon = ICON_NONE;
		
		if (compatibility && !(ntype->compatibility & compatibility))
			continue;
		
		if (ntype->nclass != nclass)
			continue;
		
		arg->node_type = ntype;
		
		ui_node_link_items(arg, SOCK_OUT, &items, &totitems);
		
		for (i = 0; i < totitems; ++i)
			if (ui_compatible_sockets(items[i].socket_type, sock->type))
				num++;
		
		for (i = 0; i < totitems; ++i) {
			if (!ui_compatible_sockets(items[i].socket_type, sock->type))
				continue;
			
			if (first) {
				column = uiLayoutColumn(layout, 0);
				uiBlockSetCurLayout(block, column);
				
				uiItemL(column, IFACE_(cname), ICON_NODE);
				but = block->buttons.last;
				
				first = 0;
			}
			
			if (num > 1) {
				if (!cur_node_name || !STREQ(cur_node_name, items[i].node_name)) {
					cur_node_name = items[i].node_name;
					/* XXX Do not use uiItemL here, it would add an empty icon as we are in a menu! */
					uiDefBut(block, LABEL, 0, IFACE_(cur_node_name), 0, 0, UI_UNIT_X * 4, UI_UNIT_Y,
					         NULL, 0.0, 0.0, 0.0, 0.0, "");
				}

				BLI_snprintf(name, UI_MAX_NAME_STR, "%s", IFACE_(items[i].socket_name));
				icon = ICON_BLANK1;
			}
			else {
				BLI_strncpy(name, IFACE_(items[i].node_name), UI_MAX_NAME_STR);
				icon = ICON_NONE;
			}
			
			but = uiDefIconTextBut(block, BUT, 0, icon, name, 0, 0, UI_UNIT_X * 4, UI_UNIT_Y,
			                       NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Add node to input"));
			
			argN = MEM_dupallocN(arg);
			argN->item = items[i];
			uiButSetNFunc(but, ui_node_link, argN, NULL);
		}
		
		if (items)
			MEM_freeN(items);
	}
	NODE_TYPES_END
}
Beispiel #8
0
static void ui_node_menu_column(NodeLinkArg *arg, int nclass, const char *cname)
{
	Main *bmain = arg->bmain;
	bNodeTree *ntree = arg->ntree;
	bNodeSocket *sock = arg->sock;
	uiLayout *layout = arg->layout;
	uiLayout *column = NULL;
	uiBlock *block = uiLayoutGetBlock(layout);
	uiBut *but;
	bNodeType *ntype;
	bNodeTree *ngroup;
	NodeLinkArg *argN;
	int first = 1;
	int compatibility= 0;

	if (ntree->type == NTREE_SHADER) {
		if (BKE_scene_use_new_shading_nodes(arg->scene))
			compatibility= NODE_NEW_SHADING;
		else
			compatibility= NODE_OLD_SHADING;
	}

	if (nclass == NODE_CLASS_GROUP) {
		for (ngroup=bmain->nodetree.first; ngroup; ngroup=ngroup->id.next) {
			bNodeSocket *gsock;
			char name[UI_MAX_NAME_STR];
			int i, j, num = 0;

			if (ngroup->type != ntree->type)
				continue;

			for (gsock=ngroup->inputs.first; gsock; gsock=gsock->next)
				if (ui_compatible_sockets(gsock->type, sock->type))
					num++;

			for (i=0, j=0, gsock=ngroup->outputs.first; gsock; gsock=gsock->next, i++) {
				if (!ui_compatible_sockets(gsock->type, sock->type))
					continue;

				if (first) {
					column= uiLayoutColumn(layout, 0);
					uiBlockSetCurLayout(block, column);

					uiItemL(column, cname, ICON_NODE);
					but= block->buttons.last;
					but->flag= UI_TEXT_LEFT;

					first = 0;
				}

				if (num > 1) {
					if (j == 0) {
						uiItemL(column, ngroup->id.name+2, ICON_NODE);
						but= block->buttons.last;
						but->flag= UI_TEXT_LEFT;
					}

					BLI_snprintf(name, UI_MAX_NAME_STR, "  %s", gsock->name);
					j++;
				}
				else
					BLI_strncpy(name, ngroup->id.name+2, UI_MAX_NAME_STR);

				but = uiDefBut(block, BUT, 0, ngroup->id.name+2, 0, 0, UI_UNIT_X*4, UI_UNIT_Y,
					NULL, 0.0, 0.0, 0.0, 0.0, "Add node to input");

				argN = MEM_dupallocN(arg);
				argN->type = NODE_GROUP;
				argN->ngroup = ngroup;
				argN->output = i;
				uiButSetNFunc(but, ui_node_link, argN, NULL);
			}
		}
	}
	else {
		bNodeTreeType *ttype= ntreeGetType(ntree->type);

		for (ntype=ttype->node_types.first; ntype; ntype=ntype->next) {
			bNodeSocketTemplate *stemp;
			char name[UI_MAX_NAME_STR];
			int i, j, num = 0;

			if (compatibility && !(ntype->compatibility & compatibility))
				continue;

			if (ntype->nclass != nclass)
				continue;

			for (i=0, stemp=ntype->outputs; stemp && stemp->type != -1; stemp++, i++)
				if (ui_compatible_sockets(stemp->type, sock->type))
					num++;

			for (i=0, j=0, stemp=ntype->outputs; stemp && stemp->type != -1; stemp++, i++) {
				if (!ui_compatible_sockets(stemp->type, sock->type))
					continue;

				if (first) {
					column= uiLayoutColumn(layout, 0);
					uiBlockSetCurLayout(block, column);

					uiItemL(column, cname, ICON_NODE);
					but= block->buttons.last;
					but->flag= UI_TEXT_LEFT;

					first = 0;
				}

				if (num > 1) {
					if (j == 0) {
						uiItemL(column, ntype->name, ICON_NODE);
						but= block->buttons.last;
						but->flag= UI_TEXT_LEFT;
					}

					BLI_snprintf(name, UI_MAX_NAME_STR, "  %s", stemp->name);
					j++;
				}
				else
					BLI_strncpy(name, ntype->name, UI_MAX_NAME_STR);

				but = uiDefBut(block, BUT, 0, name, 0, 0, UI_UNIT_X*4, UI_UNIT_Y,
					NULL, 0.0, 0.0, 0.0, 0.0, "Add node to input");

				argN = MEM_dupallocN(arg);
				argN->type = ntype->type;
				argN->output = i;
				uiButSetNFunc(but, ui_node_link, argN, NULL);
			}
		}
	}
}