const unsigned int points_len,
const unsigned int dims,
const double error_threshold,
+ const unsigned int calc_flag,
const unsigned int *corners,
unsigned int corners_len,
const unsigned int points_len,
const unsigned int dims,
const float error_threshold,
+ const unsigned int calc_flag,
const unsigned int *corners,
const unsigned int corners_len,
float r_handle_r[],
float *r_error_sq);
+enum {
+ CURVE_FIT_CALC_HIGH_QUALIY = (1 << 0),
+};
+
/* curve_fit_corners_detect.c */
/**
*r_error_max_sq = error_max_sq;
*r_split_index = split_index;
- if (error_max_sq < error_threshold_sq) {
- free(u);
- return true;
- }
- else {
+ if (!(error_max_sq < error_threshold_sq)) {
cubic_copy(cubic_test, r_cubic, dims);
/* If error not too large, try some reparameterization and iteration */
points_offset_coords_length,
#endif
u_prime, tan_l, tan_r, dims, cubic_test);
- error_max_sq = cubic_calc_error(
+
+ const double error_max_sq_test = cubic_calc_error(
cubic_test, points_offset, points_offset_len, u_prime, dims,
&split_index);
- if (error_max_sq < error_threshold_sq) {
- free(u_prime);
- free(u);
-
- cubic_copy(r_cubic, cubic_test, dims);
- *r_error_max_sq = error_max_sq;
- *r_split_index = split_index;
- return true;
- }
- else if (error_max_sq < *r_error_max_sq) {
+ if (error_max_sq > error_max_sq_test) {
+ error_max_sq = error_max_sq_test;
cubic_copy(r_cubic, cubic_test, dims);
*r_error_max_sq = error_max_sq;
*r_split_index = split_index;
}
+ if (!(error_max_sq < error_threshold_sq)) {
+ /* continue */
+ }
+ else {
+ assert((error_max_sq < error_threshold_sq));
+ free(u_prime);
+ free(u);
+ return true;
+ }
+
SWAP(double *, u, u_prime);
}
free(u_prime);
return false;
}
+ else {
+ free(u);
+ return true;
+ }
}
static void fit_cubic_to_points_recursive(
const double tan_l[],
const double tan_r[],
const double error_threshold_sq,
+ const uint calc_flag,
const uint dims,
/* fill in the list */
CubicList *clist)
#ifdef USE_LENGTH_CACHE
points_length_cache,
#endif
- tan_l, tan_r, error_threshold_sq, dims,
- cubic, &error_max_sq, &split_index))
+ tan_l, tan_r,
+ (calc_flag & CURVE_FIT_CALC_HIGH_QUALIY) ? DBL_EPSILON : error_threshold_sq,
+ dims,
+ cubic, &error_max_sq, &split_index) ||
+ (error_max_sq < error_threshold_sq))
{
cubic_list_prepend(clist, cubic);
return;
#ifdef USE_LENGTH_CACHE
points_length_cache,
#endif
- tan_l, tan_center, error_threshold_sq, dims, clist);
+ tan_l, tan_center, error_threshold_sq, calc_flag, dims, clist);
fit_cubic_to_points_recursive(
&points_offset[split_index * dims], points_offset_len - split_index,
#ifdef USE_LENGTH_CACHE
points_length_cache + split_index,
#endif
- tan_center, tan_r, error_threshold_sq, dims, clist);
+ tan_center, tan_r, error_threshold_sq, calc_flag, dims, clist);
}
const uint points_len,
const uint dims,
const double error_threshold,
+ const uint calc_flag,
const uint *corners,
uint corners_len,
#ifdef USE_LENGTH_CACHE
points_length_cache,
#endif
- tan_l, tan_r, error_threshold_sq, dims, &clist);
+ tan_l, tan_r, error_threshold_sq, calc_flag, dims, &clist);
}
else if (points_len == 1) {
assert(points_offset_len == 1);
const uint points_len,
const uint dims,
const float error_threshold,
+ const uint calc_flag,
const uint *corners,
const uint corners_len,
uint cubic_array_len = 0;
int result = curve_fit_cubic_to_points_db(
- points_db, points_len, dims, error_threshold, corners, corners_len,
+ points_db, points_len, dims, error_threshold, calc_flag, corners, corners_len,
&cubic_array_db, &cubic_array_len,
r_cubic_orig_index,
r_corner_index_array, r_corner_index_len);
SOCKET_OUT_FLOAT(is_camera_ray, "Is Camera Ray");
SOCKET_OUT_FLOAT(is_shadow_ray, "Is Shadow Ray");
- SOCKET_OUT_FLOAT(is_diffus_ray, "Is Diffus Ray");
+ SOCKET_OUT_FLOAT(is_diffuse_ray, "Is Diffuse Ray");
SOCKET_OUT_FLOAT(is_glossy_ray, "Is Glossy Ray");
SOCKET_OUT_FLOAT(is_singular_ray, "Is Singular Ray");
SOCKET_OUT_FLOAT(is_reflection_ray, "Is Reflection Ray");
('Graph Editor', 'GRAPH_EDITOR', 'WINDOW', [
('Graph Editor Generic', 'GRAPH_EDITOR', 'WINDOW', []),
]),
- ('Dopesheet', 'DOPESHEET_EDITOR', 'WINDOW', []),
+ ('Dopesheet', 'DOPESHEET_EDITOR', 'WINDOW', [
+ ('Dopesheet Generic', 'DOPESHEET_EDITOR', 'WINDOW', []),
+ ]),
('NLA Editor', 'NLA_EDITOR', 'WINDOW', [
('NLA Channels', 'NLA_EDITOR', 'WINDOW', []),
('NLA Generic', 'NLA_EDITOR', 'WINDOW', []),
struct bNodeTree *ntreeFromID(struct ID *id);
void ntreeMakeLocal(struct bNodeTree *ntree, bool id_in_mainlist);
+struct bNode *ntreeFindType(const struct bNodeTree *ntree, int type);
bool ntreeHasType(const struct bNodeTree *ntree, int type);
bool ntreeHasTree(const struct bNodeTree *ntree, const struct bNodeTree *lookup);
void ntreeUpdateTree(struct Main *main, struct bNodeTree *ntree);
int index = 0;
while (index < MAX_LIBARRAY) {
- id_map->type_maps[index].map = NULL;
- id_map->type_maps[index].id_type = BKE_idcode_iter_step(&index);
+ struct IDNameLib_TypeMap *type_map = &id_map->type_maps[index];
+ type_map->map = NULL;
+ type_map->id_type = BKE_idcode_iter_step(&index);
+ BLI_assert(type_map->id_type != 0);
}
BLI_assert(index == MAX_LIBARRAY);
/* ************ find stuff *************** */
+bNode *ntreeFindType(const bNodeTree *ntree, int type) {
+ if (ntree) {
+ for (bNode * node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == type) {
+ return node;
+ }
+ }
+ }
+ return NULL;
+}
+
bool ntreeHasType(const bNodeTree *ntree, int type)
{
- bNode *node;
-
- if (ntree)
- for (node = ntree->nodes.first; node; node = node->next)
- if (node->type == type)
- return true;
- return false;
+ return ntreeFindType(ntree, type) != NULL;
}
bool ntreeHasTree(const bNodeTree *ntree, const bNodeTree *lookup)
/* if the cost from #BLI_quadric_evaluate is 'noise', fallback to topology */
#define USE_TOPOLOGY_FALLBACK
#ifdef USE_TOPOLOGY_FALLBACK
-# define TOPOLOGY_FALLBACK_EPS FLT_EPSILON
+/* cost is calculated with double precision, it's ok to use a very small epsilon, see T48154. */
+# define TOPOLOGY_FALLBACK_EPS 1e-12f
#endif
/* these checks are for rare cases that we can't avoid since they are valid meshes still */
COLLADAFW::MeshPrimitiveArray& prim_arr = mesh->getMeshPrimitives();
const std::string &name = bc_get_dae_name(mesh);
- int hole_count = 0;
for (unsigned i = 0; i < prim_arr.getCount(); i++) {
-
+
COLLADAFW::MeshPrimitive *mp = prim_arr[i];
COLLADAFW::MeshPrimitive::PrimitiveType type = mp->getPrimitiveType();
const char *type_str = bc_primTypeToStr(type);
-
+
// OpenCollada passes POLYGONS type for <polylist>
if (type == COLLADAFW::MeshPrimitive::POLYLIST || type == COLLADAFW::MeshPrimitive::POLYGONS) {
COLLADAFW::Polygons *mpvc = (COLLADAFW::Polygons *)mp;
COLLADAFW::Polygons::VertexCountArray& vca = mpvc->getGroupedVerticesVertexCountArray();
-
+
+ int hole_count = 0;
+ int nonface_count = 0;
+
for (unsigned int j = 0; j < vca.getCount(); j++) {
int count = vca[j];
if (abs(count) < 3) {
- fprintf(stderr, "ERROR: Primitive %s in %s has at least one face with vertex count < 3\n",
- type_str, name.c_str());
- return false;
+ nonface_count++;
}
- if (count < 0)
- {
+
+ if (count < 0) {
hole_count ++;
}
}
- if (hole_count > 0)
- {
+ if (hole_count > 0) {
fprintf(stderr, "WARNING: Primitive %s in %s: %d holes not imported (unsupported)\n", type_str, name.c_str(), hole_count);
}
+
+ if (nonface_count > 0) {
+ fprintf(stderr, "WARNING: Primitive %s in %s: %d faces with vertex count < 3 (rejected)\n", type_str, name.c_str(), nonface_count);
+ }
}
else if (type == COLLADAFW::MeshPrimitive::LINES) {
unsigned int corners_index_len = 0;
const int result = curve_fit_cubic_to_points_fl(
- coords, stroke_len, dims, error_threshold,
+ coords, stroke_len, dims, error_threshold, CURVE_FIT_CALC_HIGH_QUALIY,
corners, corners_len,
&cubic_spline, &cubic_spline_len,
NULL,
!IS_EVENT_MOD(event, shift, oskey) &&
(event->val == KM_PRESS))
{
- if (event->alt)
- ui_but_anim_remove_driver(C);
- else if (event->ctrl)
- ui_but_anim_add_driver(C);
-
- ED_region_tag_redraw(data->region);
-
+ /* quick check to prevent this opening within the popup menu its self */
+ if (!ELEM(NULL, but->rnapoin.data, but->rnaprop)) {
+ if (event->alt)
+ ui_but_anim_remove_driver(C);
+ else if (event->ctrl)
+ ui_but_anim_add_driver(C);
+
+ ED_region_tag_redraw(data->region);
+ }
return WM_UI_HANDLER_BREAK;
}
/* handle keyingsets */
RNA_def_boolean(ot->srna,
"auto_connect", 0, "Auto Connect",
- "set use_connect for parent bones which have exactly one child bone");
+ "Set use_connect for parent bones which have exactly one child bone");
RNA_def_int(ot->srna,
"min_chain_length",
/* until implement profile = 0 case, need to clamp somewhat above zero */
#define PROFILE_HARD_MIN 0.15f
+#define SEGMENTS_HARD_MAX 1000
+
+/* which value is mouse movement and numeric input controlling? */
+#define OFFSET_VALUE 0
+#define OFFSET_VALUE_PERCENT 1
+#define PROFILE_VALUE 2
+#define SEGMENTS_VALUE 3
+#define NUM_VALUE_KINDS 4
+
+static const char *value_rna_name[NUM_VALUE_KINDS] = {"offset", "offset", "profile", "segments"};
+static const float value_clamp_min[NUM_VALUE_KINDS] = {0.0f, 0.0f, PROFILE_HARD_MIN, 1.0f};
+static const float value_clamp_max[NUM_VALUE_KINDS] = {1e6, 100.0f, 1.0f, SEGMENTS_HARD_MAX};
+static const float value_start[NUM_VALUE_KINDS] = {0.0f, 0.0f, 0.5f, 1.0f};
+static const float value_scale_per_inch[NUM_VALUE_KINDS] = { 0.0f, 100.0f, 1.0f, 4.0f};
+
typedef struct {
BMEditMesh *em;
- float initial_length;
- float pixel_size; /* use when mouse input is interpreted as spatial distance */
+ float initial_length[NUM_VALUE_KINDS];
+ float scale[NUM_VALUE_KINDS];
+ NumInput num_input[NUM_VALUE_KINDS];
+ float shift_value[NUM_VALUE_KINDS]; /* The current value when shift is pressed. Negative when shift not active. */
bool is_modal;
- NumInput num_input;
- float shift_factor; /* The current factor when shift is pressed. Negative when shift not active. */
/* modal only */
float mcenter[2];
BMBackup mesh_backup;
void *draw_handle_pixel;
short twtype;
- bool mouse_controls_profile;
+ short value_mode; /* Which value does mouse movement and numeric input affect? */
float segments; /* Segments as float so smooth mouse pan works in small increments */
} BevelData;
static void edbm_bevel_update_header(bContext *C, wmOperator *op)
{
const char *str = IFACE_("Confirm: (Enter/LMB), Cancel: (Esc/RMB), Mode: %s (M), Clamp Overlap: %s (C), "
- "Vertex Only: %s (V), Profile Control: %s (P), Offset: %s, Segments: %d");
+ "Vertex Only: %s (V), Profile Control: %s (P), Offset: %s, Segments: %d, Profile: %.3f");
char msg[UI_MAX_DRAW_STR];
ScrArea *sa = CTX_wm_area(C);
const char *type_str;
PropertyRNA *prop = RNA_struct_find_property(op->ptr, "offset_type");
- if (hasNumInput(&opdata->num_input)) {
- outputNumInput(&opdata->num_input, offset_str, &sce->unit);
+ if (hasNumInput(&opdata->num_input[OFFSET_VALUE])) {
+ outputNumInput(&opdata->num_input[OFFSET_VALUE], offset_str, &sce->unit);
}
else {
BLI_snprintf(offset_str, NUM_STR_REP_LEN, "%f", RNA_float_get(op->ptr, "offset"));
BLI_snprintf(msg, sizeof(msg), str, type_str,
WM_bool_as_string(RNA_boolean_get(op->ptr, "clamp_overlap")),
WM_bool_as_string(RNA_boolean_get(op->ptr, "vertex_only")),
- WM_bool_as_string(opdata->mouse_controls_profile),
- offset_str, RNA_int_get(op->ptr, "segments"));
+ WM_bool_as_string(opdata->value_mode == PROFILE_VALUE),
+ offset_str, RNA_int_get(op->ptr, "segments"), RNA_float_get(op->ptr, "profile"));
ED_area_headerprint(sa, msg);
}
Scene *scene = CTX_data_scene(C);
BMEditMesh *em = BKE_editmesh_from_object(obedit);
BevelData *opdata;
+ float pixels_per_inch;
+ int i;
if (em->bm->totvertsel == 0) {
return false;
opdata->em = em;
opdata->is_modal = is_modal;
- opdata->shift_factor = -1.0f;
- opdata->mouse_controls_profile = false;
-
- 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? */
+ opdata->value_mode = OFFSET_VALUE;
+ pixels_per_inch = U.dpi * U.pixelsize;
+
+ for (i = 0; i < NUM_VALUE_KINDS; i++) {
+ opdata->shift_value[i] = -1.0f;
+ /* note: scale for OFFSET_VALUE will get overwritten in edbm_bevel_invoke */
+ opdata->scale[i] = value_scale_per_inch[i] / pixels_per_inch;
+
+ initNumInput(&opdata->num_input[i]);
+ opdata->num_input[i].idx_max = 0;
+ opdata->num_input[i].val_flag[0] |= NUM_NO_NEGATIVE;
+ if (i == SEGMENTS_VALUE) {
+ opdata->num_input[i].val_flag[0] |= NUM_NO_FRACTION | NUM_NO_ZERO;
+ }
+ if (i == OFFSET_VALUE) {
+ opdata->num_input[i].unit_sys = scene->unit.system;
+ }
+ opdata->num_input[i].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) {
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);
+ 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;
if (v3d) {
EDBM_redo_state_restore(opdata->mesh_backup, em, false);
}
- if (em->ob)
+ if (em->ob) {
material = CLAMPIS(material, -1, em->ob->totcol - 1);
+ }
EDBM_op_init(em, &bmop, op,
"bevel geom=%hev offset=%f segments=%i vertex_only=%b offset_type=%i profile=%f clamp_overlap=%b "
"material=%i loop_slide=%b",
- BM_ELEM_SELECT, offset, segments, vertex_only, offset_type, profile, clamp_overlap, material, loop_slide);
+ BM_ELEM_SELECT, offset, segments, vertex_only, offset_type, profile,
+ clamp_overlap, material, loop_slide);
BMO_op_exec(em->bm, &bmop);
}
/* no need to de-select existing geometry */
- if (!EDBM_op_finish(em, &bmop, op, true))
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
return false;
+ }
EDBM_mesh_normals_update(opdata->em);
return OPERATOR_FINISHED;
}
+static void edbm_bevel_calc_initial_length(wmOperator *op, const wmEvent *event, bool mode_changed)
+{
+ BevelData *opdata;
+ float mlen[2], len, value, sc, st;
+ int vmode;
+
+ opdata = op->customdata;
+ mlen[0] = opdata->mcenter[0] - event->mval[0];
+ mlen[1] = opdata->mcenter[1] - event->mval[1];
+ len = len_v2(mlen);
+ vmode = opdata->value_mode;
+ if (mode_changed) {
+ /* If current value is not default start value, adjust len so that
+ * the scaling and offset in edbm_bevel_mouse_set_value will
+ * start at current value */
+ value = (vmode == SEGMENTS_VALUE) ?
+ opdata->segments : RNA_float_get(op->ptr, value_rna_name[vmode]);
+ sc = opdata->scale[vmode];
+ st = value_start[vmode];
+ if (value != value_start[vmode]) {
+ len = (st + sc * (len - MVAL_PIXEL_MARGIN) - value) / sc;
+ }
+ }
+ opdata->initial_length[opdata->value_mode] = len;
+}
+
static int edbm_bevel_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
/* TODO make modal keymap (see fly mode) */
RegionView3D *rv3d = CTX_wm_region_view3d(C);
BevelData *opdata;
- float mlen[2];
float center_3d[3];
if (!edbm_bevel_init(C, op, true)) {
* ideally this will never happen and should be checked for above */
opdata->mcenter[0] = opdata->mcenter[1] = 0;
}
- mlen[0] = opdata->mcenter[0] - event->mval[0];
- mlen[1] = opdata->mcenter[1] - event->mval[1];
- opdata->initial_length = len_v2(mlen);
- opdata->pixel_size = rv3d ? ED_view3d_pixel_size(rv3d, center_3d) : 1.0f;
+ edbm_bevel_calc_initial_length(op, event, false);
+
+ /* for OFFSET_VALUE only, the scale is the size of a pixel under the mouse in 3d space */
+ opdata->scale[OFFSET_VALUE] = rv3d ? ED_view3d_pixel_size(rv3d, center_3d) : 1.0f;
edbm_bevel_update_header(C, op);
return OPERATOR_RUNNING_MODAL;
}
-static float edbm_bevel_mval_factor(wmOperator *op, const wmEvent *event)
+static void edbm_bevel_mouse_set_value(wmOperator *op, const wmEvent *event)
{
BevelData *opdata = op->customdata;
- bool use_dist;
- bool is_percent, is_profile;
+ int vmode = opdata->value_mode;
float mdiff[2];
- float factor;
+ float value;
mdiff[0] = opdata->mcenter[0] - event->mval[0];
mdiff[1] = opdata->mcenter[1] - event->mval[1];
- is_percent = (RNA_enum_get(op->ptr, "offset_type") == BEVEL_AMT_PERCENT);
- use_dist = !is_percent;
- is_profile = opdata->mouse_controls_profile;
- factor = ((len_v2(mdiff) - MVAL_PIXEL_MARGIN) - opdata->initial_length) * opdata->pixel_size;
+ value = ((len_v2(mdiff) - MVAL_PIXEL_MARGIN) - opdata->initial_length[vmode]);
+
+ /* Scale according to value mode */
+ value = value_start[vmode] + value * opdata->scale[vmode];
/* Fake shift-transform... */
if (event->shift) {
- if (opdata->shift_factor < 0.0f) {
- if (is_profile)
- opdata->shift_factor = RNA_float_get(op->ptr, "profile");
- else {
- opdata->shift_factor = RNA_float_get(op->ptr, "offset");
- if (is_percent) {
- opdata->shift_factor /= 100.0f;
- }
- }
+ if (opdata->shift_value[vmode] < 0.0f) {
+ opdata->shift_value[vmode] = (vmode == SEGMENTS_VALUE) ?
+ opdata->segments : RNA_float_get(op->ptr, value_rna_name[vmode]);
}
- factor = (factor - opdata->shift_factor) * 0.1f + opdata->shift_factor;
+ value = (value - opdata->shift_value[vmode]) * 0.1f + opdata->shift_value[vmode];
}
- else if (opdata->shift_factor >= 0.0f) {
- opdata->shift_factor = -1.0f;
+ else if (opdata->shift_value[vmode] >= 0.0f) {
+ opdata->shift_value[vmode] = -1.0f;
}
- /* clamp differently based on distance/factor/profile */
- if (is_profile) {
- CLAMP(factor, PROFILE_HARD_MIN, 1.0f);
+ /* clamp accordingto value mode, and store value back */
+ CLAMP(value, value_clamp_min[vmode], value_clamp_max[vmode]);
+ if (vmode == SEGMENTS_VALUE) {
+ opdata->segments = value;
+ RNA_int_set(op->ptr, "segments", (int)(value + 0.5f));
}
else {
- if (use_dist) {
- if (factor < 0.0f) factor = 0.0f;
- }
- else {
- CLAMP(factor, 0.0f, 1.0f);
- if (is_percent) {
- factor *= 100.0f;
- }
- }
+ RNA_float_set(op->ptr, value_rna_name[vmode], value);
}
+}
- return factor;
+static void edbm_bevel_numinput_set_value(wmOperator *op)
+{
+ BevelData *opdata = op->customdata;
+ float value;
+ int vmode;
+
+ vmode = opdata->value_mode;
+ value = (vmode == SEGMENTS_VALUE) ?
+ opdata->segments : RNA_float_get(op->ptr, value_rna_name[vmode]);
+ applyNumInput(&opdata->num_input[vmode], &value);
+ CLAMP(value, value_clamp_min[vmode], value_clamp_max[vmode]);
+ if (vmode == SEGMENTS_VALUE) {
+ opdata->segments = value;
+ RNA_int_set(op->ptr, "segments", (int)value);
+ }
+ else {
+ RNA_float_set(op->ptr, value_rna_name[vmode], value);
+ }
}
static int edbm_bevel_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
BevelData *opdata = op->customdata;
- const bool has_numinput = hasNumInput(&opdata->num_input);
+ const bool has_numinput = hasNumInput(&opdata->num_input[opdata->value_mode]);
/* Modal numinput active, try to handle numeric inputs first... */
- if (event->val == KM_PRESS && has_numinput && handleNumInput(C, &opdata->num_input, event)) {
- float value = RNA_float_get(op->ptr, "offset");
- applyNumInput(&opdata->num_input, &value);
- RNA_float_set(op->ptr, "offset", value);
+ if (event->val == KM_PRESS && has_numinput && handleNumInput(C, &opdata->num_input[opdata->value_mode], event)) {
+ edbm_bevel_numinput_set_value(op);
edbm_bevel_calc(op);
edbm_bevel_update_header(C, op);
return OPERATOR_RUNNING_MODAL;
case MOUSEMOVE:
if (!has_numinput) {
- const float factor = edbm_bevel_mval_factor(op, event);
- if (opdata->mouse_controls_profile)
- RNA_float_set(op->ptr, "profile", factor);
- else
- RNA_float_set(op->ptr, "offset", factor);
-
+ edbm_bevel_mouse_set_value(op, event);
edbm_bevel_calc(op);
edbm_bevel_update_header(C, op);
handled = true;
if (type > BEVEL_AMT_PERCENT) {
type = BEVEL_AMT_OFFSET;
}
+ if (opdata->value_mode == OFFSET_VALUE && type == BEVEL_AMT_PERCENT)
+ opdata->value_mode = OFFSET_VALUE_PERCENT;
+ else if (opdata->value_mode == OFFSET_VALUE_PERCENT && type != BEVEL_AMT_PERCENT)
+ opdata->value_mode = OFFSET_VALUE;
RNA_property_enum_set(op->ptr, prop, type);
}
- /* Update factor accordingly to new offset_type. */
- if (!has_numinput) {
- RNA_float_set(op->ptr, "offset", edbm_bevel_mval_factor(op, event));
- }
+ /* Update offset accordingly to new offset_type. */
+ if (!has_numinput &&
+ (opdata->value_mode == OFFSET_VALUE || opdata->value_mode == OFFSET_VALUE_PERCENT))
+ {
+ edbm_bevel_mouse_set_value(op, event);
+ }
edbm_bevel_calc(op);
edbm_bevel_update_header(C, op);
handled = true;
case PKEY:
if (event->val == KM_RELEASE)
break;
- opdata->mouse_controls_profile = !opdata->mouse_controls_profile;
+ if (opdata->value_mode == PROFILE_VALUE) {
+ opdata->value_mode = OFFSET_VALUE;
+ }
+ else {
+ opdata->value_mode = PROFILE_VALUE;
+ }
+ edbm_bevel_calc_initial_length(op, event, true);
+ break;
+ case SKEY:
+ if (event->val == KM_RELEASE)
+ break;
+ if (opdata->value_mode == SEGMENTS_VALUE) {
+ opdata->value_mode = OFFSET_VALUE;
+ }
+ else {
+ opdata->value_mode = SEGMENTS_VALUE;
+ }
+ edbm_bevel_calc_initial_length(op, event, true);
break;
case VKEY:
if (event->val == KM_RELEASE)
}
/* Modal numinput inactive, try to handle numeric inputs last... */
- if (!handled && event->val == KM_PRESS && handleNumInput(C, &opdata->num_input, event)) {
- float value = RNA_float_get(op->ptr, "offset");
- applyNumInput(&opdata->num_input, &value);
- RNA_float_set(op->ptr, "offset", value);
+ if (!handled && event->val == KM_PRESS && handleNumInput(C, &opdata->num_input[opdata->value_mode], event)) {
+ edbm_bevel_numinput_set_value(op);
edbm_bevel_calc(op);
edbm_bevel_update_header(C, op);
return OPERATOR_RUNNING_MODAL;
RNA_def_enum(ot->srna, "offset_type", offset_type_items, 0, "Amount Type", "What distance Amount measures");
prop = RNA_def_float(ot->srna, "offset", 0.0f, -1e6f, 1e6f, "Amount", "", 0.0f, 1.0f);
RNA_def_property_float_array_funcs_runtime(prop, NULL, NULL, mesh_ot_bevel_offset_range_func);
- RNA_def_int(ot->srna, "segments", 1, 1, 50, "Segments", "Segments for curved edge", 1, 8);
+ RNA_def_int(ot->srna, "segments", 1, 1, SEGMENTS_HARD_MAX, "Segments", "Segments for curved edge", 1, 8);
RNA_def_float(ot->srna, "profile", 0.5f, PROFILE_HARD_MIN, 1.0f, "Profile",
- "Controls profile shape (0.5 = round)", PROFILE_HARD_MIN, 1.0f);
+ "Controls profile shape (0.5 = round)", PROFILE_HARD_MIN, 1.0f);
RNA_def_boolean(ot->srna, "vertex_only", false, "Vertex Only", "Bevel only vertices");
RNA_def_boolean(ot->srna, "clamp_overlap", false, "Clamp Overlap",
- "Do not allow beveled edges/vertices to overlap each other");
+ "Do not allow beveled edges/vertices to overlap each other");
RNA_def_boolean(ot->srna, "loop_slide", true, "Loop Slide", "Prefer slide along edge to even widths");
- RNA_def_int(ot->srna, "material", -1, -1, INT_MAX, "Material", "Material for bevel faces (-1 means use adjacent faces)", -1, 100);
+ RNA_def_int(ot->srna, "material", -1, -1, INT_MAX, "Material",
+ "Material for bevel faces (-1 means use adjacent faces)", -1, 100);
}
r_snap[2] = r_snap[1] * 0.1f;
}
}
- else if (ELEM(t->spacetype, SPACE_IMAGE, SPACE_CLIP)) {
+ else if (t->spacetype == SPACE_IMAGE) {
+ r_snap[0] = 0.0f;
+ r_snap[1] = 0.0625f;
+ r_snap[2] = 0.03125f;
+ }
+ else if (t->spacetype == SPACE_CLIP) {
r_snap[0] = 0.0f;
r_snap[1] = 0.125f;
r_snap[2] = 0.0625f;
row[index] = swap_uint(pixel, logImage->isMSB);
if (logimage_fwrite(row, rowLength, 1, logImage) == 0) {
- if (verbose) printf("DPX/Cineon: Error while writing file.\n"); {
- MEM_freeN(row);
- return 1;
+ if (verbose) {
+ printf("DPX/Cineon: Error while writing file.\n");
}
+ MEM_freeN(row);
+ return 1;
}
}
MEM_freeN(row);
prop = RNA_def_property(srna, "use_bbone_relative_start_handle", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "bboneflag", PCHAN_BBONE_CUSTOM_START_REL);
RNA_def_property_ui_text(prop, "Relative B-Bone Start Handle",
- "Use treat custom start handle position as a relative value");
+ "Treat custom start handle position as a relative value");
RNA_def_property_editable_func(prop, "rna_PoseChannel_proxy_editable");
RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update");
prop = RNA_def_property(srna, "use_bbone_relative_end_handle", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "bboneflag", PCHAN_BBONE_CUSTOM_END_REL);
RNA_def_property_ui_text(prop, "Relative B-Bone End Handle",
- "Use treat custom end handle position as a relative value");
+ "Treat custom end handle position as a relative value");
RNA_def_property_editable_func(prop, "rna_PoseChannel_proxy_editable");
RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update");
/* GPU material from shader nodes */
+static void ntree_shader_link_builtin_normal(bNodeTree *ntree,
+ bNode *node_from,
+ bNodeSocket *socket_from,
+ bNode *displacement_node,
+ bNodeSocket *displacement_socket);
+
/* Find an output node of the shader tree.
*
* NOTE: it will only return output which is NOT in the group, which isn't how
return displacement->link != NULL;
}
+static bool ntree_shader_relink_node_normal(bNodeTree *ntree,
+ bNode *node,
+ bNode *node_from,
+ bNodeSocket *socket_from)
+{
+ bNodeSocket *sock = ntree_shader_node_find_input(node, "Normal");
+ /* TODO(sergey): Can we do something smarter here than just a name-based
+ * matching?
+ */
+ if (sock == NULL) {
+ /* There's no Normal input, nothing to link. */
+ return false;
+ }
+ if (sock->link != NULL) {
+ /* Something is linked to the normal input already. can't
+ * use other input for that.
+ */
+ return false;
+ }
+ /* Create connection between specified node and the normal input. */
+ nodeAddLink(ntree, node_from, socket_from, node, sock);
+ return true;
+}
+
+static void ntree_shader_link_builtin_group_normal(
+ bNodeTree *ntree,
+ bNode *group_node,
+ bNode *node_from,
+ bNodeSocket *socket_from,
+ bNode *displacement_node,
+ bNodeSocket *displacement_socket)
+{
+ bNodeTree *group_ntree = (bNodeTree *)group_node->id;
+ /* Create input socket to plug displacement connection to. */
+ bNodeSocket *group_normal_socket =
+ ntreeAddSocketInterface(group_ntree,
+ SOCK_IN,
+ "NodeSocketVector",
+ "Normal");
+ /* Need to update tree so all node instances nodes gets proper sockets. */
+ ntreeUpdateTree(G.main, group_ntree);
+ /* Assumes sockets are always added at the end. */
+ bNodeSocket *group_node_normal_socket = (bNodeSocket*)group_node->inputs.last;
+ if (displacement_node == group_node) {
+ /* If displacement is coming from this node group we need to perform
+ * some internal re-linking in order to avoid cycles.
+ */
+ bNode *group_output_node = ntreeFindType(group_ntree, NODE_GROUP_OUTPUT);
+ BLI_assert(group_output_node != NULL);
+ bNodeSocket *group_output_node_displacement_socket =
+ nodeFindSocket(group_output_node,
+ SOCK_IN,
+ displacement_socket->identifier);
+ bNodeLink *group_displacement_link = group_output_node_displacement_socket->link;
+ if (group_displacement_link == NULL) {
+ /* Displacement output is not connected to anything, can just stop
+ * right away.
+ */
+ return;
+ }
+ /* This code is similar to ntree_shader_relink_displacement() */
+ bNode *group_displacement_node = group_displacement_link->fromnode;
+ bNodeSocket *group_displacement_socket = group_displacement_link->fromsock;
+ nodeRemLink(group_ntree, group_displacement_link);
+ /* Create and link bump node.
+ * Can't re-use bump node from parent tree because it'll cause cycle.
+ */
+ bNode *bump_node = nodeAddStaticNode(NULL, group_ntree, SH_NODE_BUMP);
+ bNodeSocket *bump_input_socket = ntree_shader_node_find_input(bump_node, "Height");
+ bNodeSocket *bump_output_socket = ntree_shader_node_find_output(bump_node, "Normal");
+ BLI_assert(bump_input_socket != NULL);
+ BLI_assert(bump_output_socket != NULL);
+ nodeAddLink(group_ntree,
+ group_displacement_node, group_displacement_socket,
+ bump_node, bump_input_socket);
+ /* Relink normals inside of the instanced tree. */
+ ntree_shader_link_builtin_normal(group_ntree,
+ bump_node,
+ bump_output_socket,
+ group_displacement_node,
+ group_displacement_socket);
+ ntreeUpdateTree(G.main, group_ntree);
+ }
+ else {
+ /* Connect group node normal input. */
+ nodeAddLink(ntree,
+ node_from, socket_from,
+ group_node, group_node_normal_socket);
+ bNode *group_input_node = ntreeFindType(group_ntree, NODE_GROUP_INPUT);
+ BLI_assert(group_input_node != NULL);
+ bNodeSocket *group_input_node_normal_socket =
+ nodeFindSocket(group_input_node,
+ SOCK_OUT,
+ group_normal_socket->identifier);
+ BLI_assert(group_input_node_normal_socket != NULL);
+ /* Relink normals inside of the instanced tree. */
+ ntree_shader_link_builtin_normal(group_ntree,
+ group_input_node,
+ group_input_node_normal_socket,
+ displacement_node,
+ displacement_socket);
+ ntreeUpdateTree(G.main, group_ntree);
+ }
+}
+
/* Use specified node and socket as an input for unconnected normal sockets. */
static void ntree_shader_link_builtin_normal(bNodeTree *ntree,
bNode *node_from,
- bNodeSocket *socket_from)
+ bNodeSocket *socket_from,
+ bNode *displacement_node,
+ bNodeSocket *displacement_socket)
{
for (bNode *node = ntree->nodes.first; node != NULL; node = node->next) {
if (node == node_from) {
/* Don't connect node itself! */
continue;
}
- bNodeSocket *sock = ntree_shader_node_find_input(node, "Normal");
- /* TODO(sergey): Can we do something smarter here than just a name-based
- * matching?
- */
- if (sock == NULL) {
- /* There's no Normal input, nothing to link. */
+ if (node->type == NODE_GROUP && node->id) {
+ /* Special re-linking for group nodes. */
+ ntree_shader_link_builtin_group_normal(ntree,
+ node,
+ node_from,
+ socket_from,
+ displacement_node,
+ displacement_socket);
continue;
}
- if (sock->link != NULL) {
- /* Something is linked to the normal input already. can't
- * use other input for that.
- */
+ if (ELEM(node->type, NODE_GROUP_INPUT, NODE_GROUP_OUTPUT)) {
+ /* Group inputs and outputs needs nothing special. */
continue;
}
- /* Create connection between specified node and the normal input. */
- nodeAddLink(ntree, node_from, socket_from, node, sock);
+ ntree_shader_relink_node_normal(ntree, node, node_from, socket_from);
}
}
displacement_node, displacement_socket,
bump_node, bump_input_socket);
/* Connect all free-standing Normal inputs. */
- ntree_shader_link_builtin_normal(ntree, bump_node, bump_output_socket);
+ ntree_shader_link_builtin_normal(ntree,
+ bump_node,
+ bump_output_socket,
+ displacement_node,
+ displacement_socket);
/* TODO(sergey): Reconnect Geometry Info->Normal sockets to the new
* bump node.
*/