예제 #1
0
static int validate_array(PyObject *rvalue, PointerRNA *ptr, PropertyRNA *prop,
                          int lvalue_dim, ItemTypeCheckFunc check_item_type, const char *item_type_str, int *totitem,
                          const char *error_prefix)
{
	int dimsize[MAX_ARRAY_DIMENSION];
	int totdim = RNA_property_array_dimension(ptr, prop, dimsize);

	/* validate type first because length validation may modify property array length */


#ifdef USE_MATHUTILS
	if (lvalue_dim == 0) { /* only valid for first level array */
		if (MatrixObject_Check(rvalue)) {
			MatrixObject *pymat = (MatrixObject *)rvalue;

			if (BaseMath_ReadCallback(pymat) == -1)
				return -1;

			if (RNA_property_type(prop) != PROP_FLOAT) {
				PyErr_Format(PyExc_ValueError, "%s %.200s.%.200s, matrix assign to non float array",
				             error_prefix, RNA_struct_identifier(ptr->type), RNA_property_identifier(prop));
				return -1;
			}
			else if (totdim != 2) {
				PyErr_Format(PyExc_ValueError, "%s %.200s.%.200s, matrix assign array with %d dimensions",
				             error_prefix, RNA_struct_identifier(ptr->type), RNA_property_identifier(prop), totdim);
				return -1;
			}
			else if (pymat->num_col != dimsize[0] || pymat->num_row != dimsize[1]) {
				PyErr_Format(PyExc_ValueError, "%s %.200s.%.200s, matrix assign dimension size mismatch, "
				             "is %dx%d, expected be %dx%d",
				             error_prefix, RNA_struct_identifier(ptr->type), RNA_property_identifier(prop),
				             pymat->num_col, pymat->num_row, dimsize[0], dimsize[1]);
				return -1;
			}
			else {
				*totitem = dimsize[0] * dimsize[1];
				return 0;
			}
		}
	}
#endif /* USE_MATHUTILS */


	{
		if (validate_array_type(rvalue, lvalue_dim, totdim, dimsize, check_item_type, item_type_str, error_prefix) == -1)
			return -1;

		return validate_array_length(rvalue, ptr, prop, lvalue_dim, totitem, error_prefix);
	}
}
예제 #2
0
static int file_panel_check_prop(PropertyRNA *prop)
{
	const char *prop_id= RNA_property_identifier(prop);
	return !(	strcmp(prop_id, "filepath") == 0 ||
				strcmp(prop_id, "directory") == 0 ||
				strcmp(prop_id, "filename") == 0
	);
}
예제 #3
0
static bool file_panel_check_prop(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
{
	const char *prop_id = RNA_property_identifier(prop);
	return !(STREQ(prop_id, "filepath") ||
	         STREQ(prop_id, "directory") ||
	         STREQ(prop_id, "filename")
	         );
}
예제 #4
0
static bool screenshot_draw_check_prop(PointerRNA *UNUSED(ptr),
                                       PropertyRNA *prop,
                                       void *UNUSED(user_data))
{
  const char *prop_id = RNA_property_identifier(prop);

  return !(STREQ(prop_id, "filepath"));
}
예제 #5
0
static int py_to_array_index(PyObject *py, PointerRNA *ptr, PropertyRNA *prop,
                             int lvalue_dim, int arrayoffset, int index,
                             ItemTypeCheckFunc check_item_type, const char *item_type_str,
                             ItemConvertFunc convert_item, RNA_SetIndexFunc rna_set_index, const char *error_prefix)
{
	int totdim, dimsize[MAX_ARRAY_DIMENSION];
	int totitem, i;

	totdim = RNA_property_array_dimension(ptr, prop, dimsize);

	/* convert index */

	/* arr[3][4][5]
	 *
	 *    arr[2] = x
	 *    lvalue_dim = 0, index = 0 + 2 * 4 * 5
	 *
	 *    arr[2][3] = x
	 *    lvalue_dim = 1, index = 40 + 3 * 5 */

	lvalue_dim++;

	for (i = lvalue_dim; i < totdim; i++)
		index *= dimsize[i];

	index += arrayoffset;

	if (lvalue_dim == totdim) { /* single item, assign directly */
		if (!check_item_type(py)) {
			PyErr_Format(PyExc_TypeError, "%s %.200s.%.200s, expected a %s type, not %s",
			             error_prefix, RNA_struct_identifier(ptr->type),
			             RNA_property_identifier(prop), item_type_str,
			             Py_TYPE(py)->tp_name);
			return -1;
		}
		copy_value_single(py, ptr, prop, NULL, 0, &index, convert_item, rna_set_index);
	}
	else {
		if (validate_array(py, ptr, prop, lvalue_dim, check_item_type, item_type_str, &totitem, error_prefix) == -1) {
			return -1;
		}

		if (totitem) {
			copy_values(py, ptr, prop, lvalue_dim, NULL, 0, &index, convert_item, rna_set_index);
		}
	}
	return 0;
}
예제 #6
0
/* medium match strictness: path match only (i.e. ignore ID) */
static tAnimCopybufItem *pastebuf_match_path_property(FCurve *fcu, const short from_single, const short UNUSED(to_simple))
{
	tAnimCopybufItem *aci;

	for (aci= animcopybuf.first; aci; aci= aci->next) {
		/* check that paths exist */
		if (aci->rna_path && fcu->rna_path) {
			/* find the property of the fcurve and compare against the end of the tAnimCopybufItem
			 * more involved since it needs to to path lookups.
			 * This is not 100% reliable since the user could be editing the curves on a path that wont
			 * resolve, or a bone could be renamed after copying for eg. but in normal copy & paste
			 * this should work out ok. 
			 */
			if (BLI_findindex(which_libbase(G.main, aci->id_type), aci->id) == -1) {
				/* pedantic but the ID could have been removed, and beats crashing! */
				printf("paste_animedit_keys: error ID has been removed!\n");
			}
			else {
				PointerRNA id_ptr, rptr;
				PropertyRNA *prop;
				
				RNA_id_pointer_create(aci->id, &id_ptr);
				RNA_path_resolve(&id_ptr, aci->rna_path, &rptr, &prop);
				
				if (prop) {
					const char *identifier= RNA_property_identifier(prop);
					int len_id = strlen(identifier);
					int len_path = strlen(fcu->rna_path);
					if (len_id <= len_path) {
						/* note, paths which end with "] will fail with this test - Animated ID Props */
						if (strcmp(identifier, fcu->rna_path + (len_path-len_id))==0) {
							if ((from_single) || (aci->array_index == fcu->array_index))
								break;
						}
					}
				}
				else {
					printf("paste_animedit_keys: failed to resolve path id:%s, '%s'!\n", aci->id->name, aci->rna_path);
				}
			}
		}
	}

	return aci;
}
static EnumPropertyItem *dt_layers_select_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *prop, bool *r_free)
{
	const bool reverse_transfer = RNA_boolean_get(ptr, "use_reverse_transfer");

	if (STREQ(RNA_property_identifier(prop), "layers_select_dst")) {
		if (reverse_transfer) {
			return dt_layers_select_src_itemf(C, ptr, prop, r_free);
		}
		else {
			return dt_layers_select_dst_itemf(C, ptr, prop, r_free);
		}
	}
	else if (reverse_transfer) {
		return dt_layers_select_dst_itemf(C, ptr, prop, r_free);
	}
	else {
		return dt_layers_select_src_itemf(C, ptr, prop, r_free);
	}
}
예제 #8
0
/* Hide one of offset or offset_pct, depending on offset_type */
static bool edbm_bevel_poll_property(const bContext *UNUSED(C),
                                     wmOperator *op,
                                     const PropertyRNA *prop)
{
  const char *prop_id = RNA_property_identifier(prop);

  if (STRPREFIX(prop_id, "offset")) {
    int offset_type = RNA_enum_get(op->ptr, "offset_type");

    if (STREQ(prop_id, "offset") && offset_type == BEVEL_AMT_PERCENT) {
      return false;
    }
    else if (STREQ(prop_id, "offset_pct") && offset_type != BEVEL_AMT_PERCENT) {
      return false;
    }
  }

  return true;
}
/* Used by both OBJECT_OT_data_transfer and OBJECT_OT_datalayout_transfer */
static bool data_transfer_draw_check_prop(PointerRNA *ptr, PropertyRNA *prop)
{
	PropertyRNA *prop_other;

	const char *prop_id = RNA_property_identifier(prop);
	const int data_type = RNA_enum_get(ptr, "data_type");
	bool use_auto_transform = false;
	bool use_max_distance = false;
	bool use_modifier = false;

	if ((prop_other = RNA_struct_find_property(ptr, "use_auto_transform"))) {
		use_auto_transform = RNA_property_boolean_get(ptr, prop_other);
	}
	if ((prop_other = RNA_struct_find_property(ptr, "use_max_distance"))) {
		use_max_distance = RNA_property_boolean_get(ptr, prop_other);
	}
	if ((prop_other = RNA_struct_find_property(ptr, "modifier"))) {
		use_modifier = RNA_property_is_set(ptr, prop_other);
	}

	if (STREQ(prop_id, "modifier")) {
		return use_modifier;
	}

	if (use_modifier) {
		/* Hide everything but 'modifier' property, if set. */
		return false;
	}

	if (STREQ(prop_id, "use_object_transform") && use_auto_transform) {
		return false;
	}
	if (STREQ(prop_id, "max_distance") && !use_max_distance) {
		return false;
	}
	if (STREQ(prop_id, "islands_precision") && !DT_DATATYPE_IS_LOOP(data_type)) {
		return false;
	}

	if (STREQ(prop_id, "vert_mapping") && !DT_DATATYPE_IS_VERT(data_type)) {
		return false;
	}
	if (STREQ(prop_id, "edge_mapping") && !DT_DATATYPE_IS_EDGE(data_type)) {
		return false;
	}
	if (STREQ(prop_id, "loop_mapping") && !DT_DATATYPE_IS_LOOP(data_type)) {
		return false;
	}
	if (STREQ(prop_id, "poly_mapping") && !DT_DATATYPE_IS_POLY(data_type)) {
		return false;
	}

	if ((STREQ(prop_id, "layers_select_src") || STREQ(prop_id, "layers_select_dst")) &&
	    !DT_DATATYPE_IS_MULTILAYERS(data_type))
	{
		return false;
	}

	/* Else, show it! */
	return true;
}
static bool gp_convert_draw_check_prop(PointerRNA *ptr, PropertyRNA *prop)
{
	const char *prop_id = RNA_property_identifier(prop);
	const bool link_strokes = RNA_boolean_get(ptr, "use_link_strokes");
	int timing_mode = RNA_enum_get(ptr, "timing_mode");
	bool realtime = RNA_boolean_get(ptr, "use_realtime");
	float gap_duration = RNA_float_get(ptr, "gap_duration");
	float gap_randomness = RNA_float_get(ptr, "gap_randomness");
	const bool valid_timing = RNA_boolean_get(ptr, "use_timing_data");
	
	/* Always show those props */
	if (STREQ(prop_id, "type") ||
	    STREQ(prop_id, "use_normalize_weights") ||
	    STREQ(prop_id, "radius_multiplier") ||
	    STREQ(prop_id, "use_link_strokes"))
	{
		return true;
	}
	
	/* Never show this prop */
	if (STREQ(prop_id, "use_timing_data"))
		return false;
	
	if (link_strokes) {
		/* Only show when link_stroke is true */
		if (STREQ(prop_id, "timing_mode"))
			return true;
		
		if (timing_mode != GP_STROKECONVERT_TIMING_NONE) {
			/* Only show when link_stroke is true and stroke timing is enabled */
			if (STREQ(prop_id, "frame_range") ||
			    STREQ(prop_id, "start_frame"))
			{
				return true;
			}
			
			/* Only show if we have valid timing data! */
			if (valid_timing && STREQ(prop_id, "use_realtime"))
				return true;
			
			/* Only show if realtime or valid_timing is false! */
			if ((!realtime || !valid_timing) && STREQ(prop_id, "end_frame"))
				return true;
			
			if (valid_timing && timing_mode == GP_STROKECONVERT_TIMING_CUSTOMGAP) {
				/* Only show for custom gaps! */
				if (STREQ(prop_id, "gap_duration"))
					return true;
				
				/* Only show randomness for non-null custom gaps! */
				if (STREQ(prop_id, "gap_randomness") && (gap_duration > 0.0f))
					return true;
				
				/* Only show seed for randomize action! */
				if (STREQ(prop_id, "seed") && (gap_duration > 0.0f) && (gap_randomness > 0.0f))
					return true;
			}
		}
	}
	
	/* Else, hidden! */
	return false;
}
예제 #11
0
파일: drivers.c 프로젝트: dfelinto/blender
/* Helper for ANIM_add_driver_with_target - Adds the actual driver */
static int add_driver_with_target(ReportList *UNUSED(reports),
                                  ID *dst_id,
                                  const char dst_path[],
                                  int dst_index,
                                  ID *src_id,
                                  const char src_path[],
                                  int src_index,
                                  PointerRNA *dst_ptr,
                                  PropertyRNA *dst_prop,
                                  PointerRNA *src_ptr,
                                  PropertyRNA *src_prop,
                                  short flag,
                                  int driver_type)
{
  FCurve *fcu;
  short add_mode = (flag & CREATEDRIVER_WITH_FMODIFIER) ? 2 : 1;
  const char *prop_name = RNA_property_identifier(src_prop);

  /* Create F-Curve with Driver */
  fcu = verify_driver_fcurve(dst_id, dst_path, dst_index, add_mode);

  if (fcu && fcu->driver) {
    ChannelDriver *driver = fcu->driver;
    DriverVar *dvar;

    /* Set the type of the driver */
    driver->type = driver_type;

    /* Set driver expression, so that the driver works out of the box
     *
     * The following checks define a bit of "autodetection magic" we use
     * to ensure that the drivers will behave as expected out of the box
     * when faced with properties with different units.
     */
    /* XXX: if we have N-1 mapping, should we include all those in the expression? */
    if ((RNA_property_unit(dst_prop) == PROP_UNIT_ROTATION) &&
        (RNA_property_unit(src_prop) != PROP_UNIT_ROTATION)) {
      /* Rotation Destination:  normal -> radians,  so convert src to radians
       * (However, if both input and output is a rotation, don't apply such corrections)
       */
      BLI_strncpy(driver->expression, "radians(var)", sizeof(driver->expression));
    }
    else if ((RNA_property_unit(src_prop) == PROP_UNIT_ROTATION) &&
             (RNA_property_unit(dst_prop) != PROP_UNIT_ROTATION)) {
      /* Rotation Source:  radians -> normal,  so convert src to degrees
       * (However, if both input and output is a rotation, don't apply such corrections)
       */
      BLI_strncpy(driver->expression, "degrees(var)", sizeof(driver->expression));
    }
    else {
      /* Just a normal property without any unit problems */
      BLI_strncpy(driver->expression, "var", sizeof(driver->expression));
    }

    /* Create a driver variable for the target
     *   - For transform properties, we want to automatically use "transform channel" instead
     *     (The only issue is with quat rotations vs euler channels...)
     *   - To avoid problems with transform properties depending on the final transform that they
     *     control (thus creating pseudo-cycles - see T48734), we don't use transform channels
     *     when both the source and destinations are in same places.
     */
    dvar = driver_add_new_variable(driver);

    if (ELEM(src_ptr->type, &RNA_Object, &RNA_PoseBone) &&
        (STREQ(prop_name, "location") || STREQ(prop_name, "scale") ||
         STRPREFIX(prop_name, "rotation_")) &&
        (src_ptr->data != dst_ptr->data)) {
      /* Transform Channel */
      DriverTarget *dtar;

      driver_change_variable_type(dvar, DVAR_TYPE_TRANSFORM_CHAN);
      dtar = &dvar->targets[0];

      /* Bone or Object target? */
      dtar->id = src_id;
      dtar->idtype = GS(src_id->name);

      if (src_ptr->type == &RNA_PoseBone) {
        RNA_string_get(src_ptr, "name", dtar->pchan_name);
      }

      /* Transform channel depends on type */
      if (STREQ(prop_name, "location")) {
        if (src_index == 2) {
          dtar->transChan = DTAR_TRANSCHAN_LOCZ;
        }
        else if (src_index == 1) {
          dtar->transChan = DTAR_TRANSCHAN_LOCY;
        }
        else {
          dtar->transChan = DTAR_TRANSCHAN_LOCX;
        }
      }
      else if (STREQ(prop_name, "scale")) {
        if (src_index == 2) {
          dtar->transChan = DTAR_TRANSCHAN_SCALEZ;
        }
        else if (src_index == 1) {
          dtar->transChan = DTAR_TRANSCHAN_SCALEY;
        }
        else {
          dtar->transChan = DTAR_TRANSCHAN_SCALEX;
        }
      }
      else {
        /* XXX: With quaternions and axis-angle, this mapping might not be correct...
         *      But since those have 4 elements instead, there's not much we can do
         */
        if (src_index == 2) {
          dtar->transChan = DTAR_TRANSCHAN_ROTZ;
        }
        else if (src_index == 1) {
          dtar->transChan = DTAR_TRANSCHAN_ROTY;
        }
        else {
          dtar->transChan = DTAR_TRANSCHAN_ROTX;
        }
      }
    }
    else {
      /* Single RNA Property */
      DriverTarget *dtar = &dvar->targets[0];

      /* ID is as-is */
      dtar->id = src_id;
      dtar->idtype = GS(src_id->name);

      /* Need to make a copy of the path (or build one with array index built in) */
      if (RNA_property_array_check(src_prop)) {
        dtar->rna_path = BLI_sprintfN("%s[%d]", src_path, src_index);
      }
      else {
        dtar->rna_path = BLI_strdup(src_path);
      }
    }
  }

  /* set the done status */
  return (fcu != NULL);
}
예제 #12
0
static int file_browse_exec(bContext *C, wmOperator *op)
{
	FileBrowseOp *fbo = op->customdata;
	ID *id;
	char *str, path[FILE_MAX];
	const char *path_prop = RNA_struct_find_property(op->ptr, "directory") ? "directory" : "filepath";
	
	if (RNA_struct_property_is_set(op->ptr, path_prop) == 0 || fbo == NULL)
		return OPERATOR_CANCELLED;
	
	str = RNA_string_get_alloc(op->ptr, path_prop, NULL, 0);

	/* add slash for directories, important for some properties */
	if (RNA_property_subtype(fbo->prop) == PROP_DIRPATH) {
		const bool is_relative = RNA_boolean_get(op->ptr, "relative_path");
		id = fbo->ptr.id.data;

		BLI_strncpy(path, str, FILE_MAX);
		BLI_path_abs(path, id ? ID_BLEND_PATH(G.main, id) : G.main->name);
		
		if (BLI_is_dir(path)) {
			/* do this first so '//' isnt converted to '//\' on windows */
			BLI_add_slash(path);
			if (is_relative) {
				BLI_strncpy(path, str, FILE_MAX);
				BLI_path_rel(path, G.main->name);
				str = MEM_reallocN(str, strlen(path) + 2);
				BLI_strncpy(str, path, FILE_MAX);
			}
			else {
				str = MEM_reallocN(str, strlen(str) + 2);
			}
		}
		else {
			char * const lslash = (char *)BLI_last_slash(str);
			if (lslash) lslash[1] = '\0';
		}
	}

	RNA_property_string_set(&fbo->ptr, fbo->prop, str);
	RNA_property_update(C, &fbo->ptr, fbo->prop);
	MEM_freeN(str);

	if (fbo->is_undo) {
		const char *undostr = RNA_property_identifier(fbo->prop);
		ED_undo_push(C, undostr);
	}

	/* special, annoying exception, filesel on redo panel [#26618] */
	{
		wmOperator *redo_op = WM_operator_last_redo(C);
		if (redo_op) {
			if (fbo->ptr.data == redo_op->ptr->data) {
				ED_undo_operator_repeat(C, redo_op);
			}
		}
	}

	MEM_freeN(op->customdata);

	return OPERATOR_FINISHED;
}
예제 #13
0
static int screenshot_draw_check_prop(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
{
	const char *prop_id = RNA_property_identifier(prop);

	return !(strcmp(prop_id, "filepath") == 0);
}
예제 #14
0
/* Modifies property array length if needed and PROP_DYNAMIC flag is set. */
static int validate_array_length(PyObject *rvalue, PointerRNA *ptr, PropertyRNA *prop,
                                 int lvalue_dim, int *totitem, const char *error_prefix)
{
	int dimsize[MAX_ARRAY_DIMENSION];
	int tot, totdim, len;

	totdim = RNA_property_array_dimension(ptr, prop, dimsize);
	tot = count_items(rvalue, totdim - lvalue_dim);

	if (tot == -1) {
		PyErr_Format(PyExc_ValueError, "%s %.200s.%.200s, error validating the sequence length",
		             error_prefix, RNA_struct_identifier(ptr->type), RNA_property_identifier(prop));
		return -1;
	}
	else if ((RNA_property_flag(prop) & PROP_DYNAMIC) && lvalue_dim == 0) {
		if (RNA_property_array_length(ptr, prop) != tot) {
#if 0
			/* length is flexible */
			if (!RNA_property_dynamic_array_set_length(ptr, prop, tot)) {
				/* BLI_snprintf(error_str, error_str_size,
				 *              "%s.%s: array length cannot be changed to %d",
				 *              RNA_struct_identifier(ptr->type), RNA_property_identifier(prop), tot); */
				PyErr_Format(PyExc_ValueError, "%s %s.%s: array length cannot be changed to %d",
				             error_prefix, RNA_struct_identifier(ptr->type), RNA_property_identifier(prop), tot);
				return -1;
			}
#else
			*totitem = tot;
			return 0;

#endif
		}

		len = tot;
	}
	else {
		/* length is a constraint */
		if (!lvalue_dim) {
			len = RNA_property_array_length(ptr, prop);
		}
		/* array item assignment */
		else {
			int i;

			len = 1;

			/* arr[3][4][5]
			 *
			 *    arr[2] = x
			 *    dimsize = {4, 5}
			 *    dimsize[1] = 4
			 *    dimsize[2] = 5
			 *    lvalue_dim = 0, totdim = 3
			 * 
			 *    arr[2][3] = x
			 *    lvalue_dim = 1
			 * 
			 *    arr[2][3][4] = x
			 *    lvalue_dim = 2 */
			for (i = lvalue_dim; i < totdim; i++)
				len *= dimsize[i];
		}

		if (tot != len) {
			/* BLI_snprintf(error_str, error_str_size, "sequence must have length of %d", len); */
			PyErr_Format(PyExc_ValueError, "%s %.200s.%.200s, sequence must have %d items total, not %d",
			             error_prefix, RNA_struct_identifier(ptr->type), RNA_property_identifier(prop), len, tot);
			return -1;
		}
	}

	*totitem = len;

	return 0;
}