Fix bug in how librt knob adapters handled edit_flag.
edit_flag identifies the exact primitive operation, while edit_mode identifies the interaction class. rt_knob_edit_rot/tran/sca() incorrectly replaced a primitive-specific flag with the generic operation before dispatching. Fixed in src/librt/edit.cpp:811: - Preserve primitive-specific edit_flag when edit_mode matches. - Fall back to generic operations otherwise. - Covers translation, rotation, and scale paths. The MGED faceplate and constrained-axis handlers already preserve the flag correctly; they route through these adapters. Added regressions in src/librt/tests/edit/arb8.cpp:312 for: - ARB5 point 5 direct editing. - ARB5 point 5 knob dragging. - ARB face rotation through the knob path.
This commit is contained in:
1 parent
f0a946cf1d
commit
be97d86e4e
3 files changed
+111
-3
No files matched your search
@@ -473,6 +473,12 @@ rt_edit_knob_cmd_process(
|
||||
char origin, int incr_flag, void *u_data
|
||||
);
|
||||
|
||||
/* Knob operations preserve a primitive-specific edit_flag when edit_mode
|
||||
* already matches the requested interaction class. This allows interactive
|
||||
* drags to continue operations such as moving an ARB vertex or rotating an
|
||||
* ARB face; generic RT_PARAMS_EDIT_* flags are selected only when the current
|
||||
* edit is not in the corresponding class. */
|
||||
|
||||
RT_EXPORT extern void
|
||||
rt_knob_edit_rot(struct rt_edit *s,
|
||||
char coords,
|
||||
|
||||
+16
-3
@@ -808,6 +808,19 @@ rt_edit_knob_cmd_process(
|
||||
return BRLCAD_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Knob input describes an interaction class, but the active edit flag may
|
||||
* identify a primitive-specific operation in that class. Keep that exact
|
||||
* operation selected when the caller has already supplied a matching
|
||||
* edit_mode; otherwise fall back to the generic operation.
|
||||
*/
|
||||
static void
|
||||
rt_edit_set_knob_edflag(struct rt_edit *s, int edit_mode)
|
||||
{
|
||||
if (s->edit_mode != edit_mode)
|
||||
rt_edit_set_edflag(s, edit_mode);
|
||||
}
|
||||
|
||||
void
|
||||
rt_knob_edit_rot(struct rt_edit *s,
|
||||
char coords,
|
||||
@@ -853,7 +866,7 @@ rt_knob_edit_rot(struct rt_edit *s,
|
||||
int save_edflag = s->edit_flag;
|
||||
int save_mode = s->edit_mode;
|
||||
|
||||
rt_edit_set_edflag(s, RT_PARAMS_EDIT_ROT);
|
||||
rt_edit_set_knob_edflag(s, RT_PARAMS_EDIT_ROT);
|
||||
|
||||
rt_edit_process(s);
|
||||
|
||||
@@ -952,7 +965,7 @@ rt_knob_edit_tran(struct rt_edit *s,
|
||||
int save_edflag = s->edit_flag;
|
||||
int save_mode = s->edit_mode;
|
||||
|
||||
rt_edit_set_edflag(s, RT_PARAMS_EDIT_TRANS);
|
||||
rt_edit_set_knob_edflag(s, RT_PARAMS_EDIT_TRANS);
|
||||
|
||||
VADD2(s->e_para, delta, s->curr_e_axes_pos);
|
||||
s->e_inpara = 3;
|
||||
@@ -996,7 +1009,7 @@ rt_knob_edit_sca(struct rt_edit *s, int matrix_edit)
|
||||
int save_edflag = s->edit_flag;
|
||||
int save_mode = s->edit_mode;
|
||||
|
||||
rt_edit_set_edflag(s, RT_PARAMS_EDIT_SCALE);
|
||||
rt_edit_set_knob_edflag(s, RT_PARAMS_EDIT_SCALE);
|
||||
|
||||
rt_edit_process(s);
|
||||
|
||||
|
||||
@@ -124,6 +124,30 @@ arb8_reset(struct rt_edit *s, struct rt_arb_internal *arb, struct rt_arb8_edit *
|
||||
s->mv_context = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
arb5_reset(struct rt_edit *s, struct rt_arb_internal *arb, struct rt_arb8_edit *a)
|
||||
{
|
||||
VSET(arb->pt[0], 0, 0, 0);
|
||||
VSET(arb->pt[1], 1, 0, 0);
|
||||
VSET(arb->pt[2], 1, 1, 0);
|
||||
VSET(arb->pt[3], 0, 1, 0);
|
||||
VSET(arb->pt[4], 0.5, 0.5, 1);
|
||||
VMOVE(arb->pt[5], arb->pt[4]);
|
||||
VMOVE(arb->pt[6], arb->pt[4]);
|
||||
VMOVE(arb->pt[7], arb->pt[4]);
|
||||
|
||||
a->newedge = 0;
|
||||
a->edit_menu = 0;
|
||||
|
||||
VSETALL(s->e_keypoint, 0.0);
|
||||
MAT_IDN(s->acc_rot_sol);
|
||||
MAT_IDN(s->incr_change);
|
||||
s->acc_sc_sol = 1.0;
|
||||
s->e_inpara = 0;
|
||||
s->es_scale = 0.0;
|
||||
s->mv_context = 1;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
@@ -285,6 +309,52 @@ main(int argc, char *argv[])
|
||||
bu_exit(1, "ERROR: RT_PARAMS_EDIT_ROT(xy) failed\n");
|
||||
bu_log("RT_PARAMS_EDIT_ROT(xy) SUCCESS: rotation applied via knob path\n");
|
||||
|
||||
/* ================================================================
|
||||
* PTARB ARB5 point 5: both direct parameters and knob translation must
|
||||
* retain the primitive-specific edit flag. Point 5 is stored at pt[4]
|
||||
* and duplicated in pt[5..7].
|
||||
* ================================================================*/
|
||||
arb5_reset(s, arb, a);
|
||||
a->edit_menu = 8; /* symbolic ARB5 point-5 menu argument */
|
||||
rt_edit_set_edflag(s, PTARB);
|
||||
s->edit_mode = RT_PARAMS_EDIT_TRANS;
|
||||
s->e_inpara = 3;
|
||||
VSET(s->e_para, 0.75, 0.75, 1.25);
|
||||
s->mv_context = 0;
|
||||
rt_edit_process(s);
|
||||
{
|
||||
point_t expected = {0.75, 0.75, 1.25};
|
||||
point_t expected_base = {0, 0, 0};
|
||||
if (!VNEAR_EQUAL(arb->pt[4], expected, VUNITIZE_TOL) ||
|
||||
!VNEAR_EQUAL(arb->pt[5], expected, VUNITIZE_TOL) ||
|
||||
!VNEAR_EQUAL(arb->pt[6], expected, VUNITIZE_TOL) ||
|
||||
!VNEAR_EQUAL(arb->pt[7], expected, VUNITIZE_TOL))
|
||||
bu_exit(1, "ERROR: PTARB ARB5 point 5 parameter edit failed\n");
|
||||
if (!VNEAR_EQUAL(arb->pt[0], expected_base, VUNITIZE_TOL))
|
||||
bu_exit(1, "ERROR: PTARB ARB5 point 5 moved the base\n");
|
||||
bu_log("PTARB ARB5 point 5 parameter edit SUCCESS\n");
|
||||
}
|
||||
|
||||
arb5_reset(s, arb, a);
|
||||
a->edit_menu = 8;
|
||||
rt_edit_set_edflag(s, PTARB);
|
||||
s->edit_mode = RT_PARAMS_EDIT_TRANS;
|
||||
s->mv_context = 0;
|
||||
VMOVE(s->curr_e_axes_pos, arb->pt[4]);
|
||||
vect_t point_delta = {0.1, 0.2, 0.3};
|
||||
rt_knob_edit_tran(s, 'm', 0, point_delta);
|
||||
{
|
||||
point_t expected = {0.6, 0.7, 1.3};
|
||||
point_t expected_base = {0, 0, 0};
|
||||
if (!VNEAR_EQUAL(arb->pt[4], expected, VUNITIZE_TOL) ||
|
||||
!VNEAR_EQUAL(arb->pt[5], expected, VUNITIZE_TOL) ||
|
||||
!VNEAR_EQUAL(arb->pt[6], expected, VUNITIZE_TOL) ||
|
||||
!VNEAR_EQUAL(arb->pt[7], expected, VUNITIZE_TOL) ||
|
||||
!VNEAR_EQUAL(arb->pt[0], expected_base, VUNITIZE_TOL))
|
||||
bu_exit(1, "ERROR: PTARB ARB5 point 5 knob edit failed\n");
|
||||
bu_log("PTARB ARB5 point 5 knob edit SUCCESS\n");
|
||||
}
|
||||
|
||||
|
||||
/* ================================================================
|
||||
* RT_MATRIX_EDIT_ROT: absolute matrix rotation from keyboard angles
|
||||
@@ -465,6 +535,25 @@ bu_log("RT_MATRIX_EDIT_TRANS_MODEL_XYZ SUCCESS: "
|
||||
a->es_peqn[a->edit_menu][0], a->es_peqn[a->edit_menu][1],
|
||||
a->es_peqn[a->edit_menu][2], a->es_peqn[a->edit_menu][W]);
|
||||
|
||||
/* The same face operation must survive the interactive rotation knob
|
||||
* adapter, which supplies an incremental matrix rather than parameters.
|
||||
*/
|
||||
arb8_reset(s, arb, a);
|
||||
a->edit_menu = 4;
|
||||
s->e_inpara = 1;
|
||||
s->e_para[0] = 1.0;
|
||||
rt_edit_set_edflag(s, ECMD_ARB_SETUP_ROTFACE);
|
||||
rt_edit_process(s);
|
||||
plane_t knob_orig_peqn;
|
||||
HMOVE(knob_orig_peqn, a->es_peqn[a->edit_menu]);
|
||||
mat_t knob_rot;
|
||||
MAT_IDN(knob_rot);
|
||||
bn_mat_angles(knob_rot, 45.0, 0.0, 0.0);
|
||||
rt_knob_edit_rot(s, 'm', 'm', 0, knob_rot);
|
||||
if (VEQUAL(a->es_peqn[a->edit_menu], knob_orig_peqn))
|
||||
bu_exit(1, "ERROR: ECMD_ARB_ROTATE_FACE knob edit did not rotate face\n");
|
||||
bu_log("ECMD_ARB_ROTATE_FACE knob edit SUCCESS\n");
|
||||
|
||||
rt_edit_destroy(s);
|
||||
db_close(dbip);
|
||||
return 0;
|
||||
|
||||
Reference in new issue
Block a user