forked from bartvdbraak/blender
Fix #35368:
* Editing number of segments for particle hair did not update the viewport. * Hidden particles were confusing, the paths were drawn but without the points. Now it draws the path faded to indicate that they are hidden/locked. * Select tips/roots operators now have options to select/deselect/toggle/invert.
This commit is contained in:
parent
837d0ac2e0
commit
00f0ac8107
@ -1437,14 +1437,32 @@ class VIEW3D_MT_particle_specials(Menu):
|
|||||||
particle_edit = context.tool_settings.particle_edit
|
particle_edit = context.tool_settings.particle_edit
|
||||||
|
|
||||||
layout.operator("particle.rekey")
|
layout.operator("particle.rekey")
|
||||||
|
layout.operator("particle.delete")
|
||||||
|
layout.operator("particle.remove_doubles")
|
||||||
|
|
||||||
layout.separator()
|
|
||||||
if particle_edit.select_mode == 'POINT':
|
if particle_edit.select_mode == 'POINT':
|
||||||
layout.operator("particle.subdivide")
|
layout.operator("particle.subdivide")
|
||||||
|
|
||||||
|
layout.operator("particle.weight_set")
|
||||||
|
layout.separator()
|
||||||
|
|
||||||
|
layout.operator("particle.mirror")
|
||||||
|
|
||||||
|
if particle_edit.select_mode == 'POINT':
|
||||||
|
layout.separator()
|
||||||
layout.operator("particle.select_roots")
|
layout.operator("particle.select_roots")
|
||||||
layout.operator("particle.select_tips")
|
layout.operator("particle.select_tips")
|
||||||
|
|
||||||
layout.operator("particle.remove_doubles")
|
layout.separator()
|
||||||
|
|
||||||
|
layout.operator("particle.select_more")
|
||||||
|
layout.operator("particle.select_less")
|
||||||
|
|
||||||
|
layout.separator()
|
||||||
|
|
||||||
|
layout.operator("particle.select_all").action = 'TOGGLE'
|
||||||
|
layout.operator("particle.select_linked")
|
||||||
|
layout.operator("particle.select_all", text="Inverse").action = 'INVERT'
|
||||||
|
|
||||||
|
|
||||||
class VIEW3D_MT_particle_showhide(ShowHideMenu, Menu):
|
class VIEW3D_MT_particle_showhide(ShowHideMenu, Menu):
|
||||||
|
@ -376,6 +376,9 @@ typedef struct PEData {
|
|||||||
int invert;
|
int invert;
|
||||||
int tot;
|
int tot;
|
||||||
float vec[3];
|
float vec[3];
|
||||||
|
|
||||||
|
int select_action;
|
||||||
|
int select_toggle_action;
|
||||||
} PEData;
|
} PEData;
|
||||||
|
|
||||||
static void PE_set_data(bContext *C, PEData *data)
|
static void PE_set_data(bContext *C, PEData *data)
|
||||||
@ -1332,6 +1335,34 @@ static void toggle_key_select(PEData *data, int point_index, int key_index)
|
|||||||
|
|
||||||
/************************ de select all operator ************************/
|
/************************ de select all operator ************************/
|
||||||
|
|
||||||
|
static void select_action_apply(PTCacheEditPoint *point, PTCacheEditKey *key, int action)
|
||||||
|
{
|
||||||
|
switch (action) {
|
||||||
|
case SEL_SELECT:
|
||||||
|
if ((key->flag & PEK_SELECT) == 0) {
|
||||||
|
key->flag |= PEK_SELECT;
|
||||||
|
point->flag |= PEP_EDIT_RECALC;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SEL_DESELECT:
|
||||||
|
if (key->flag & PEK_SELECT) {
|
||||||
|
key->flag &= ~PEK_SELECT;
|
||||||
|
point->flag |= PEP_EDIT_RECALC;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SEL_INVERT:
|
||||||
|
if ((key->flag & PEK_SELECT) == 0) {
|
||||||
|
key->flag |= PEK_SELECT;
|
||||||
|
point->flag |= PEP_EDIT_RECALC;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
key->flag &= ~PEK_SELECT;
|
||||||
|
point->flag |= PEP_EDIT_RECALC;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int pe_select_all_exec(bContext *C, wmOperator *op)
|
static int pe_select_all_exec(bContext *C, wmOperator *op)
|
||||||
{
|
{
|
||||||
Scene *scene= CTX_data_scene(C);
|
Scene *scene= CTX_data_scene(C);
|
||||||
@ -1355,30 +1386,7 @@ static int pe_select_all_exec(bContext *C, wmOperator *op)
|
|||||||
|
|
||||||
LOOP_VISIBLE_POINTS {
|
LOOP_VISIBLE_POINTS {
|
||||||
LOOP_VISIBLE_KEYS {
|
LOOP_VISIBLE_KEYS {
|
||||||
switch (action) {
|
select_action_apply(point, key, action);
|
||||||
case SEL_SELECT:
|
|
||||||
if ((key->flag & PEK_SELECT) == 0) {
|
|
||||||
key->flag |= PEK_SELECT;
|
|
||||||
point->flag |= PEP_EDIT_RECALC;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case SEL_DESELECT:
|
|
||||||
if (key->flag & PEK_SELECT) {
|
|
||||||
key->flag &= ~PEK_SELECT;
|
|
||||||
point->flag |= PEP_EDIT_RECALC;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case SEL_INVERT:
|
|
||||||
if ((key->flag & PEK_SELECT) == 0) {
|
|
||||||
key->flag |= PEK_SELECT;
|
|
||||||
point->flag |= PEP_EDIT_RECALC;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
key->flag &= ~PEK_SELECT;
|
|
||||||
point->flag |= PEP_EDIT_RECALC;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1445,22 +1453,39 @@ int PE_mouse_particles(bContext *C, const int mval[2], bool extend, bool deselec
|
|||||||
return OPERATOR_FINISHED;
|
return OPERATOR_FINISHED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************ select first operator ************************/
|
/************************ select root operator ************************/
|
||||||
|
|
||||||
static void select_root(PEData *data, int point_index)
|
static void select_root(PEData *data, int point_index)
|
||||||
{
|
{
|
||||||
if (data->edit->points[point_index].flag & PEP_HIDE)
|
PTCacheEditPoint *point = data->edit->points + point_index;
|
||||||
|
PTCacheEditKey *key = point->keys;
|
||||||
|
|
||||||
|
if (point->flag & PEP_HIDE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
data->edit->points[point_index].keys->flag |= PEK_SELECT;
|
if (data->select_action != SEL_TOGGLE)
|
||||||
data->edit->points[point_index].flag |= PEP_EDIT_RECALC; /* redraw selection only */
|
select_action_apply(point, key, data->select_action);
|
||||||
|
else if (key->flag & PEK_SELECT)
|
||||||
|
data->select_toggle_action = SEL_DESELECT;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int select_roots_exec(bContext *C, wmOperator *UNUSED(op))
|
static int select_roots_exec(bContext *C, wmOperator *op)
|
||||||
{
|
{
|
||||||
PEData data;
|
PEData data;
|
||||||
|
int action = RNA_enum_get(op->ptr, "action");
|
||||||
|
|
||||||
PE_set_data(C, &data);
|
PE_set_data(C, &data);
|
||||||
|
|
||||||
|
if (action == SEL_TOGGLE) {
|
||||||
|
data.select_action = SEL_TOGGLE;
|
||||||
|
data.select_toggle_action = SEL_SELECT;
|
||||||
|
|
||||||
|
foreach_point(&data, select_root);
|
||||||
|
|
||||||
|
action = data.select_toggle_action;
|
||||||
|
}
|
||||||
|
|
||||||
|
data.select_action = action;
|
||||||
foreach_point(&data, select_root);
|
foreach_point(&data, select_root);
|
||||||
|
|
||||||
PE_update_selection(data.scene, data.ob, 1);
|
PE_update_selection(data.scene, data.ob, 1);
|
||||||
@ -1482,26 +1507,44 @@ void PARTICLE_OT_select_roots(wmOperatorType *ot)
|
|||||||
|
|
||||||
/* flags */
|
/* flags */
|
||||||
ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
|
ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||||
|
|
||||||
|
/* properties */
|
||||||
|
WM_operator_properties_select_action(ot, SEL_SELECT);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************ select last operator ************************/
|
/************************ select tip operator ************************/
|
||||||
|
|
||||||
static void select_tip(PEData *data, int point_index)
|
static void select_tip(PEData *data, int point_index)
|
||||||
{
|
{
|
||||||
PTCacheEditPoint *point = data->edit->points + point_index;
|
PTCacheEditPoint *point = data->edit->points + point_index;
|
||||||
|
PTCacheEditKey *key = &point->keys[point->totkey - 1];
|
||||||
|
|
||||||
if (point->flag & PEP_HIDE)
|
if (point->flag & PEP_HIDE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
point->keys[point->totkey - 1].flag |= PEK_SELECT;
|
if (data->select_action != SEL_TOGGLE)
|
||||||
point->flag |= PEP_EDIT_RECALC; /* redraw selection only */
|
select_action_apply(point, key, data->select_action);
|
||||||
|
else if (key->flag & PEK_SELECT)
|
||||||
|
data->select_toggle_action = SEL_DESELECT;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int select_tips_exec(bContext *C, wmOperator *UNUSED(op))
|
static int select_tips_exec(bContext *C, wmOperator *op)
|
||||||
{
|
{
|
||||||
PEData data;
|
PEData data;
|
||||||
|
int action = RNA_enum_get(op->ptr, "action");
|
||||||
|
|
||||||
PE_set_data(C, &data);
|
PE_set_data(C, &data);
|
||||||
|
|
||||||
|
if (action == SEL_TOGGLE) {
|
||||||
|
data.select_action = SEL_TOGGLE;
|
||||||
|
data.select_toggle_action = SEL_SELECT;
|
||||||
|
|
||||||
|
foreach_point(&data, select_tip);
|
||||||
|
|
||||||
|
action = data.select_toggle_action;
|
||||||
|
}
|
||||||
|
|
||||||
|
data.select_action = action;
|
||||||
foreach_point(&data, select_tip);
|
foreach_point(&data, select_tip);
|
||||||
|
|
||||||
PE_update_selection(data.scene, data.ob, 1);
|
PE_update_selection(data.scene, data.ob, 1);
|
||||||
@ -1523,6 +1566,9 @@ void PARTICLE_OT_select_tips(wmOperatorType *ot)
|
|||||||
|
|
||||||
/* flags */
|
/* flags */
|
||||||
ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
|
ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||||
|
|
||||||
|
/* properties */
|
||||||
|
WM_operator_properties_select_action(ot, SEL_SELECT);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************ select linked operator ************************/
|
/************************ select linked operator ************************/
|
||||||
|
@ -4785,11 +4785,10 @@ static void draw_ptcache_edit(Scene *scene, View3D *v3d, PTCacheEdit *edit)
|
|||||||
UI_GetThemeColor3fv(TH_VERTEX, nosel_col);
|
UI_GetThemeColor3fv(TH_VERTEX, nosel_col);
|
||||||
|
|
||||||
/* draw paths */
|
/* draw paths */
|
||||||
if (timed) {
|
steps = (*edit->pathcache)->steps + 1;
|
||||||
glEnable(GL_BLEND);
|
|
||||||
steps = (*edit->pathcache)->steps + 1;
|
glEnable(GL_BLEND);
|
||||||
pathcol = MEM_callocN(steps * 4 * sizeof(float), "particle path color data");
|
pathcol = MEM_callocN(steps * 4 * sizeof(float), "particle path color data");
|
||||||
}
|
|
||||||
|
|
||||||
glEnableClientState(GL_VERTEX_ARRAY);
|
glEnableClientState(GL_VERTEX_ARRAY);
|
||||||
glEnableClientState(GL_COLOR_ARRAY);
|
glEnableClientState(GL_COLOR_ARRAY);
|
||||||
@ -4804,11 +4803,19 @@ static void draw_ptcache_edit(Scene *scene, View3D *v3d, PTCacheEdit *edit)
|
|||||||
}
|
}
|
||||||
|
|
||||||
cache = edit->pathcache;
|
cache = edit->pathcache;
|
||||||
for (i = 0; i < totpoint; i++) {
|
for (i = 0, point = edit->points; i < totpoint; i++, point++) {
|
||||||
path = cache[i];
|
path = cache[i];
|
||||||
glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->co);
|
glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->co);
|
||||||
|
|
||||||
if (timed) {
|
if (point->flag & PEP_HIDE) {
|
||||||
|
for (k = 0, pcol = pathcol; k < steps; k++, pcol += 4) {
|
||||||
|
copy_v3_v3(pcol, path->col);
|
||||||
|
pcol[3] = 0.25f;
|
||||||
|
}
|
||||||
|
|
||||||
|
glColorPointer(4, GL_FLOAT, 4 * sizeof(float), pathcol);
|
||||||
|
}
|
||||||
|
else if (timed) {
|
||||||
for (k = 0, pcol = pathcol, pkey = path; k < steps; k++, pkey++, pcol += 4) {
|
for (k = 0, pcol = pathcol, pkey = path; k < steps; k++, pkey++, pcol += 4) {
|
||||||
copy_v3_v3(pcol, pkey->col);
|
copy_v3_v3(pcol, pkey->col);
|
||||||
pcol[3] = 1.0f - fabsf((float)(CFRA) -pkey->time) / (float)pset->fade_frames;
|
pcol[3] = 1.0f - fabsf((float)(CFRA) -pkey->time) / (float)pset->fade_frames;
|
||||||
|
@ -2294,7 +2294,7 @@ static void rna_def_particle_settings(BlenderRNA *brna)
|
|||||||
prop = RNA_def_property(srna, "hair_step", PROP_INT, PROP_NONE);
|
prop = RNA_def_property(srna, "hair_step", PROP_INT, PROP_NONE);
|
||||||
RNA_def_property_range(prop, 2, 50);
|
RNA_def_property_range(prop, 2, 50);
|
||||||
RNA_def_property_ui_text(prop, "Segments", "Number of hair segments");
|
RNA_def_property_ui_text(prop, "Segments", "Number of hair segments");
|
||||||
RNA_def_property_update(prop, 0, "rna_Particle_redo");
|
RNA_def_property_update(prop, 0, "rna_Particle_reset");
|
||||||
|
|
||||||
|
|
||||||
/*TODO: not found in UI, readonly? */
|
/*TODO: not found in UI, readonly? */
|
||||||
|
@ -243,6 +243,7 @@ void WM_operator_properties_gesture_border(struct wmOperatorType *ot, bool exte
|
|||||||
void WM_operator_properties_mouse_select(struct wmOperatorType *ot);
|
void WM_operator_properties_mouse_select(struct wmOperatorType *ot);
|
||||||
void WM_operator_properties_gesture_straightline(struct wmOperatorType *ot, bool cursor);
|
void WM_operator_properties_gesture_straightline(struct wmOperatorType *ot, bool cursor);
|
||||||
void WM_operator_properties_select_all(struct wmOperatorType *ot);
|
void WM_operator_properties_select_all(struct wmOperatorType *ot);
|
||||||
|
void WM_operator_properties_select_action(struct wmOperatorType *ot, int default_action);
|
||||||
|
|
||||||
bool WM_operator_check_ui_enabled(const struct bContext *C, const char *idname);
|
bool WM_operator_check_ui_enabled(const struct bContext *C, const char *idname);
|
||||||
wmOperator *WM_operator_last_redo(const struct bContext *C);
|
wmOperator *WM_operator_last_redo(const struct bContext *C);
|
||||||
|
@ -1109,9 +1109,9 @@ void WM_operator_properties_filesel(wmOperatorType *ot, int filter, short type,
|
|||||||
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
|
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WM_operator_properties_select_all(wmOperatorType *ot)
|
void WM_operator_properties_select_action(wmOperatorType *ot, int default_action)
|
||||||
{
|
{
|
||||||
static EnumPropertyItem select_all_actions[] = {
|
static EnumPropertyItem select_actions[] = {
|
||||||
{SEL_TOGGLE, "TOGGLE", 0, "Toggle", "Toggle selection for all elements"},
|
{SEL_TOGGLE, "TOGGLE", 0, "Toggle", "Toggle selection for all elements"},
|
||||||
{SEL_SELECT, "SELECT", 0, "Select", "Select all elements"},
|
{SEL_SELECT, "SELECT", 0, "Select", "Select all elements"},
|
||||||
{SEL_DESELECT, "DESELECT", 0, "Deselect", "Deselect all elements"},
|
{SEL_DESELECT, "DESELECT", 0, "Deselect", "Deselect all elements"},
|
||||||
@ -1119,7 +1119,12 @@ void WM_operator_properties_select_all(wmOperatorType *ot)
|
|||||||
{0, NULL, 0, NULL, NULL}
|
{0, NULL, 0, NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
RNA_def_enum(ot->srna, "action", select_all_actions, SEL_TOGGLE, "Action", "Selection action to execute");
|
RNA_def_enum(ot->srna, "action", select_actions, default_action, "Action", "Selection action to execute");
|
||||||
|
}
|
||||||
|
|
||||||
|
void WM_operator_properties_select_all(wmOperatorType *ot)
|
||||||
|
{
|
||||||
|
WM_operator_properties_select_action(ot, SEL_TOGGLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WM_operator_properties_border(wmOperatorType *ot)
|
void WM_operator_properties_border(wmOperatorType *ot)
|
||||||
|
Loading…
Reference in New Issue
Block a user